Skip to content
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

Fix unsubscribed server side behavior #23715

Merged
merged 1 commit into from
Feb 19, 2016
Merged

Conversation

maclover7
Copy link
Contributor

Closes #23708

Before this commit, the unsubscribed callbacks in Action Cable server
side channels were never called. This is because when a WebSocket
"goodbye" message was sent from the client, the Action Cable server
didn't properly clean up after the now closed WebSocket. This means that
memory could possibly skyrocket with this behavior, since part of this
commit is to properly remove closed subscriptions from the global
subscriptions hash. Say you have 10,000 users currently connected, and
then all 10,000 disconnect -- before this patch, Action Cable would
still hold onto information (and Ruby objects!) for all of these now
dead connections.

cc @dhh @matthewd

@jeremy
Copy link
Member

jeremy commented Feb 17, 2016

Good catch. Test coverage to demonstrate the expected behavior?

@maclover7
Copy link
Contributor Author

Was working on this earlier, but added a regression test to show the expected behavior. cc @matthewd since we talked about this in Campfire.

c.send_message command: 'subscribe', identifier: JSON.dump(channel: 'EchoChannel')
assert_equal({"identifier"=>"{\"channel\":\"EchoChannel\"}", "type"=>"confirm_subscription"}, c.read_message)
assert_equal(1, app.connections.count)
assert_equal(1, app.connections.first.subscriptions.method(:subscriptions).call.count)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is ugly (and definitely not public API), but is still necessary to demonstrate the regression test.

@maclover7
Copy link
Contributor Author

@jeremy updated with regression test - all set to go?

@@ -54,7 +54,7 @@ def identifiers
end

def unsubscribe_from_all
subscriptions.each { |id, channel| channel.unsubscribe_from_channel }
subscriptions.each { |id, channel| remove({ 'identifier' => id }) }
Copy link
Member

Choose a reason for hiding this comment

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

Can we use remove_subscription(channel) here? This feels like unnecessary indirection (and I think I'd actually argue we don't want the log lines).

@maclover7 maclover7 force-pushed the fix-unsubscribe branch 3 times, most recently from 97dc23c to 0402df5 Compare February 18, 2016 21:13
Before this commit, the `unsubscribed` callbacks in Action Cable server
side channels were never called. This is because when a WebSocket
"goodbye" message was sent from the client, the Action Cable server
didn't properly clean up after the now closed WebSocket. This means that
memory could possibly skyrocket with this behavior, since part of this
commit is to properly remove closed subscriptions from the global
subscriptions hash. Say you have 10,000 users currently connected, and
then all 10,000 disconnect -- before this patch, Action Cable would
still hold onto information (and Ruby objects!) for all of these now
dead connections.
matthewd added a commit that referenced this pull request Feb 19, 2016
Fix `unsubscribed` server side behavior
@matthewd matthewd merged commit 6da571a into rails:master Feb 19, 2016
@maclover7 maclover7 deleted the fix-unsubscribe branch February 19, 2016 00:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ActionCable disconnect client
3 participants