这个Rails验证是否是线程安全的

时间:2016-04-28 18:56:12

标签: ruby-on-rails multithreading activerecord sidekiq activemodel

这是在多个Sidekiq实例和工作人员同时运行,似乎已经产生了一些问题,例如实例被分配了"它最近被警告"不应该出现错误,而不是相反。

很少见,但它正在发生,这是问题还是其他的东西?

{{1}}

2 个答案:

答案 0 :(得分:3)

我们在工作中遇到了类似的情况,经过大量的挖掘终于弄清了正在发生的事情。

类方法validates_with使用验证器的一个实例(BrokenValidator)来验证您要验证的类(BrokenModel)的所有实例。通常,这很好,但是您正在分配变量(@record,然后通过另一种方法(check_alerted访问该变量,因此其他线程正在分配@record,而其他线程仍在尝试{{ 1}}。

有两种方法可以解决此问题:

1)将check_alerted传递到record

check_alerted

2)使用class BrokenValidator < ActiveModel::Validator def validate(record) check_alerted(record) end private def check_alerted(record) if AtomicGlobalAlerted.new(record).valid? record.errors[:base] << "It was alerted recently" end p "check_alerted: #{record.errors[:base]}" end end 的实例版本,它为要验证的每个模型实例创建一个新的验证器实例:

validates_with

任何一种解决方案都可以解决并发问题。如果您遇到其他任何问题,请告诉我。

答案 1 :(得分:-1)

我相信铁轨中存在一些线程安全问题,但我们可以采取必要的预防措施来克服它们。

局部变量(例如本地var)对于方法块的每个特定调用都是本地的。如果两个线程同时调用此块,则每个调用将获得其自己的本地上下文变量,并且除非涉及共享资源,否则不会重叠:实例变量如(@global_var),静态变量{{ 1}},globals (@@static_var)会导致并发问题。

您正在使用实例变量,只需在每次使用($global_var)方法时对其进行实例化,并希望您的问题会像以下一样消失:

validate_record

有关详情,请访问详细link

或尝试在此处研究铁路配置:link