From 64858c10febafecf875a70a3d565b5a05e74e2e8 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Wed, 29 Jun 2016 14:19:18 +0800 Subject: [PATCH] FIX: Set a not expiring key for user enabled readonly mode. --- app/controllers/admin/backups_controller.rb | 2 +- lib/discourse.rb | 26 +++++++----- spec/components/discourse_spec.rb | 47 ++++++++++++++------- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/app/controllers/admin/backups_controller.rb b/app/controllers/admin/backups_controller.rb index 3539e2fa4..b085dc81f 100644 --- a/app/controllers/admin/backups_controller.rb +++ b/app/controllers/admin/backups_controller.rb @@ -95,7 +95,7 @@ class Admin::BackupsController < Admin::AdminController def readonly enable = params.fetch(:enable).to_s == "true" - enable ? Discourse.enable_readonly_mode : Discourse.disable_readonly_mode + enable ? Discourse.enable_readonly_mode(user_enabled: true) : Discourse.disable_readonly_mode(user_enabled: true) render nothing: true end diff --git a/lib/discourse.rb b/lib/discourse.rb index fe0684a4b..3539a7bbf 100644 --- a/lib/discourse.rb +++ b/lib/discourse.rb @@ -216,11 +216,18 @@ module Discourse end READONLY_MODE_KEY_TTL ||= 60 + READONLY_MODE_KEY ||= 'readonly_mode'.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) + else + $redis.setex(READONLY_MODE_KEY, READONLY_MODE_KEY_TTL, 1) + keep_readonly_mode + end - def self.enable_readonly_mode - $redis.setex(readonly_mode_key, READONLY_MODE_KEY_TTL, 1) MessageBus.publish(readonly_channel, true) - keep_readonly_mode true end @@ -228,20 +235,21 @@ module Discourse # extend the expiry by 1 minute every 30 seconds Thread.new do while readonly_mode? - $redis.expire(readonly_mode_key, READONLY_MODE_KEY_TTL) + $redis.expire(READONLY_MODE_KEY, READONLY_MODE_KEY_TTL) sleep 30.seconds end end end - def self.disable_readonly_mode - $redis.del(readonly_mode_key) + def self.disable_readonly_mode(user_enabled: false) + key = user_enabled ? USER_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) + recently_readonly? || !!$redis.get(READONLY_MODE_KEY) end def self.request_refresh! @@ -310,10 +318,6 @@ module Discourse Rails.configuration.action_controller.asset_host end - def self.readonly_mode_key - "readonly_mode" - end - def self.readonly_channel "/site/read-only" end diff --git a/spec/components/discourse_spec.rb b/spec/components/discourse_spec.rb index 49948f6c5..674992878 100644 --- a/spec/components/discourse_spec.rb +++ b/spec/components/discourse_spec.rb @@ -86,36 +86,45 @@ describe Discourse do end context 'readonly mode' do - let(:readonly_channel) { Discourse.readonly_channel } - let(:readonly_key) { Discourse.readonly_mode_key } + let(:readonly_mode_key) { Discourse::READONLY_MODE_KEY } let(:readonly_mode_ttl) { Discourse::READONLY_MODE_KEY_TTL } + let(:user_readonly_mode_key) { Discourse::USER_READONLY_MODE_KEY } after do - $redis.del(readonly_key) + $redis.del(readonly_mode_key) + $redis.del(user_readonly_mode_key) end - def assert_readonly_mode(message, channel, key, ttl) - expect(message.channel).to eq(channel) + def assert_readonly_mode(message, key, ttl = -1) + expect(message.channel).to eq(Discourse.readonly_channel) expect(message.data).to eq(true) expect($redis.get(key)).to eq("1") expect($redis.ttl(key)).to eq(ttl) end - def assert_readonly_mode_disabled(message, channel, key) - expect(message.channel).to eq(channel) + def assert_readonly_mode_disabled(message, key) + expect(message.channel).to eq(Discourse.readonly_channel) expect(message.data).to eq(false) expect($redis.get(key)).to eq(nil) end - context ".enable_readonly_mode" do + describe ".enable_readonly_mode" do it "adds a key in redis and publish a message through the message bus" do - expect($redis.get(readonly_key)).to eq(nil) + expect($redis.get(readonly_mode_key)).to eq(nil) message = MessageBus.track_publish { Discourse.enable_readonly_mode }.first - assert_readonly_mode(message, readonly_channel, readonly_key, readonly_mode_ttl) + assert_readonly_mode(message, readonly_mode_key, readonly_mode_ttl) + end + + context 'user enabled readonly mode' do + it "adds a key in redis and publish a message through the message bus" do + expect($redis.get(user_readonly_mode_key)).to eq(nil) + message = MessageBus.track_publish { Discourse.enable_readonly_mode(user_enabled: true) }.first + assert_readonly_mode(message, user_readonly_mode_key) + end end end - context ".disable_readonly_mode" do + describe ".disable_readonly_mode" do it "removes a key from redis and publish a message through the message bus" do Discourse.enable_readonly_mode @@ -123,17 +132,25 @@ describe Discourse do Discourse.disable_readonly_mode end.first - assert_readonly_mode_disabled(message, readonly_channel, readonly_key) + assert_readonly_mode_disabled(message, readonly_mode_key) + end + + context 'user disabled readonly mode' do + it "removes readonly key in redis and publish a message through the message bus" do + Discourse.enable_readonly_mode(user_enabled: true) + message = MessageBus.track_publish { Discourse.disable_readonly_mode(user_enabled: true) }.first + assert_readonly_mode_disabled(message, user_readonly_mode_key) + end end end - context ".readonly_mode?" do + describe ".readonly_mode?" do it "is false by default" do expect(Discourse.readonly_mode?).to eq(false) end it "returns true when the key is present in redis" do - $redis.set(readonly_key, 1) + $redis.set(readonly_mode_key, 1) expect(Discourse.readonly_mode?).to eq(true) end @@ -143,7 +160,7 @@ describe Discourse do end end - context ".received_readonly!" do + describe ".received_readonly!" do it "sets the right time" do time = Discourse.received_readonly! expect(Discourse.last_read_only['default']).to eq(time)