DelayedJob break验证ActiveRecord中的唯一约束

时间:2012-07-14 15:53:57

标签: activerecord delayed-job race-condition

这很简单,我正在运行一个找到Cogs的爬虫。 Cogs可以属于一个Widget。有时它会发现一堆Cogs都属于同一个Widget。在Cog模型中,它运行:

# Find or create widget
match = Widget.where("name ILIKE (?)", name).first
match = Widget.create(name: name) unless match

并行运行的延迟作业基本上是这样的:

- CREATE Cog, name: "cog1", (Widget, name: "Foo")
- CREATE Cog, name: "cog2", (Widget, name: "Foo")
- CREATE Cog, name: "cog3", (Widget, name: "Foo")
- CREATE Cog, name: "cog4", (Widget, name: "Foo")

这是不可避免的,但我认为会由上面的匹配代码处理。我在Widget模型中也有这个:

validates :name, presence: true, uniqueness: true

不幸的是,有4个DelayedJob工作者在4个核心上运行,这些作业完全同时运行,导致多个Widgets被创建,尽管两个检查都是如此。如何在创建小部件时防止竞争条件,这样我就不会重复了?

1 个答案:

答案 0 :(得分:1)

因为独特的检查和插入是分开进行的,所以存在竞争条件。您需要一个索引来强制执行唯一性约束。

文档提到了这一点:http://guides.rubyonrails.org/active_record_validations.html#uniqueness