Fixed channel.destroy() not allowing the user to resubscribe #334
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.
I noticed that when you call
channel.destroy()
in the javascript client, it will unsubscribe from the channel, so the server will no longer send those channel events to the client, but it will not remove the channel from theWebSocketRails.channels
collection. Essentially what this means is that if you create a channel, callchannel.destroy()
, then attempt to recreate the channel, the dispatcher will give you back your original, now closed channel, and will not create a new one, meaning it will not re-subscribe to the channel, so the server will not send events to this client. This is a problem for me because I have multiple widgets on the screen controllable by the user, and each widget might subscribe to a channel, and destroys it's channel when it's removed, so if the user creates, removes, then creates the widget, it will not get any updates.I know a solution to this would be to use
WebSocketRails.unsubscribe()
instead ofchannel.destroy()
, and maybe it's just that I'm thinking about it wrong, but it seems to me that destroying the channel should free it up to be opened again.So I made it where instead of using a shared object for all the instances of a channel, every time you call dispatcher.subscribe, it will create a new channel object and add that to a pool of channels that it uses instead of a single channel, and if the pool is empty, calls the subscribe method to let the server know it wants to subscribe. If there is already something for that channel, it just adds it to the pool without telling the server about it. In addition, when you call
channel.destroy()
, instead of immediately unsubscribing from the server, it now tells the dispatcher to remove itself from the channels pool, and if it is the last one in the dispatchers channels pool, then the dispatcher will run the unsubscribe event and remove the channel's name from the channels object, allowing the user to resubscribe at a later time.This is useful for long running backbone style apps with lots of channels, where you don't want to bog down each page with all the events from every page that the user has visited so far this session, or maybe want to remove certain callbacks from a channel with an even name without removing all callbacks for that event name.
The only major downside to this is that it creates kind of a tight coupling between the channel and the dispatcher, but without moving the destroy channel function from the channel to the dispatcher I can't think of a way to loosen up on that.