Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if there are subscriptions to a broadcast in turbo rails?

In my Rails view I’m using turbo_stream_from to subscribe to a turbo stream broadcast to display a list of patients:

<%= turbo_stream_from :all_patients %>

I want this list to be updated when a new patient is created, so I call:

constly_method
Turbo::StreamsChannel.broadcast_update_to(:all_patients,...)

However, I want to run this code only if there are any clients that are actually subscribed to :all_patients at the moment, because this code takes some computing resources. So, I want something like

if Turbo::StreamsChannel.broadcast_subscribed?(:all_patients)
  constly_method
  Turbo::StreamsChannel.broadcast_update_to(:all_patients,...)
end

Is there any way to check that?

like image 205
Evgenii Avatar asked Sep 18 '25 08:09

Evgenii


1 Answers

<%= turbo_stream_from "channel_name" %> # on one page
<%= turbo_stream_from User.first %>     # on another page

Redis keeps track of some of it:

>> redis = Redis.new

# active channels
>> channels = redis.pubsub("channels") 
=> ["Z2lkOi8vc3RhY2tvdmVyZmxvdy9Vc2VyLzE", "_action_cable_internal", "channel_name"]

# subscribers, which are ActionCable servers
>> redis.pubsub("numsub", channels)
=> ["Z2lkOi8vc3RhY2tvdmVyZmxvdy9Vc2VyLzE", 1, "_action_cable_internal", 1, "channel_name", 1]

Number of actual users connected, I don't think matters:

>> redis.pubsub("numsub", channels)
=> ["Z2lkOi8vc3RhY2tvdmVyZmxvdy9Vc2VyLzE", 0, "_action_cable_internal", 1, "channel_name", 1]
#                                          ^
# if i close user page, ActionCable disconnects from that channel

>> redis.pubsub("channels") 
=> ["_action_cable_internal", "channel_name"]

https://redis.io/commands/pubsub-channels/


This one only works per server instance and gives you the number of streams connected for each channel:

ActionCable.server.connections.flat_map do |conn|
  conn.subscriptions.send(:subscriptions).values
end.flat_map do |channel|
  # also streams seem to get stuck when code reloads in development
  # count goes up with every code change. must be a bug.
  channel.send(:streams).keys
end.tally
# => {"channel_name"=>4, "Z2lkOi8vc3RhY2tvdmVyZmxvdy9Vc2VyLzE"=>1}
like image 82
Alex Avatar answered Sep 21 '25 00:09

Alex