Add configurable default dispatcher#208
Conversation
116f859 to
5395b6b
Compare
Adds a :dispatcher option to child_spec/start_link that sets the
default dispatcher module for all broadcast functions. Defaults to
Phoenix.PubSub (preserving existing behavior). Can be overridden
per-call by passing a dispatcher to broadcast/4 and friends.
{Phoenix.PubSub, name: :my_pubsub, dispatcher: MyApp.Dispatcher}
5395b6b to
541436a
Compare
|
This adds additional lookups on every invocation, which we want to avoid. Our suggestion is to wrap the pubsub API in another module that enforces your dispatcher. Thanks! |
|
@josevalim Understood, thanks for the quick feedback. I'll stick with the wrapper module approach and Credo rules to ensure we don't call Phoenix.PubSub directly. Too bad the meta pubsub isn't a map, could have been a single backward-compatible lookup. |
|
Wait, I believe the meta is private, so we can change it? Do you think that could work? |
|
@josevalim yeah as long as the value in |
|
That looks good to me! Please send a new PR! |
|
Apparently I cannot reopen this one :( |
Summary
Adds a
:dispatcheroption tochild_spec/start_linkthat sets the default dispatcher module for all broadcast functions. Defaults toPhoenix.PubSub(preserving existing behavior). Can be overridden per-call.Motivation
The custom dispatching feature is powerful, but in practice it's difficult to use as a default for an application. The current options are:
broadcastcallBoth add boilerplate for what is conceptually a per-PubSub configuration. The wrapper approach is particularly fragile. Any code that calls
Phoenix.PubSub.broadcast/3directly instead of going through the wrapper bypasses the custom dispatcher entirely. In a growing codebase with multiple contributors, this is easy to miss.The use case I ran into was filtering broadcasts in test environments, scoping delivery so that concurrent async tests sharing a topic don't leak messages to each other. A configurable default makes this a one-line change at startup rather than a module-level abstraction that every callsite must remember to use.
Trade-offs
The 3-arity broadcast functions (without an explicit dispatcher) now call
Registry.meta/2to look up the configured default. The 4-arity versions also callRegistry.meta/2for the adapter, so the 3-arity path makes two lookups total (one to get the default, one when delegating to the 4-arity head).Registry.metareads from:persistent_term, so this is a nanosecond-level cost. I don't believe it's meaningful, but wanted to call it out.Changes
Phoenix.PubSub.Supervisoraccepts:dispatcheroption, stores it in Registry metaThank you for Phoenix.PubSub. It's a great foundation and the dispatcher extension point was well designed. This just makes it a little easier to reach.