Allow Postgres to trigger readonly mode for the site.
This commit is contained in:
parent
c10a8d481d
commit
16408cee06
|
@ -89,6 +89,11 @@ class ApplicationController < ActionController::Base
|
|||
render_json_error I18n.t("rate_limiter.too_many_requests", time_left: time_left), type: :rate_limit, status: 429
|
||||
end
|
||||
|
||||
rescue_from PG::ReadOnlySqlTransaction do |e|
|
||||
Discourse.received_readonly!
|
||||
raise Discourse::ReadOnly
|
||||
end
|
||||
|
||||
rescue_from Discourse::NotLoggedIn do |e|
|
||||
raise e if Rails.env.test?
|
||||
|
||||
|
|
|
@ -93,6 +93,19 @@ module Discourse
|
|||
end
|
||||
end
|
||||
|
||||
def self.recently_readonly?
|
||||
return false unless @last_read_only
|
||||
@last_read_only > 15.seconds.ago
|
||||
end
|
||||
|
||||
def self.received_readonly!
|
||||
@last_read_only = Time.now
|
||||
end
|
||||
|
||||
def self.clear_readonly!
|
||||
@last_read_only = nil
|
||||
end
|
||||
|
||||
def self.disabled_plugin_names
|
||||
plugins.select {|p| !p.enabled?}.map(&:name)
|
||||
end
|
||||
|
@ -202,7 +215,7 @@ module Discourse
|
|||
end
|
||||
|
||||
def self.readonly_mode?
|
||||
DiscourseRedis.recently_readonly? || !!$redis.get(readonly_mode_key)
|
||||
recently_readonly? || !!$redis.get(readonly_mode_key)
|
||||
end
|
||||
|
||||
def self.request_refresh!
|
||||
|
|
|
@ -4,19 +4,6 @@
|
|||
require_dependency 'cache'
|
||||
class DiscourseRedis
|
||||
|
||||
def self.recently_readonly?
|
||||
return false unless @last_read_only
|
||||
@last_read_only > 15.seconds.ago
|
||||
end
|
||||
|
||||
def self.received_readonly!
|
||||
@last_read_only = Time.now
|
||||
end
|
||||
|
||||
def self.clear_readonly!
|
||||
@last_read_only = nil
|
||||
end
|
||||
|
||||
def self.raw_connection(config = nil)
|
||||
config ||= self.config
|
||||
redis_opts = {host: config['host'], port: config['port'], db: config['db']}
|
||||
|
@ -51,10 +38,10 @@ class DiscourseRedis
|
|||
yield
|
||||
rescue Redis::CommandError => ex
|
||||
if ex.message =~ /READONLY/
|
||||
unless DiscourseRedis.recently_readonly?
|
||||
unless Discourse.recently_readonly?
|
||||
STDERR.puts "WARN: Redis is in a readonly state. Performed a noop"
|
||||
end
|
||||
DiscourseRedis.received_readonly!
|
||||
Discourse.received_readonly!
|
||||
else
|
||||
raise ex
|
||||
end
|
||||
|
|
|
@ -106,11 +106,6 @@ describe Discourse do
|
|||
end
|
||||
|
||||
context "#readonly_mode?" do
|
||||
|
||||
after do
|
||||
DiscourseRedis.clear_readonly!
|
||||
end
|
||||
|
||||
it "is false by default" do
|
||||
expect(Discourse.readonly_mode?).to eq(false)
|
||||
end
|
||||
|
@ -120,8 +115,8 @@ describe Discourse do
|
|||
expect(Discourse.readonly_mode?).to eq(true)
|
||||
end
|
||||
|
||||
it "returns true when DiscourseRedis is recently read only" do
|
||||
DiscourseRedis.received_readonly!
|
||||
it "returns true when Discourse is recently read only" do
|
||||
Discourse.received_readonly!
|
||||
expect(Discourse.readonly_mode?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -114,7 +114,7 @@ describe TopicsController do
|
|||
end
|
||||
|
||||
it "returns a readonly header if the site is read only" do
|
||||
DiscourseRedis.received_readonly!
|
||||
Discourse.received_readonly!
|
||||
get :show, {topic_id: topic.id}
|
||||
expect(response.headers['Discourse-Readonly']).to eq('true')
|
||||
end
|
||||
|
|
|
@ -112,7 +112,7 @@ Spork.prefork do
|
|||
# very expensive IO operations
|
||||
SiteSetting.automatically_download_gravatars = false
|
||||
|
||||
DiscourseRedis.clear_readonly!
|
||||
Discourse.clear_readonly!
|
||||
|
||||
I18n.locale = :en
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue