2012-07-14 165 views
3

这很简单,我运行一个爬行程序来查找Cogs。 Cog可以属于一个Widget。有时它会发现一堆Cog都应该属于同一个Widget。在COG模式运行:DelayedJob打破验证ActiveRecord中的唯一约束条件

# 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") 

这是不可避免的,但我以为会被对手上面的代码来处理。我也有这样的小部件模型:

validates :name, presence: true, uniqueness: true 

不幸的是,在4个内核上运行4名DelayedJob工人这些作业在完全相同的时间运行,从而导致尽管两者的检查,以创建多个窗口小部件。创建小工具时如何防止竞争条件,以免重复?

回答

1

由于独特的检查和插入是分开执行的,因此存在竞争条件。您需要一个索引来执行唯一性约束。

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

+0

数据库索引将解决创建重复记录的问题,但他们会引发错误,因为代码仍然会在同一时间,只有数据库运行将防止插入。我想在应用程序级别而不是数据库级别提供解决方案。也许ActiveRecord交易? – sandre89 2016-11-18 13:43:05