-
Notifications
You must be signed in to change notification settings - Fork 330
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
Possible to detect Action Cable disconnections when using turbo_stream_from
?
#674
Comments
At the moment, I think the only way to "observe" connection state is to create a MutationObserver that observes the At least from the Unfortunately, there isn't an equivalent attribute on Dispatching an event (either a Similarly, events that communicate Action Cable subscription state changes could be just as valuable (separate from Turbo). It might be worthwhile to modify Action Cable's Consumer class to do so. |
I was able to rustle up a working solution for what I needed. It depends on the fact the turbo library bundled in turbo-rails exports a Here's a stimulus control that monkey-patches any existing subscriptions at import { Controller } from '@hotwired/stimulus'
import { cable } from '@hotwired/turbo-rails'
export default class CableWatcher extends Controller {
async connect () {
this.consumer = await cable.getConsumer()
this.subscriptionConnected = this.subscriptionConnected.bind(this)
this.subscriptionDisconnected = this.subscriptionDisconnected.bind(this)
this.subscriptionRejected = this.subscriptionRejected.bind(this)
this.#patchSubscriptions()
}
subscriptionConnected (identifier) {
this.dispatch('connected', { detail: { value: JSON.parse(identifier) } })
}
subscriptionDisconnected (identifier) {
this.dispatch('disconnected', { detail: { value: JSON.parse(identifier) } })
}
subscriptionRejected (identifier) {
this.dispatch('rejected', { detail: { value: JSON.parse(identifier) } })
}
// This will only patch subscriptions that are already connected,
// but any <%= turbo_stream_from %> tags should already have mounted by our connect() time
#patchSubscriptions () {
const self = this
this.consumer.subscriptions.subscriptions.forEach(subscription => {
const originalConnected = subscription.connected
const originalDisconnected = subscription.disconnected
const originalRejected = subscription.rejected
subscription.connected = function () {
originalConnected.call(this)
self.subscriptionConnected(this.identifier)
}
subscription.disconnected = function () {
originalDisconnected.call(this)
self.subscriptionDisconnected(this.identifier)
}
subscription.rejected = function () {
originalRejected.call(this)
self.subscriptionRejected(this.identifier)
}
})
}
} Then I can subscribe to it like this: data-action="cable-watcher:connected->my-controller#cableConnected cable-watcher:disconnected->my-controller#cableDisconnected cable-watcher:rejected->my-controller#cableDisconnected" And in those controller actions, I can get at the channel/subscriber ID: cableConnected (e) {
if (e.detail?.value?.channel === 'Turbo::StreamsChannel') {
console.log(e.detail.value.signed_stream_name)
}
}
cableDisconnected (e) {
if (e.detail?.value?.channel === 'Turbo::StreamsChannel') {
console.log(e.detail.value.signed_stream_name)
}
} I'm using this to set up an interval polling fallback whenever the cable disconnects until it reconnects. It'd be super cool if the library could handle this kind of plumbing for users somewhere or other, simply because relying on broadcasts can lead to some really goofy state problems if it disconnects intermittently |
I'm using the turbo_stream_from helper to subscribe to Action Cable on a page that receives Turbo Stream broadcasts. One major issue, though, is that I have no idea when broadcasts aren't being received. I'd (ideally) like to be notified when they are with a JavaScript event, but I'd even be happy with a way to introspect the Cable connection, either via the Turbo or the Action Cable JS libraries.
Is this possible, or would I have to roll my own cable subscription outside Turbo to be able to do this?
The text was updated successfully, but these errors were encountered: