From 16408cee06935890f4a02cfcef1e3d7237627e87 Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Wed, 29 Apr 2015 11:49:58 -0400 Subject: [PATCH] Allow Postgres to trigger readonly mode for the site. --- app/controllers/application_controller.rb | 5 +++++ lib/discourse.rb | 15 ++++++++++++++- lib/discourse_redis.rb | 17 ++--------------- spec/components/discourse_spec.rb | 9 ++------- spec/controllers/application_controller_spec.rb | 2 +- spec/spec_helper.rb | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index bfe6462ff8b..1c9bdbbd8ef 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -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? diff --git a/lib/discourse.rb b/lib/discourse.rb index b4527dfd068..44d708e2a5e 100644 --- a/lib/discourse.rb +++ b/lib/discourse.rb @@ -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! diff --git a/lib/discourse_redis.rb b/lib/discourse_redis.rb index b0a56d29ba3..7c33dbbd1f9 100644 --- a/lib/discourse_redis.rb +++ b/lib/discourse_redis.rb @@ -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 diff --git a/spec/components/discourse_spec.rb b/spec/components/discourse_spec.rb index 09426698a90..45685d92e70 100644 --- a/spec/components/discourse_spec.rb +++ b/spec/components/discourse_spec.rb @@ -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 diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index eb35d6caa01..9d0e17c0acf 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -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 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 672981c922b..63b3b45b02a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -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