Class: ActionCable::Server::Base

Inherits:
Object
  • Object
show all
Includes:
Broadcasting, Connections
Defined in:
lib/action_cable/server/base.rb

Overview

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.

Constant Summary

Constants included from Connections

Connections::BEAT_INTERVAL

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Connections

#add_connection, #connections, #open_connections_statistics, #remove_connection, #setup_heartbeat_timer

Methods included from Broadcasting

#broadcast, #broadcaster_for

Constructor Details

#initializeBase

Returns a new instance of Base.



20
21
22
23
# File 'lib/action_cable/server/base.rb', line 20

def initialize
  @mutex = Monitor.new
  @remote_connections = @event_loop = @worker_pool = @pubsub = nil
end

Instance Attribute Details

#mutexObject (readonly)

Returns the value of attribute mutex.



18
19
20
# File 'lib/action_cable/server/base.rb', line 18

def mutex
  @mutex
end

Class Method Details

.loggerObject



15
# File 'lib/action_cable/server/base.rb', line 15

def self.logger; config.logger; end

Instance Method Details

#call(env) ⇒ Object

Called by Rack to setup the server.



26
27
28
29
# File 'lib/action_cable/server/base.rb', line 26

def call(env)
  setup_heartbeat_timer
  config.connection_class.call.new(self, env).process
end

#connection_identifiersObject

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



80
81
82
# File 'lib/action_cable/server/base.rb', line 80

def connection_identifiers
  config.connection_class.call.identifiers
end

#disconnect(identifiers) ⇒ Object

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



32
33
34
# File 'lib/action_cable/server/base.rb', line 32

def disconnect(identifiers)
  remote_connections.where(identifiers).disconnect
end

#event_loopObject



55
56
57
# File 'lib/action_cable/server/base.rb', line 55

def event_loop
  @event_loop || @mutex.synchronize { @event_loop ||= config.event_loop_class.new }
end

#pubsubObject

Adapter used for all streams/broadcasting.



75
76
77
# File 'lib/action_cable/server/base.rb', line 75

def pubsub
  @pubsub || @mutex.synchronize { @pubsub ||= config.pubsub_adapter.new(self) }
end

#remote_connectionsObject

Gateway to RemoteConnections. See that class for details.



51
52
53
# File 'lib/action_cable/server/base.rb', line 51

def remote_connections
  @remote_connections || @mutex.synchronize { @remote_connections ||= RemoteConnections.new(self) }
end

#restartObject



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/action_cable/server/base.rb', line 36

def restart
  connections.each(&:close)

  @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

#worker_poolObject

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 db connection pool and block while they wait for other workers to release their connections. Use a smaller worker pool or a larger db connection pool instead.



70
71
72
# File 'lib/action_cable/server/base.rb', line 70

def worker_pool
  @worker_pool || @mutex.synchronize { @worker_pool ||= ActionCable::Server::Worker.new(max_size: config.worker_pool_size) }
end