Repository navigation
Use the PubSub.Sender behavior for fastlaning - #6869
Merged
Merged
Conversation
Channels now subscribe with a sender instead of fastlane metadata. Since nodes running Phoenix < 1.8.16 still expect channel broadcasts to use Phoenix.Channel.Server as dispatcher, we keep broadcasting with it and delegate its dispatch/3 to the default dispatching.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds PubSub
:sendersupport to 1.8.Channels now subscribe with a
Phoenix.PubSub.Sender, new in phoenix_pubsub 2.4, instead of{:fastlane, ...}metadata. Fastlaning moves out of thePhoenix.Channel.Server.dispatch/3dispatcher and intoPhoenix.Channel.Server.send/4. PubSub's default dispatching callssend/4once for each subscription.Applications see no difference at runtime:
handle_out/3.Phoenix.Channel.Serveras the dispatcher.This release prepares for 1.9, where channels stop passing a dispatcher. Without it, a rolling deploy from 1.8 to 1.9 crashes channels on the 1.8 nodes.
Why this is needed
Fastlaning depends on the dispatcher named when broadcasting
Today
init_join/3subscribes withmetadata: {:fastlane, transport_pid, serializer, intercepts}. OnlyPhoenix.Channel.Server.dispatch/3knows how to read that value, so every channel broadcast has to passPhoenix.Channel.Serveras the dispatcher.Sometimes another dispatcher handles the broadcast, for example with a plain
Phoenix.PubSub.broadcast/3or a default dispatcher configured on the PubSub. That dispatcher ignores the subscription value and sends the raw%Phoenix.Socket.Broadcast{}to the channel process.The channel process assumes it only receives broadcasts for intercepted events:
handle_info(%Broadcast{})always callshandle_out/3.handle_out/3.So every event that isn't intercepted crashes the channel. It raises
UndefinedFunctionError, orFunctionClauseErrorif the channel intercepts other events. The client rejoins, and the next broadcast crashes the channel again.phoenix_pubsub 2.4 deprecates custom dispatchers in favour of per-subscription senders, and in 1.9 we want channel broadcasts to use the default dispatching.
The dispatcher runs on the receiving node
A cluster broadcast carries the dispatcher as a module name:
{:forward_to_local, topic, message, dispatcher}. The receiving node runs its owndispatcher.dispatch/3against its own registry entries.Suppose 1.9 nodes broadcast with the default dispatcher while 1.8 nodes still have
{:fastlane, ...}subscriptions. The 1.8 nodes then hit exactly the crash described above:No change on the 1.9 side can fix this, because the code that fails is 1.8's. The 1.8 nodes have to subscribe in a way the default dispatching understands before 1.9 is rolled out. That's what this PR does.
What changes
phoenix_pubsub ~> 2.4becomes a requirement.init_join/3subscribes withsender: {Phoenix.Channel.Server, {transport_pid, serializer, intercepts}}.Phoenix.Channel.Server.send/4implements thePhoenix.PubSub.Senderbehaviour with the same logic as the olddispatch/3:Phoenix.Channel.Server.dispatch/3stays but hands off toPhoenix.PubSub.dispatch/3:Phoenix.Channel.Serverin their broadcasts.Phoenix.Channel.Server, both cluster-wide and local:Rolling deploy compatibility
Phoenix.Channel.Serverdispatch/3→PubSub.dispatch/3→send/4Phoenix.Channel.Serverdispatch/3Phoenix.Channel.Serverdispatch/3→PubSub.dispatch/3→send/4Phoenix.PubSubPubSub.dispatch/3→send/4Phoenix.PubSub%Broadcast{}→handle_out/3The last row is why the 1.9 changelog asks users to deploy 1.8.16 first. The upgrade path:
Side effect
A
%Phoenix.Socket.Broadcast{}published withPhoenix.PubSub.broadcast/3and no dispatcher now reaches channels correctly, through fastlane orhandle_out/3. Before, it crashed every channel on the topic that didn't intercept the event.Notes for users / changelog
mix deps.update phoenix phoenix_pubsub. Updating onlyphoenixkeeps the locked pubsub version, and Hex may stay on an earlier 1.8 release.subscribe(..., metadata: [atom | _]), because that shape now means a sender.{:fastlane, ...}subscriptions, which the new code doesn't read. Rolling restarts aren't affected.{:fastlane, ...}subscription value was internal. Custom dispatchers that matched on it won't see it any more.