Skip to content

Conversation

@nathanl
Copy link
Contributor

@nathanl nathanl commented Jun 25, 2025

Given that the possibility of duplicate subscriptions was already discussed in the docs on subscribe/3, I assume there's a performance cost to checking for existing subscriptions that callers may not always want to pay. If so, I'd be happy to document that on subscribe_once/3. But it seems useful to have this function; I'm looking at a use case where the number of subscriptions to a topic won't be large but duplicate messages would be problematic.

Currently, any caller who wants to avoid duplicate subscriptions would need to use some kind of workaround, such as:

  • Avoid calling subscribe/3 more than once by tracking subscriptions in their own process state, or by checking Registry.lookup/2 directly (relying on an implementation detail of PubSub)
  • Call unsubscribe/2 each time before calling subscribe/3

@spec subscribe_once(t, topic, keyword) :: :ok | {:error, term}
def subscribe_once(pubsub, topic, opts \\ [])
when is_atom(pubsub) and is_binary(topic) and is_list(opts) do
subscriptions = Registry.lookup(pubsub, topic)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, I believe there is a race condition here. In betwen the Registry lookup and the else path, another process could have subscribed.

The only way this could work is by doing an insert_new operation to :ets

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you can only subscribe yourself, it cannot be a race condition. However, because this is a duplicate registry, there is basicaly no cheap way to check if you are already subscribed. If you have a topic with 100k entries, then this function will be very expensive because you are bringing a 100k elements list to memory, which is why we don't provide this functionality, it is basically an anti-pattern. So it is more scalable to guarantee code wise you won't subscribe multiple times. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a topic with 100k entries

Meaning 100k subscribers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given what you said, I'd like to do a followup docs PR to explain why the caller should guard against multiple subscriptions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be lovely!!! ❤️

@josevalim
Copy link
Member

Closing per the above. :)

@josevalim josevalim closed this Jan 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants