我写下面的代码。目的是避免使用活动记录查询我的数据库。
向数据库发出请求的唯一原因是更新(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乘客进行生产并使用多个单独的流程?
答案 0 :(得分:1)
如果您有几个不同的进程运行此代码,那么每个进程最终可能会出现“单例”。如果你有多个应用服务器,你肯定会遇到问题。
问题是将重新加载实例的唯一进程将是保存发生的进程。除非实例也保存在这些进程上,否则其他任何进程都不会知道它已更改。
所以:
答案 1 :(得分: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最低的行,而不是继续创建的引用。