Added multi process support (share updated settings over multiple processes).

This commit is contained in:
Martin Edenhofer 2015-08-31 14:36:57 +02:00
parent 427b8e9fbd
commit ab0a02c09d

View file

@ -7,15 +7,75 @@ class Setting < ApplicationModel
store :preferences store :preferences
before_create :state_check, :set_initial before_create :state_check, :set_initial
before_update :state_check before_update :state_check
after_create :delete_cache after_create :reset_cache
after_update :delete_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 def self.load
# check if config is already generated # 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 # read all config settings
config = {} config = {}
@ -33,52 +93,56 @@ class Setting < ApplicationModel
} }
# store for class requests # store for class requests
@@current[:settings_config] = config cache(config)
config config
end end
def self.set(name, value) # set initial value in state_initial
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
def set_initial def set_initial
self.state_initial = state self.state_initial = state
end 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 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 } self.state = { value: state }
end end