2014-01-24 111 views
0

我写下面的代码。目的是为了避免查询我的数据库与活动记录。ActiveRecord单身危险?

向数据库发出请求的唯一原因是更新(after_save)。

class Configuration < ActiveRecord::Base 

    def self.instance 
    ConfigurationSingleton.instance.active_record_instance 
    end 

    class ConfigurationSingleton 
    include Singleton 

    def initialize 
     @active_record_instance = Configuration.first || Configuration.new 
    end 

    def active_record_instance 
     @active_record_instance 
    end 
    end 

    after_save Proc.new { ConfigurationSingleton.instance.active_record_instance.reload } 
end 

它似乎在发展模式,但我觉得不安全。 这个代码安全地运行在apache乘客生产与几个单独的过程?

回答

1

如果你有几个不同的进程运行这个代码,那么你最终可能会得到每个进程的“单例”。如果你有多个应用程序服务器,你一定会遇到这个问题。

问题在于将重新加载实例的唯一过程将是保存发生的过程。除非实例保存在这些进程中,否则其他进程都不知道它已经更改。

所以:

  1. 应用服务器1个负载情况下
  2. 应用服务器2点的负载情况下
  3. 实例的应用程序服务器上进行更改1
  4. 应用服务器1个重载实例
  5. 应用服务器2继续与旧实例
0

通过在列上添加唯一索引并在创建单例时将该列设置为固定值,您可以轻松消除竞争状况的风险。确保在存在重复时处理SQL异常。

create_table :app_settings do |t| 
    t.integer :unique, null: false, default: 1 
    t.boolean :haz_mojo 
end 
add_index :app_settings, :unique, unique: true 

另一种选择是,创造了单之后,选择具有最低ID而不是与创建的参考持续行。