mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Extract Server configuration into a Configuration object
This commit is contained in:
parent
44e7cc324d
commit
b8b50e6b04
7 changed files with 82 additions and 35 deletions
|
@ -117,7 +117,7 @@ module ActionCable
|
||||||
# Tags are declared in the server but computed in the connection. This allows us per-connection tailored tags.
|
# Tags are declared in the server but computed in the connection. This allows us per-connection tailored tags.
|
||||||
def new_tagged_logger
|
def new_tagged_logger
|
||||||
TaggedLoggerProxy.new server.logger,
|
TaggedLoggerProxy.new server.logger,
|
||||||
tags: server.log_tags.map { |tag| tag.respond_to?(:call) ? tag.call(request) : tag.to_s.camelize }
|
tags: server.config.log_tags.map { |tag| tag.respond_to?(:call) ? tag.call(request) : tag.to_s.camelize }
|
||||||
end
|
end
|
||||||
|
|
||||||
def started_request_message
|
def started_request_message
|
||||||
|
|
|
@ -22,8 +22,8 @@ module ActionCable
|
||||||
id_key = data['identifier']
|
id_key = data['identifier']
|
||||||
id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access
|
id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access
|
||||||
|
|
||||||
subscription_klass = connection.server.registered_channels.detect do |channel_klass|
|
subscription_klass = connection.server.channel_classes.detect do |channel_class|
|
||||||
channel_klass == id_options[:channel].safe_constantize
|
channel_class == id_options[:channel].safe_constantize
|
||||||
end
|
end
|
||||||
|
|
||||||
if subscription_klass
|
if subscription_klass
|
||||||
|
|
|
@ -3,6 +3,7 @@ module ActionCable
|
||||||
autoload :Base, 'action_cable/server/base'
|
autoload :Base, 'action_cable/server/base'
|
||||||
autoload :Broadcasting, 'action_cable/server/broadcasting'
|
autoload :Broadcasting, 'action_cable/server/broadcasting'
|
||||||
autoload :Connections, 'action_cable/server/connections'
|
autoload :Connections, 'action_cable/server/connections'
|
||||||
|
autoload :Configuration, 'action_cable/server/configuration'
|
||||||
autoload :Worker, 'action_cable/server/worker'
|
autoload :Worker, 'action_cable/server/worker'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,43 +4,26 @@ module ActionCable
|
||||||
include ActionCable::Server::Broadcasting
|
include ActionCable::Server::Broadcasting
|
||||||
include ActionCable::Server::Connections
|
include ActionCable::Server::Connections
|
||||||
|
|
||||||
cattr_accessor(:logger, instance_reader: true) { Rails.logger }
|
cattr_accessor(:config, instance_accessor: true) { ActionCable::Server::Configuration.new }
|
||||||
|
|
||||||
|
def self.logger; config.logger; end
|
||||||
|
delegate :logger, to: :config
|
||||||
|
|
||||||
attr_accessor :registered_channels, :redis_config, :log_tags
|
def initialize
|
||||||
|
|
||||||
def initialize(redis_config:, channels:, worker_pool_size: 100, connection: Connection, log_tags: [ 'ActionCable' ])
|
|
||||||
@redis_config = redis_config.with_indifferent_access
|
|
||||||
@registered_channels = Set.new(channels)
|
|
||||||
@worker_pool_size = worker_pool_size
|
|
||||||
@connection_class = connection
|
|
||||||
@log_tags = log_tags
|
|
||||||
|
|
||||||
@connections = []
|
|
||||||
|
|
||||||
logger.info "[ActionCable] Initialized server (redis_config: #{@redis_config.inspect}, worker_pool_size: #{@worker_pool_size})"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
@connection_class.new(self, env).process
|
config.connection_class.new(self, env).process
|
||||||
end
|
end
|
||||||
|
|
||||||
def worker_pool
|
def worker_pool
|
||||||
@worker_pool ||= ActionCable::Server::Worker.pool(size: @worker_pool_size)
|
@worker_pool ||= ActionCable::Server::Worker.pool(size: config.worker_pool_size)
|
||||||
end
|
end
|
||||||
|
|
||||||
def pubsub
|
def channel_classes
|
||||||
@pubsub ||= redis.pubsub
|
@channel_classes ||= begin
|
||||||
end
|
config.channel_paths.each { |channel_path| require channel_path }
|
||||||
|
config.channel_class_names.collect { |name| name.constantize }
|
||||||
def redis
|
|
||||||
@redis ||= begin
|
|
||||||
redis = EM::Hiredis.connect(@redis_config[:url])
|
|
||||||
redis.on(:reconnect_failed) do
|
|
||||||
logger.info "[ActionCable] Redis reconnect failed."
|
|
||||||
# logger.info "[ActionCable] Redis reconnected. Closing all the open connections."
|
|
||||||
# @connections.map &:close
|
|
||||||
end
|
|
||||||
redis
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,10 +31,22 @@ module ActionCable
|
||||||
@remote_connections ||= RemoteConnections.new(self)
|
@remote_connections ||= RemoteConnections.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def connection_identifiers
|
def pubsub
|
||||||
@connection_class.identifiers
|
@pubsub ||= redis.pubsub
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def redis
|
||||||
|
@redis ||= EM::Hiredis.connect(config.redis[:url]).tap do |redis|
|
||||||
|
redis.on(:reconnect_failed) do
|
||||||
|
logger.info "[ActionCable] Redis reconnect failed."
|
||||||
|
# logger.info "[ActionCable] Redis reconnected. Closing all the open connections."
|
||||||
|
# @connections.map &:close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def connection_identifiers
|
||||||
|
config.connection_class.identifiers
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ module ActionCable
|
||||||
end
|
end
|
||||||
|
|
||||||
def broadcasting_redis
|
def broadcasting_redis
|
||||||
@broadcasting_redis ||= Redis.new(redis_config)
|
@broadcasting_redis ||= Redis.new(config.redis)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
51
lib/action_cable/server/configuration.rb
Normal file
51
lib/action_cable/server/configuration.rb
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
module ActionCable
|
||||||
|
module Server
|
||||||
|
class Configuration
|
||||||
|
attr_accessor :logger, :log_tags
|
||||||
|
attr_accessor :connection_class, :worker_pool_size
|
||||||
|
attr_accessor :redis_path, :channels_path
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@logger = Rails.logger
|
||||||
|
@log_tags = []
|
||||||
|
|
||||||
|
@connection_class = ApplicationCable::Connection
|
||||||
|
@worker_pool_size = 100
|
||||||
|
|
||||||
|
@redis_path = Rails.root.join('config/redis/cable.yml')
|
||||||
|
@channels_path = Rails.root.join('app/channels')
|
||||||
|
end
|
||||||
|
|
||||||
|
def channel_paths
|
||||||
|
@channels ||= Dir["#{channels_path}/**/*_channel.rb"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def channel_class_names
|
||||||
|
@channel_class_names ||= channel_paths.collect do |channel_path|
|
||||||
|
Pathname.new(channel_path).basename.to_s.split('.').first.camelize
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def redis
|
||||||
|
@redis ||= config_for(redis_path).with_indifferent_access
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# FIXME: Extract this from Rails::Application in a way it can be used here.
|
||||||
|
def config_for(path)
|
||||||
|
if path.exist?
|
||||||
|
require "yaml"
|
||||||
|
require "erb"
|
||||||
|
(YAML.load(ERB.new(path.read).result) || {})[Rails.env] || {}
|
||||||
|
else
|
||||||
|
raise "Could not load configuration. No such file - #{path}"
|
||||||
|
end
|
||||||
|
rescue Psych::SyntaxError => e
|
||||||
|
raise "YAML syntax error occurred while parsing #{path}. " \
|
||||||
|
"Please note that YAML must be consistently indented using spaces. Tabs are not allowed. " \
|
||||||
|
"Error: #{e.message}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -17,7 +17,7 @@ class ServerTest < ActionCableTest
|
||||||
end
|
end
|
||||||
|
|
||||||
test "channel registration" do
|
test "channel registration" do
|
||||||
assert_equal ChatServer.registered_channels, Set.new([ ChatChannel ])
|
assert_equal ChatServer.channel_classes, Set.new([ ChatChannel ])
|
||||||
end
|
end
|
||||||
|
|
||||||
test "subscribing to a channel with valid params" do
|
test "subscribing to a channel with valid params" do
|
||||||
|
|
Loading…
Reference in a new issue