Просмотр исходного кода

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

Martin Edenhofer 9 лет назад
Родитель
Сommit
ab0a02c09d
1 измененных файлов с 94 добавлено и 30 удалено
  1. 94 30
      app/models/setting.rb

+ 94 - 30
app/models/setting.rb

@@ -7,35 +7,22 @@ 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
 
-  def self.load
-
-    # check if config is already generated
-    return @@current[:settings_config] if @@current[:settings_config]
+=begin
 
-    # read all config settings
-    config = {}
-    Setting.select('name, state').order(:id).each { |setting|
-      config[setting.name] = setting.state[:value]
-    }
+set config setting
 
-    # config lookups
-    config.each { |key, value|
-      next if value.class.to_s != 'String'
+  Setting.set('some_config_name', some_value)
 
-      config[key].gsub!( /\#\{config\.(.+?)\}/ ) {
-        config[$1].to_s
-      }
-    }
-
-    # store for class requests
-    @@current[:settings_config] = config
-    config
-  end
+=end
 
   def self.set(name, value)
     setting = Setting.find_by( name: name )
@@ -44,14 +31,30 @@ class Setting < ApplicationModel
     end
     setting.state = { value: value }
     setting.save
-    logger.info "Setting.set() name:#{name}, value:#{value.inspect}"
+    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
@@ -59,26 +62,87 @@ class Setting < ApplicationModel
     end
     setting.state = setting.state_initial
     setting.save
-    logger.info "Setting.reset() name:#{name}, value:#{setting.state.inspect}"
+    logger.info "Setting.reset(#{name}, #{setting.state.inspect})"
     load
     @@current[:settings_config][name]
   end
 
   private
 
-  def delete_cache
-    @@current[:settings_config] = nil
+  # load values and cache them
+  def self.load
+
+    # check if config is already generated
+    if @@current[:settings_config]
+      return @@current[:settings_config] if cache_valid?
+    end
+
+    # read all config settings
+    config = {}
+    Setting.select('name, state').order(:id).each { |setting|
+      config[setting.name] = setting.state[:value]
+    }
+
+    # config lookups
+    config.each { |key, value|
+      next if value.class.to_s != 'String'
+
+      config[key].gsub!( /\#\{config\.(.+?)\}/ ) {
+        config[$1].to_s
+      }
+    }
+
+    # store for class requests
+    cache(config)
+    config
   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