-
Notifications
You must be signed in to change notification settings - Fork 131
Add Phoenix.PubSub.subscribe_once/3
#199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| @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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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. :)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be lovely!!! ❤️
|
Closing per the above. :) |
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 onsubscribe_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:
subscribe/3more than once by tracking subscriptions in their own process state, or by checkingRegistry.lookup/2directly (relying on an implementation detail of PubSub)unsubscribe/2each time before callingsubscribe/3