rails
rails copied to clipboard
[Bug][ActionCable/Zeitwerk] Code reloading doesn't close connections
Steps to reproduce
- Run a Rails application with ActionCable
- Use anything such as Javascript to connect to the channel
- Rails console will log in loop:
[#<MyChannel:0x000000013411e9c0>] Connection is active! - Refresh the browser, the thread is closed, the connection reopen and everything works as expected unless! you edit some code like add whitespace or new empty line or anything and refresh the browser. The rails console will now log twice as fast and you will notice it's coming from 2 different instances.
class MyChannelChannel < ApplicationCable::Channel
def subscribed
reject_subscription if params[:session_id].blank?
room_id = "web_ssh_#{params[:session_id]}"
stream_from room_id
@subscribed ||= Thread.new do
while streams.present?
Rails.logger.debug { "[#{self}] Connection is active!" }
sleep 1
end
end
end
def unsubscribed
@thread&.exit
end
end
Expected behavior
Editing the code should not prevent ActionCable from closing connections.
Actual behavior
It appears to not close connections
System configuration
rails (7.1.3.2)
actioncable (7.1.3.2)
zeitwerk (2.6.13)
Ruby version: 3.3.0
Extra info
If you're wondering why I am using a thread, it is because i'm opening a Net::SSH connection over an ActionCable connection. This gem requires to have a loop to call process in order to process things and work properly.
# self.ssh_client ||= Net::SSH.start(...)
# self.ssh_channel ||= ssh_client.open_channel do ... end
def open_connection_thread!
self.thread ||= Thread.new do
while ssh_channel.active? && streams.present?
ssh_client.process(0)
sleep 0.05 # Save CPU time
end
rescue StandardError
# Ignored
ensure
ssh_channel&.close
ssh_client&.close
end
end