Make PostgreSQL failover work with distributed cache.

This commit is contained in:
Guo Xiang Tan 2017-10-20 16:39:31 +08:00
parent 989280a222
commit fe1e78ddf4
4 changed files with 20 additions and 8 deletions

View File

@ -7,10 +7,12 @@ class PostgreSQLFallbackHandler
include Singleton
attr_reader :masters_down
attr_accessor :initialized
def initialize
@masters_down = DistributedCache.new('masters_down')
@masters_down = DistributedCache.new('masters_down', namespace: false)
@mutex = Mutex.new
@initialized = false
end
def verify_master
@ -126,13 +128,12 @@ module ActiveRecord
else
begin
connection = postgresql_connection(config)
fallback_handler.master_down = false
fallback_handler.initialized ||= true
rescue PG::ConnectionBad => e
on_boot = fallback_handler.master_down?.nil?
fallback_handler.master_down = true
fallback_handler.verify_master
if on_boot
if !fallback_handler.initialized
return postgresql_fallback_connection(config)
else
raise e

View File

@ -105,10 +105,11 @@ class DistributedCache
attr_reader :key
def initialize(key, manager = nil)
def initialize(key, manager: nil, namespace: true)
@key = key
@data = {}
@manager = manager || DistributedCache.default_manager
@namespace = namespace
@manager.ensure_subscribe!
@manager.register(self)
@ -142,7 +143,14 @@ class DistributedCache
end
def hash(db = nil)
db ||= RailsMultisite::ConnectionManagement.current_db
db ||= begin
if @namespace
RailsMultisite::ConnectionManagement.current_db
else
RailsMultisite::ConnectionManagement::DEFAULT
end
end
@data[db] ||= ThreadSafe::Hash.new
end

View File

@ -62,6 +62,7 @@ describe ActiveRecord::ConnectionHandling do
it 'should failover to a replica server' do
RailsMultisite::ConnectionManagement.stubs(:all_dbs).returns(['default', multisite_db])
postgresql_fallback_handler.expects(:verify_master).at_least(3)
[config, multisite_config].each do |configuration|
ActiveRecord::Base.expects(:postgresql_connection).with(configuration).raises(PG::ConnectionBad)
@ -113,13 +114,15 @@ describe ActiveRecord::ConnectionHandling do
context 'when both master and replica server is down' do
it 'should raise the right error' do
ActiveRecord::Base.expects(:postgresql_connection).with(config).raises(PG::ConnectionBad).once
ActiveRecord::Base.expects(:postgresql_connection).with(config).raises(PG::ConnectionBad)
ActiveRecord::Base.expects(:postgresql_connection).with(config.dup.merge(
host: replica_host,
port: replica_port
)).raises(PG::ConnectionBad).once
postgresql_fallback_handler.expects(:verify_master).twice
2.times do
expect { ActiveRecord::Base.postgresql_fallback_connection(config) }
.to raise_error(PG::ConnectionBad)

View File

@ -14,7 +14,7 @@ describe DistributedCache do
end
def cache(name)
DistributedCache.new(name, @manager)
DistributedCache.new(name, manager: @manager)
end
let! :cache1 do