115 lines
4.8 KiB
Ruby
115 lines
4.8 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
#
|
|
# Copyright (C) 2017 - present Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
require_relative "../spec_helper.rb"
|
|
|
|
describe ActiveSupport::Cache::HaStore do
|
|
before do
|
|
skip unless Canvas.redis_enabled?
|
|
end
|
|
|
|
let(:store) { ActiveSupport::Cache::HaStore.new(url: Canvas.redis.id, expires_in: 5.minutes.to_i, race_condition_ttl: 7.days.to_i, consul_event: 'invalidate') }
|
|
|
|
describe "#delete" do
|
|
it "triggers a consul event when configured" do
|
|
# will get called twice; once with rails52: prefix, once without
|
|
expect(Diplomat::Event).to receive(:fire).with("invalidate", match(/mykey$/), nil, nil, nil, nil).twice
|
|
store.delete('mykey')
|
|
end
|
|
end
|
|
|
|
describe "consume_consul_events" do
|
|
it "works" do
|
|
# check that Canvas.redis is equivalent to Redis.new that consume_consule_events uses
|
|
# I would normally compare against `id`, but that might have localhost vs. 127.0.0.1
|
|
redis = Redis.new(connect_timeout: 0.5)
|
|
secret_key = SecureRandom.uuid
|
|
Canvas.redis.set(secret_key, "1", ex: 5)
|
|
skip "Can't run this spec unless redis is default configured" unless (redis.get(secret_key) rescue nil) == "1"
|
|
consul_event_id = SecureRandom.uuid
|
|
|
|
Bundler.with_clean_env do
|
|
payload = [{ ID: consul_event_id, Payload: Base64.strict_encode64(secret_key) }].to_json
|
|
|
|
`echo #{Shellwords.escape(payload)} | #{Rails.root}/script/consume_consul_events`
|
|
expect($?).to be_success
|
|
end
|
|
expect(redis.get(secret_key)).to be_nil
|
|
expect(redis.zrank("consul_events", consul_event_id)).not_to be_nil
|
|
end
|
|
|
|
it "cleared everything with FLUSHDB" do
|
|
# check that Canvas.redis is equivalent to Redis.new that consume_consule_events uses
|
|
# I would normally compare against `id`, but that might have localhost vs. 127.0.0.1
|
|
redis = Redis.new(connect_timeout: 0.5)
|
|
secret_key = SecureRandom.uuid
|
|
secret_key2 = SecureRandom.uuid
|
|
Canvas.redis.set(secret_key, "1", ex: 5)
|
|
Canvas.redis.set(secret_key2, "1", ex: 5)
|
|
skip "Can't run this spec unless redis is default configured" unless (redis.get(secret_key) rescue nil) == "1"
|
|
consul_event_id = SecureRandom.uuid
|
|
|
|
Bundler.with_clean_env do
|
|
payload = [{ ID: consul_event_id, Payload: Base64.strict_encode64('FLUSHDB') }].to_json
|
|
|
|
`echo #{Shellwords.escape(payload)} | #{Rails.root}/script/consume_consul_events`
|
|
expect($?).to be_success
|
|
end
|
|
expect(redis.get(secret_key)).to be_nil
|
|
expect(redis.get(secret_key2)).to be_nil
|
|
# This is reset after clearing the db, which is important so we don't repeatedly clear
|
|
expect(redis.zrank("consul_events", consul_event_id)).not_to be_nil
|
|
end
|
|
end
|
|
|
|
context "Account cache register" do
|
|
specs_require_cache(:redis_cache_store)
|
|
|
|
before do
|
|
allow(MultiCache).to receive(:cache).and_return(store)
|
|
allow(Diplomat::Event).to receive(:fire)
|
|
end
|
|
|
|
it "uses MultiCache as store for feature_flags cache_key" do
|
|
Timecop.freeze do
|
|
now = Time.now.utc.to_s(Account.cache_timestamp_format)
|
|
base_key = Account.base_cache_register_key_for(Account.site_admin)
|
|
full_key = base_key + "/feature_flags"
|
|
expect(Canvas::CacheRegister.lua).to receive(:run).with(:get_key, [full_key], [now], store.redis).and_return("cool beans")
|
|
expect(Account.site_admin.cache_key(:feature_flags)).to eq("accounts/#{Account.site_admin.global_id}-cool beans")
|
|
# doesn't use it for other key types
|
|
expect(Canvas::CacheRegister.lua).to receive(:run).with(:get_key, [base_key + "/global_navigation"], [now], Canvas.redis).and_return(now)
|
|
expect(Account.site_admin.cache_key(:global_navigation)).to eq("accounts/#{Account.site_admin.global_id}-#{now}")
|
|
end
|
|
end
|
|
|
|
it "properly invalidates feature_flags cache_key" do
|
|
Timecop.freeze do
|
|
key1 = Account.site_admin.cache_key(:feature_flags)
|
|
Timecop.travel(1)
|
|
expect(Account.site_admin.cache_key(:feature_flags)).to eq key1
|
|
Timecop.travel(1)
|
|
expect(Canvas.redis).to_not receive(:del)
|
|
Account.site_admin.clear_cache_key(:feature_flags)
|
|
expect(Account.site_admin.cache_key(:feature_flags)).not_to eq key1
|
|
end
|
|
end
|
|
end
|
|
end
|