mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #27577 from maclover7/jm-fix-27547
Action Cable owns database connection, not Active Record
This commit is contained in:
commit
c07c708cf6
2 changed files with 47 additions and 8 deletions
|
@ -14,7 +14,7 @@ module ActionCable
|
||||||
end
|
end
|
||||||
|
|
||||||
def broadcast(channel, payload)
|
def broadcast(channel, payload)
|
||||||
with_connection do |pg_conn|
|
with_broadcast_connection do |pg_conn|
|
||||||
pg_conn.exec("NOTIFY #{pg_conn.escape_identifier(channel_identifier(channel))}, '#{pg_conn.escape_string(payload)}'")
|
pg_conn.exec("NOTIFY #{pg_conn.escape_identifier(channel_identifier(channel))}, '#{pg_conn.escape_string(payload)}'")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -31,14 +31,24 @@ module ActionCable
|
||||||
listener.shutdown
|
listener.shutdown
|
||||||
end
|
end
|
||||||
|
|
||||||
def with_connection(&block) # :nodoc:
|
def with_subscriptions_connection(&block) # :nodoc:
|
||||||
ActiveRecord::Base.connection_pool.with_connection do |ar_conn|
|
ar_conn = ActiveRecord::Base.connection_pool.checkout.tap do |conn|
|
||||||
|
# Action Cable is taking ownership over this database connection, and
|
||||||
|
# will perform the necessary cleanup tasks
|
||||||
|
ActiveRecord::Base.connection_pool.remove(conn)
|
||||||
|
end
|
||||||
pg_conn = ar_conn.raw_connection
|
pg_conn = ar_conn.raw_connection
|
||||||
|
|
||||||
unless pg_conn.is_a?(PG::Connection)
|
verify!(pg_conn)
|
||||||
raise "The Active Record database must be PostgreSQL in order to use the PostgreSQL Action Cable storage adapter"
|
yield pg_conn
|
||||||
|
ensure
|
||||||
|
ar_conn.disconnect!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_broadcast_connection(&block) # :nodoc:
|
||||||
|
ActiveRecord::Base.connection_pool.with_connection do |ar_conn|
|
||||||
|
pg_conn = ar_conn.raw_connection
|
||||||
|
verify!(pg_conn)
|
||||||
yield pg_conn
|
yield pg_conn
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -52,6 +62,12 @@ module ActionCable
|
||||||
@listener || @server.mutex.synchronize { @listener ||= Listener.new(self, @server.event_loop) }
|
@listener || @server.mutex.synchronize { @listener ||= Listener.new(self, @server.event_loop) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def verify!(pg_conn)
|
||||||
|
unless pg_conn.is_a?(PG::Connection)
|
||||||
|
raise "The Active Record database must be PostgreSQL in order to use the PostgreSQL Action Cable storage adapter"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class Listener < SubscriberMap
|
class Listener < SubscriberMap
|
||||||
def initialize(adapter, event_loop)
|
def initialize(adapter, event_loop)
|
||||||
super()
|
super()
|
||||||
|
@ -67,7 +83,7 @@ module ActionCable
|
||||||
end
|
end
|
||||||
|
|
||||||
def listen
|
def listen
|
||||||
@adapter.with_connection do |pg_conn|
|
@adapter.with_subscriptions_connection do |pg_conn|
|
||||||
catch :shutdown do
|
catch :shutdown do
|
||||||
loop do
|
loop do
|
||||||
until @queue.empty?
|
until @queue.empty?
|
||||||
|
|
|
@ -39,4 +39,27 @@ class PostgresqlAdapterTest < ActionCable::TestCase
|
||||||
def cable_config
|
def cable_config
|
||||||
{ adapter: "postgresql" }
|
{ adapter: "postgresql" }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_clear_active_record_connections_adapter_still_works
|
||||||
|
server = ActionCable::Server::Base.new
|
||||||
|
server.config.cable = cable_config.with_indifferent_access
|
||||||
|
server.config.logger = Logger.new(StringIO.new).tap { |l| l.level = Logger::UNKNOWN }
|
||||||
|
|
||||||
|
adapter_klass = Class.new(server.config.pubsub_adapter) do
|
||||||
|
def active?
|
||||||
|
!@listener.nil?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
adapter = adapter_klass.new(server)
|
||||||
|
|
||||||
|
subscribe_as_queue("channel", adapter) do |queue|
|
||||||
|
adapter.broadcast("channel", "hello world")
|
||||||
|
assert_equal "hello world", queue.pop
|
||||||
|
end
|
||||||
|
|
||||||
|
ActiveRecord::Base.clear_reloadable_connections!
|
||||||
|
|
||||||
|
assert adapter.active?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue