gpt4 book ai didi

ruby-on-rails - 这是 Rails 验证线程安全的吗

转载 作者:行者123 更新时间:2023-12-01 16:42:54 25 4
gpt4 key购买 nike

这同时在多个 Sidekiq 实例和 worker 中运行,这似乎产生了一些问题,例如实例被分配了“最近被警告”的错误,而在不应该和相反的情况下。

这种情况很少见,但正在发生,这是问题所在还是其他原因?

class BrokenModel < ActiveRecord::Base
validates_with BrokenValidator

end

class BrokenValidator < ActiveModel::Validator
def validate record
@record = record

check_alerted
end

private

def check_alerted
if AtomicGlobalAlerted.new(@record).valid?
@record.errors[:base] << "It was alerted recently"
end

p "check_alerted: #{@record.errors[:base]}"
end
end

class AtomicGlobalAlerted
include Redis::Objects
attr_accessor :id

def initialize id
@id = id
@fredis = nil

Sidekiq.redis do |redis|
@fredis = FreshRedis.new(redis, freshness: 7.days, granularity: 4.hours)
end
end

def valid?
@fredis.smembers.includes?(@id)
end
end

最佳答案

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

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

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

1) 将record传递给check_alerted:

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

2) 使用 validates_with 的实例版本,它为您要验证的每个模型实例创建一个新的验证器实例:

class BrokenModel < ActiveRecord::Base
validate :instance_validators

def instance_validators
validates_with BrokenValidator
end

end

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

关于ruby-on-rails - 这是 Rails 验证线程安全的吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36923269/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com