diff options
Diffstat (limited to 'actioncable/lib/action_cable')
7 files changed, 22 insertions, 98 deletions
diff --git a/actioncable/lib/action_cable/connection/client_socket.rb b/actioncable/lib/action_cable/connection/client_socket.rb index ba33c8b982..10289ab55c 100644 --- a/actioncable/lib/action_cable/connection/client_socket.rb +++ b/actioncable/lib/action_cable/connection/client_socket.rb @@ -21,7 +21,7 @@ module ActionCable return true if env["HTTP_X_FORWARDED_PROTO"] == "https" return true if env["rack.url_scheme"] == "https" - return false + false end CONNECTING = 0 diff --git a/actioncable/lib/action_cable/connection/subscriptions.rb b/actioncable/lib/action_cable/connection/subscriptions.rb index faafd6d0a6..bb8d64e27a 100644 --- a/actioncable/lib/action_cable/connection/subscriptions.rb +++ b/actioncable/lib/action_cable/connection/subscriptions.rb @@ -43,7 +43,7 @@ module ActionCable def remove(data) logger.info "Unsubscribing from channel: #{data['identifier']}" - remove_subscription subscriptions[data["identifier"]] + remove_subscription find(data) end def remove_subscription(subscription) diff --git a/actioncable/lib/action_cable/engine.rb b/actioncable/lib/action_cable/engine.rb index c961f47342..53cbb597cd 100644 --- a/actioncable/lib/action_cable/engine.rb +++ b/actioncable/lib/action_cable/engine.rb @@ -2,7 +2,7 @@ require "rails" require "action_cable" -require_relative "helpers/action_cable_helper" +require "action_cable/helpers/action_cable_helper" require "active_support/core_ext/hash/indifferent_access" module ActionCable diff --git a/actioncable/lib/action_cable/server/configuration.rb b/actioncable/lib/action_cable/server/configuration.rb index 82fed81a18..26209537df 100644 --- a/actioncable/lib/action_cable/server/configuration.rb +++ b/actioncable/lib/action_cable/server/configuration.rb @@ -25,13 +25,26 @@ module ActionCable # Also makes sure proper dependencies are required. def pubsub_adapter adapter = (cable.fetch("adapter") { "redis" }) + + # Require the adapter itself and give useful feedback about + # 1. Missing adapter gems and + # 2. Adapter gems' missing dependencies. path_to_adapter = "action_cable/subscription_adapter/#{adapter}" begin require path_to_adapter - rescue Gem::LoadError => e - raise Gem::LoadError, "Specified '#{adapter}' for Action Cable pubsub adapter, but the gem is not loaded. Add `gem '#{e.name}'` to your Gemfile (and ensure its version is at the minimum required by Action Cable)." rescue LoadError => e - raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/cable.yml is valid. If you use an adapter other than 'postgresql' or 'redis' add the necessary adapter gem to the Gemfile.", e.backtrace + # We couldn't require the adapter itself. Raise an exception that + # points out config typos and missing gems. + if e.path == path_to_adapter + # We can assume that a non-builtin adapter was specified, so it's + # either misspelled or missing from Gemfile. + raise e.class, "Could not load the '#{adapter}' Action Cable pubsub adapter. Ensure that the adapter is spelled correctly in config/cable.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace + + # Bubbled up from the adapter require. Prefix the exception message + # with some guidance about how to address it and reraise. + else + raise e.class, "Error loading the '#{adapter}' Action Cable pubsub adapter. Missing a gem it depends on? #{e.message}", e.backtrace + end end adapter = adapter.camelize diff --git a/actioncable/lib/action_cable/subscription_adapter/async.rb b/actioncable/lib/action_cable/subscription_adapter/async.rb index 96c18c4a2f..c9930299c7 100644 --- a/actioncable/lib/action_cable/subscription_adapter/async.rb +++ b/actioncable/lib/action_cable/subscription_adapter/async.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require_relative "inline" +require "action_cable/subscription_adapter/inline" module ActionCable module SubscriptionAdapter diff --git a/actioncable/lib/action_cable/subscription_adapter/evented_redis.rb b/actioncable/lib/action_cable/subscription_adapter/evented_redis.rb deleted file mode 100644 index 07774810ce..0000000000 --- a/actioncable/lib/action_cable/subscription_adapter/evented_redis.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: true - -require "thread" - -gem "em-hiredis", "~> 0.3.0" -gem "redis", "~> 3.0" -require "em-hiredis" -require "redis" - -EventMachine.epoll if EventMachine.epoll? -EventMachine.kqueue if EventMachine.kqueue? - -module ActionCable - module SubscriptionAdapter - class EventedRedis < Base # :nodoc: - prepend ChannelPrefix - - @@mutex = Mutex.new - - # Overwrite this factory method for EventMachine Redis connections if you want to use a different Redis connection library than EM::Hiredis. - # This is needed, for example, when using Makara proxies for distributed Redis. - cattr_accessor :em_redis_connector, default: ->(config) { EM::Hiredis.connect(config[:url]) } - - # Overwrite this factory method for Redis connections if you want to use a different Redis connection library than Redis. - # This is needed, for example, when using Makara proxies for distributed Redis. - cattr_accessor :redis_connector, default: ->(config) { ::Redis.new(url: config[:url]) } - - def initialize(*) - ActiveSupport::Deprecation.warn(<<-MSG.squish) - The "evented_redis" subscription adapter is deprecated and - will be removed in Rails 5.2. Please use the "redis" adapter - instead. - MSG - - super - @redis_connection_for_broadcasts = @redis_connection_for_subscriptions = nil - end - - def broadcast(channel, payload) - redis_connection_for_broadcasts.publish(channel, payload) - end - - def subscribe(channel, message_callback, success_callback = nil) - redis_connection_for_subscriptions.pubsub.subscribe(channel, &message_callback).tap do |result| - result.callback { |reply| success_callback.call } if success_callback - end - end - - def unsubscribe(channel, message_callback) - redis_connection_for_subscriptions.pubsub.unsubscribe_proc(channel, message_callback) - end - - def shutdown - redis_connection_for_subscriptions.pubsub.close_connection - @redis_connection_for_subscriptions = nil - end - - private - def redis_connection_for_subscriptions - ensure_reactor_running - @redis_connection_for_subscriptions || @server.mutex.synchronize do - @redis_connection_for_subscriptions ||= self.class.em_redis_connector.call(@server.config.cable).tap do |redis| - redis.on(:reconnect_failed) do - @logger.error "[ActionCable] Redis reconnect failed." - end - - redis.on(:failed) do - @logger.error "[ActionCable] Redis connection has failed." - end - end - end - end - - def redis_connection_for_broadcasts - @redis_connection_for_broadcasts || @server.mutex.synchronize do - @redis_connection_for_broadcasts ||= self.class.redis_connector.call(@server.config.cable) - end - end - - def ensure_reactor_running - return if EventMachine.reactor_running? && EventMachine.reactor_thread - @@mutex.synchronize do - Thread.new { EventMachine.run } unless EventMachine.reactor_running? - Thread.pass until EventMachine.reactor_running? && EventMachine.reactor_thread - end - end - end - end -end diff --git a/actioncable/lib/action_cable/subscription_adapter/redis.rb b/actioncable/lib/action_cable/subscription_adapter/redis.rb index facea944ff..c28951608f 100644 --- a/actioncable/lib/action_cable/subscription_adapter/redis.rb +++ b/actioncable/lib/action_cable/subscription_adapter/redis.rb @@ -2,7 +2,7 @@ require "thread" -gem "redis", "~> 3.0" +gem "redis", ">= 3", "< 5" require "redis" module ActionCable @@ -76,7 +76,7 @@ module ActionCable def listen(conn) conn.without_reconnect do - original_client = conn.client + original_client = conn.respond_to?(:_client) ? conn._client : conn.client conn.subscribe("_action_cable_internal") do |on| on.subscribe do |chan, count| |