From 8859880e55d50cc0124f5edbdbafb32ddf7fd96e Mon Sep 17 00:00:00 2001 From: Sony Mathew Date: Mon, 11 May 2020 19:00:33 +0530 Subject: [PATCH] Feature: Global Config helper (#844) (#845) * Added a global config helper to easily access installation/global configs * this will fetch the keys from cache with fallback to DB on cache miss * ability to query multiple keys simultaneously * interface to delete the existing global config cache * Added tests for this new helper module --- .rubocop.yml | 1 + lib/global_config.rb | 44 ++++++++++++++++++++++++++++++++++ spec/lib/global_config_spec.rb | 39 ++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 lib/global_config.rb create mode 100644 spec/lib/global_config_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index bded7aed3..9ea8ca106 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -30,6 +30,7 @@ Style/GlobalVars: Exclude: - 'config/initializers/redis.rb' - 'lib/redis/alfred.rb' + - 'lib/global_config.rb' Metrics/BlockLength: Exclude: - spec/**/* diff --git a/lib/global_config.rb b/lib/global_config.rb new file mode 100644 index 000000000..8c1da224d --- /dev/null +++ b/lib/global_config.rb @@ -0,0 +1,44 @@ +class GlobalConfig + VERSION = 'V1'.freeze + KEY_PREFIX = 'GLOBAL_CONFIG'.freeze + DEFAULT_EXPIRY = 1.day + + class << self + def get(*args) + config_keys = *args + config = {} + + config_keys.each do |config_key| + config[config_key] = load_from_cache(config_key) + end + + config.with_indifferent_access + end + + def clear_cache + cached_keys = $alfred.keys("#{VERSION}:#{KEY_PREFIX}:*") + (cached_keys || []).each do |cached_key| + $alfred.expire(cached_key, 0) + end + end + + private + + def load_from_cache(config_key) + cache_key = "#{VERSION}:#{KEY_PREFIX}:#{config_key}" + cached_value = $alfred.get(cache_key) + + if cached_value.blank? + value_from_db = db_fallback(config_key) + cached_value = { value: value_from_db }.to_json + $alfred.set(cache_key, cached_value, { expiry: DEFAULT_EXPIRY }) + end + + JSON.parse(cached_value)['value'] + end + + def db_fallback(config_key) + InstallationConfig.find_by(name: config_key)&.value + end + end +end diff --git a/spec/lib/global_config_spec.rb b/spec/lib/global_config_spec.rb new file mode 100644 index 000000000..ac9a94368 --- /dev/null +++ b/spec/lib/global_config_spec.rb @@ -0,0 +1,39 @@ +require 'rails_helper' + +describe GlobalConfig do + subject(:trigger) { described_class } + + describe 'execute' do + context 'when called with default options' do + before do + described_class.clear_cache + end + + it 'hit DB for the first call' do + expect(InstallationConfig).to receive(:find_by) + described_class.get('test') + end + + it 'get from cache for subsequent calls' do + # this loads from DB + described_class.get('test') + + # subsequent calls should not hit DB + expect(InstallationConfig).not_to receive(:find_by) + described_class.get('test') + end + + it 'clears cache and fetch from DB next time, when clear_cache is called' do + # this loads from DB and is cached + described_class.get('test') + + # clears the cache + described_class.clear_cache + + # should be loaded from DB + expect(InstallationConfig).to receive(:find_by).with({ name: 'test' }).and_return(nil) + described_class.get('test') + end + end + end +end