diff --git a/app/models/setting.rb b/app/models/setting.rb index fb82da162..40aac368f 100644 --- a/app/models/setting.rb +++ b/app/models/setting.rb @@ -7,15 +7,75 @@ class Setting < ApplicationModel store :preferences before_create :state_check, :set_initial before_update :state_check - after_create :delete_cache - after_update :delete_cache + after_create :reset_cache + after_update :reset_cache + after_destroy :reset_cache - @@current = {} # rubocop:disable Style/ClassVars + @@current = {} # rubocop:disable Style/ClassVars + @@change_id = nil # rubocop:disable Style/ClassVars + @@lookup_at = nil # rubocop:disable Style/ClassVars + @@lookup_timeout = 2.minutes # rubocop:disable Style/ClassVars +=begin + +set config setting + + Setting.set('some_config_name', some_value) + +=end + + def self.set(name, value) + setting = Setting.find_by( name: name ) + if !setting + fail "Can't find config setting '#{name}'" + end + setting.state = { value: value } + setting.save + logger.info "Setting.set(#{name}, #{value.inspect})" + end + +=begin + +get config setting + + value = Setting.get('some_config_name') + +=end + + def self.get(name) + load + @@current[:settings_config][name] + end + +=begin + +reset config setting to default + + Setting.reset('some_config_name') + +=end + + def self.reset(name) + setting = Setting.find_by( name: name ) + if !setting + fail "Can't find config setting '#{name}'" + end + setting.state = setting.state_initial + setting.save + logger.info "Setting.reset(#{name}, #{setting.state.inspect})" + load + @@current[:settings_config][name] + end + + private + + # load values and cache them def self.load # check if config is already generated - return @@current[:settings_config] if @@current[:settings_config] + if @@current[:settings_config] + return @@current[:settings_config] if cache_valid? + end # read all config settings config = {} @@ -33,52 +93,56 @@ class Setting < ApplicationModel } # store for class requests - @@current[:settings_config] = config + cache(config) config end - def self.set(name, value) - setting = Setting.find_by( name: name ) - if !setting - fail "Can't find config setting '#{name}'" - end - setting.state = { value: value } - setting.save - logger.info "Setting.set() name:#{name}, value:#{value.inspect}" - end - - def self.get(name) - load - @@current[:settings_config][name] - end - - def self.reset(name) - setting = Setting.find_by( name: name ) - if !setting - fail "Can't find config setting '#{name}'" - end - setting.state = setting.state_initial - setting.save - logger.info "Setting.reset() name:#{name}, value:#{setting.state.inspect}" - load - @@current[:settings_config][name] - end - - private - - def delete_cache - @@current[:settings_config] = nil - end - + # set initial value in state_initial def set_initial self.state_initial = state end + # set new cache + def self.cache(config) + @@change_id = Cache.get('Setting::ChangeId') # rubocop:disable Style/ClassVars + @@current[:settings_config] = config + logger.debug "Setting.cache: set cache, #{@@change_id}" + @@lookup_at = Time.zone.now # rubocop:disable Style/ClassVars + end + + # reset cache + def reset_cache + @@change_id = rand(999_999_999).to_s # rubocop:disable Style/ClassVars + logger.debug "Setting.reset_cache: set new cache, #{@@change_id}" + + Cache.write('Setting::ChangeId', @@change_id, { expires_in: 24.hours }) + @@current[:settings_config] = nil + end + + # check if cache is still valid + def self.cache_valid? + if @@lookup_at && @@lookup_at > Time.zone.now - @@lookup_timeout + logger.debug 'Setting.cache_valid?: cache_id has beed set within last 2 minutes' + return true + end + change_id = Cache.get('Setting::ChangeId') + if change_id == @@change_id + @@lookup_at = Time.zone.now # rubocop:disable Style/ClassVars + logger.debug "Setting.cache_valid?: cache still valid, #{@@change_id}/#{change_id}" + return true + end + logger.debug "Setting.cache_valid?: cache has changed, #{@@change_id}/#{change_id}" + false + end + + # convert state ot hash to be able to store it as store def state_check - return if !(state || state == false) + return if !state + return if state == false - return if !( !state.respond_to?('has_key?') || !state.key?(:value) ) + return if state.respond_to?('has_key?') + return if state.key?(:value) self.state = { value: state } end