Added cache for application settings (Setting model).

Once the values are cached, only one database query is done at each user request (to check if the cache is still valid).

git-svn-id: http://redmine.rubyforge.org/svn/trunk@685 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
Jean-Philippe Lang 2007-08-31 17:45:32 +00:00
parent 404bfce446
commit 6bdc13b33d
3 changed files with 47 additions and 10 deletions

View File

@ -32,6 +32,7 @@ class ApplicationController < ActionController::Base
end end
def user_setup def user_setup
Setting.check_cache
if session[:user_id] if session[:user_id]
# existing session # existing session
User.current = User.find(session[:user_id]) User.current = User.find(session[:user_id])

View File

@ -24,24 +24,27 @@ class Setting < ActiveRecord::Base
validates_inclusion_of :name, :in => @@available_settings.keys validates_inclusion_of :name, :in => @@available_settings.keys
validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| @@available_settings[setting.name]['format'] == 'int' } validates_numericality_of :value, :only_integer => true, :if => Proc.new { |setting| @@available_settings[setting.name]['format'] == 'int' }
def self.get(name) # Hash used to cache setting values
name = name.to_s @cached_settings = {}
setting = find_by_name(name) @cached_cleared_on = Time.now
setting ||= new(:name => name, :value => @@available_settings[name]['default']) if @@available_settings.has_key? name
setting
end
# Returns the value of the setting named name
def self.[](name) def self.[](name)
get(name).value value = @cached_settings[name]
value ? value : (@cached_settings[name] = find_or_default(name).value)
end end
def self.[]=(name, value) def self.[]=(name, value)
setting = get(name) setting = find_or_default(name)
setting.value = (value ? value.to_s : "") setting.value = (value ? value.to_s : "")
@cached_settings[name] = nil
setting.save setting.save
setting.value setting.value
end end
# Defines getter and setter for each setting
# Then setting values can be read using: Setting.some_setting_name
# or set using Setting.some_setting_name = "some value"
@@available_settings.each do |name, params| @@available_settings.each do |name, params|
src = <<-END_SRC src = <<-END_SRC
def self.#{name} def self.#{name}
@ -58,4 +61,26 @@ class Setting < ActiveRecord::Base
END_SRC END_SRC
class_eval src, __FILE__, __LINE__ class_eval src, __FILE__, __LINE__
end end
# Checks if settings have changed since the values were read
# and clears the cache hash if it's the case
# Called once per request
def self.check_cache
settings_updated_on = Setting.maximum(:updated_on)
if settings_updated_on && @cached_cleared_on <= settings_updated_on
@cached_settings.clear
@cached_cleared_on = Time.now
logger.info "Settings cache cleared." if logger
end
end
private
# Returns the Setting instance for the setting named name
# (record found in database or new record with default value)
def self.find_or_default(name)
name = name.to_s
raise "There's no setting named #{name}" unless @@available_settings.has_key?(name)
setting = find_by_name(name)
setting ||= new(:name => name, :value => @@available_settings[name]['default']) if @@available_settings.has_key? name
end
end end

View File

@ -0,0 +1,11 @@
class AddSettingsUpdatedOn < ActiveRecord::Migration
def self.up
add_column :settings, :updated_on, :timestamp
# set updated_on
Setting.find(:all).each(&:save)
end
def self.down
remove_column :settings, :updated_on
end
end