Action Cable Server Base

A singleton ActionCable::Server instance is available via ActionCable.server. It’s used by the Rack process that starts the Action Cable server, but is also used by the user to reach the RemoteConnections object, which is used for finding and disconnecting connections across all servers.

Also, this is the server instance used for broadcasting. See Broadcasting for more information.

Methods

Included Modules

Attributes

[R] config
[R] mutex

Class Public methods

logger()

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 26
      def self.logger; config.logger; end
πŸ”Ž See on GitHub

new(config: self.class.config)

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 31
      def initialize(config: self.class.config)
        @config = config
        @mutex = Monitor.new
        @remote_connections = @event_loop = @worker_pool = @pubsub = nil
      end
πŸ”Ž See on GitHub

Instance Public methods

call(env)

Called by Rack to set up the server.

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 38
      def call(env)
        return config.health_check_application.call(env) if env["PATH_INFO"] == config.health_check_path
        setup_heartbeat_timer
        config.connection_class.call.new(self, env).process
      end
πŸ”Ž See on GitHub

connection_identifiers()

All of the identifiers applied to the connection class associated with this server.

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 102
      def connection_identifiers
        config.connection_class.call.identifiers
      end
πŸ”Ž See on GitHub

disconnect(identifiers)

Disconnect all the connections identified by identifiers on this server or any others via RemoteConnections.

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 46
      def disconnect(identifiers)
        remote_connections.where(identifiers).disconnect
      end
πŸ”Ž See on GitHub

event_loop()

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 71
      def event_loop
        @event_loop || @mutex.synchronize { @event_loop ||= ActionCable::Connection::StreamEventLoop.new }
      end
πŸ”Ž See on GitHub

pubsub()

Adapter used for all streams/broadcasting.

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 96
      def pubsub
        @pubsub || @mutex.synchronize { @pubsub ||= config.pubsub_adapter.new(self) }
      end
πŸ”Ž See on GitHub

remote_connections()

Gateway to RemoteConnections. See that class for details.

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 67
      def remote_connections
        @remote_connections || @mutex.synchronize { @remote_connections ||= RemoteConnections.new(self) }
      end
πŸ”Ž See on GitHub

restart()

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 50
      def restart
        connections.each do |connection|
          connection.close(reason: ActionCable::INTERNAL[:disconnect_reasons][:server_restart])
        end

        @mutex.synchronize do
          # Shutdown the worker pool
          @worker_pool.halt if @worker_pool
          @worker_pool = nil

          # Shutdown the pub/sub adapter
          @pubsub.shutdown if @pubsub
          @pubsub = nil
        end
      end
πŸ”Ž See on GitHub

worker_pool()

The worker pool is where we run connection callbacks and channel actions. We do as little as possible on the server’s main thread. The worker pool is an executor service that’s backed by a pool of threads working from a task queue. The thread pool size maxes out at 4 worker threads by default. Tune the size yourself with config.action_cable.worker_pool_size.

Using Active Record, Redis, etc within your channel actions means you’ll get a separate connection from each thread in the worker pool. Plan your deployment accordingly: 5 servers each running 5 Puma workers each running an 8-thread worker pool means at least 200 database connections.

Also, ensure that your database connection pool size is as least as large as your worker pool size. Otherwise, workers may oversubscribe the database connection pool and block while they wait for other workers to release their connections. Use a smaller worker pool or a larger database connection pool instead.

πŸ“ Source code
# File actioncable/lib/action_cable/server/base.rb, line 91
      def worker_pool
        @worker_pool || @mutex.synchronize { @worker_pool ||= ActionCable::Server::Worker.new(max_size: config.worker_pool_size) }
      end
πŸ”Ž See on GitHub