Use a different Redis key when PG failover sets site to readonly mode.

This commit is contained in:
Guo Xiang Tan
2017-01-11 16:38:07 +08:00
parent 77045eb1f1
commit cdd550e947
5 changed files with 56 additions and 36 deletions

View File

@ -113,24 +113,6 @@ module Discourse
end
end
def self.last_read_only
@last_read_only ||= {}
end
def self.recently_readonly?
read_only = last_read_only[$redis.namespace]
return false unless read_only
read_only > 15.seconds.ago
end
def self.received_readonly!
last_read_only[$redis.namespace] = Time.zone.now
end
def self.clear_readonly!
last_read_only[$redis.namespace] = nil
end
def self.disabled_plugin_names
plugins.select { |p| !p.enabled? }.map(&:name)
end
@ -212,41 +194,67 @@ module Discourse
READONLY_MODE_KEY_TTL ||= 60
READONLY_MODE_KEY ||= 'readonly_mode'.freeze
PG_READONLY_MODE_KEY ||= 'readonly_mode:postgres'.freeze
USER_READONLY_MODE_KEY ||= 'readonly_mode:user'.freeze
def self.enable_readonly_mode(user_enabled: false)
if user_enabled
$redis.set(USER_READONLY_MODE_KEY, 1)
READONLY_KEYS = [
READONLY_MODE_KEY,
PG_READONLY_MODE_KEY,
USER_READONLY_MODE_KEY
]
def self.enable_readonly_mode(key = READONLY_MODE_KEY)
if key == USER_READONLY_MODE_KEY
$redis.set(key, 1)
else
$redis.setex(READONLY_MODE_KEY, READONLY_MODE_KEY_TTL, 1)
keep_readonly_mode
$redis.setex(key, READONLY_MODE_KEY_TTL, 1)
keep_readonly_mode(key)
end
MessageBus.publish(readonly_channel, true)
true
end
def self.keep_readonly_mode
def self.keep_readonly_mode(key)
# extend the expiry by 1 minute every 30 seconds
unless Rails.env.test?
Thread.new do
while readonly_mode?
$redis.expire(READONLY_MODE_KEY, READONLY_MODE_KEY_TTL)
$redis.expire(key, READONLY_MODE_KEY_TTL)
sleep 30.seconds
end
end
end
end
def self.disable_readonly_mode(user_enabled: false)
key = user_enabled ? USER_READONLY_MODE_KEY : READONLY_MODE_KEY
def self.disable_readonly_mode(key = READONLY_MODE_KEY)
$redis.del(key)
MessageBus.publish(readonly_channel, false)
true
end
def self.readonly_mode?
recently_readonly? || !!$redis.get(READONLY_MODE_KEY) || !!$redis.get(USER_READONLY_MODE_KEY)
return true if recently_readonly?
READONLY_KEYS.each { |key| return true if !!$redis.get(key) }
false
end
def self.last_read_only
@last_read_only ||= {}
end
def self.recently_readonly?
read_only = last_read_only[$redis.namespace]
return false unless read_only
read_only > 15.seconds.ago
end
def self.received_readonly!
last_read_only[$redis.namespace] = Time.zone.now
end
def self.clear_readonly!
last_read_only[$redis.namespace] = nil
end
def self.request_refresh!