class Rage::Cable::Router
def init_connection_class
def init_connection_class @connection_class = if Object.const_defined?("RageCable::Connection") RageCable::Connection elsif Object.const_defined?("ApplicationCable::Connection") ApplicationCable::Connection else puts "WARNING: Could not find the RageCable connection class! All connections will be accepted by default." Rage::Cable::Connection end end
def initialize
- Private: -
def initialize # Hash<String(channel name) => Proc(new channel instance)> @channels_map = {} init_connection_class end
def process_connection(connection)
-
(false)- if the connection was rejected -
(true)- if the connection was accepted
Parameters:
-
connection(Rage::Cable::WebSocketConnection) -- the connection object
def process_connection(connection) env = connection.env cable_connection = @connection_class.new(env) Rage::Telemetry.tracer.span_cable_connection_process(connection: cable_connection, action: :connect, env:) do cable_connection.connect end if cable_connection.rejected? Rage.logger.debug { "An unauthorized connection attempt was rejected" } else env["rage.identified_by"] = cable_connection.__identified_by_map env["rage.cable"] = {} end !cable_connection.rejected? end
def process_disconnection(connection)
-
connection(Rage::Cable::WebSocketConnection) -- the connection object
def process_disconnection(connection) env = connection.env env["rage.cable"]&.each do |_, channel| channel.__run_action(:unsubscribed) end cable_connection = @connection_class.new(env, env["rage.identified_by"]) Rage::Telemetry.tracer.span_cable_connection_process(connection: cable_connection, action: :disconnect, env:) do cable_connection.disconnect end end
def process_message(connection, identifier, action_name, data)
-
(:processed)- if the message has been successfully processed -
(:unknown_action)- if the action does not exist on the specified channel -
(:no_subscription)- if the client is not subscribed to the specified channel
Parameters:
-
data(Object) -- the data sent by the client -
action_name(Symbol) -- the name of the handler method -
identifier(String) -- the identifier of the subscription -
connection(Rage::Cable::WebSocketConnection) -- the connection object
def process_message(connection, identifier, action_name, data) channel = connection.env["rage.cable"][identifier] unless channel Rage.logger.debug { "Unable to find the subscription" } return :no_subscription end if channel.__has_action?(action_name) channel.__run_action(action_name, data) :processed else Rage.logger.debug { "Unable to process #{channel.class.name}##{action_name}" } :unknown_action end end
def process_subscription(connection, identifier, channel_name, params)
-
(:subscribed)- if the subscription was accepted -
(:rejected)- if the subscription was rejected -
(:invalid)- if the subscription class does not exist
Parameters:
-
params(Hash) -- the params hash associated with the subscription -
channel_name(String) -- the name of the channel class -
identifier(String) -- the identifier of the subscription -
connection(Rage::Cable::WebSocketConnection) -- the connection object
def process_subscription(connection, identifier, channel_name, params) channel_class = @channels_map[channel_name] || begin begin klass = Object.const_get(channel_name) rescue NameError nil end if klass.nil? || !klass.ancestors.include?(Rage::Cable::Channel) Rage.logger.debug { "Subscription class not found: #{channel_name}" } return :invalid end klass.__register_actions.tap do |available_actions| Rage.logger.debug { "Compiled #{channel_name}. Available remote actions: #{available_actions}." } end @channels_map[channel_name] = klass end channel = channel_class.new(connection, params, connection.env["rage.identified_by"]) channel.__run_action(:subscribed) if channel.subscription_rejected? Rage.logger.debug { "#{channel_name} is transmitting the subscription rejection" } # if the subscription is rejected in the `subscribed` method, ActionCable will additionally run # the `unsubscribed` method; this makes little sense to me as the client was never subscribed in # the first place; additionally, I don't think this behaviour is documented anywhere; # so, I'm going to leave this line commented out for now; # channel.__run_action(:unsubscribed) :rejected else Rage.logger.debug { "#{channel_name} is transmitting the subscription confirmation" } connection.env["rage.cable"][identifier] = channel :subscribed end end
def reset
- Private: -
def reset @channels_map.clear init_connection_class end