2012-07-14 88 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