我正在與Sidekiq一個高流量的測試,創建使用Mongoid作爲我在Rails應用4基於驅動MongoDB的對象重複的ID創建文檔。我看到的問題是,當PlayByPlay
文檔應該具有唯一的game_id
時,我看到使用相同的確切game_id創建了多個PlayByPlay對象。我也強制MongoDB的唯一約束,這仍然在發生。這是我的文檔,它是嵌入式文檔,以及我如何創建文檔的一瞥。問題是,這一切都發生在使用Sidekiq的線程環境中,我不確定是否有辦法解決它。我的寫作關注在mongoid.yml
中設置爲1
,看起來safe
選項在主版本中被刪除,persist_in_safe_mode
也被刪除。代碼如下 - 關於如何正確工作的任何建議,將不勝感激。這不是一個副本集,它是目前單個MongoDB服務器執行所有讀取/寫入請求。Mongoid 4(GitHub的主機)與
module MLB
class Play
include Mongoid::Document
include Mongoid::Timestamps
embedded_in :play_by_play
field :batter#, type: Hash
field :next_batter#, type: Hash
field :pitchers#, type: Array
field :pitches#, type: Array
field :fielders#, type: Array
field :narrative, type: String
field :seq_id, type: Integer
field :inning, type: Integer
field :outs
field :no_play
field :home_team_score
field :away_team_score
end
class PlayByPlay
include Mongoid::Document
include Mongoid::Timestamps
embeds_many :plays, cascade_callbacks: true
accepts_nested_attributes_for :plays
field :sport
field :datetime, type: DateTime
field :gamedate, type: DateTime
field :game_id
field :home_team_id
field :away_team_id
field :home_team_score
field :away_team_score
field :season_year
field :season_type
field :location
field :status
field :home_team_abbr
field :away_team_abbr
field :hp_umpire
field :fb_umpire
field :sb_umpire
field :tb_umpire
index({game_id: 1})
index({away_team_id: 1})
index({home_team_id: 1})
index({season_type: 1})
index({season_year: 1})
index({"plays.seq_id" => 1}, {unique: true, drop_dups: true})
#validates 'play.seq_id', uniqueness: true
validates :game_id, presence: true, uniqueness: true
validates :home_team_id, presence: true
validates :away_team_id, presence: true
validates :gamedate, presence: true
validates :datetime, presence: true
validates :season_type, presence: true
validates :season_year, presence: true
def self.parse!(entry)
@document = Nokogiri::XML(entry.data)
xslt = Nokogiri::XSLT(File.read("#{$XSLT_PATH}/mlb_pbp.xslt"))
transform = xslt.apply_to(@document)
json_document = JSON.parse(transform)
obj = find_or_create_by(game_id: json_document['game_id'])
obj.sport = json_document['sport']
obj.home_team_id = json_document['home_team_id']
obj.away_team_id = json_document['away_team_id']
obj.home_team_score = json_document['home_team_score']
obj.away_team_score = json_document['away_team_score']
obj.season_type = json_document['season_type']
obj.season_year = json_document['season_year']
obj.location = json_document['location']
obj.datetime = DateTime.strptime(json_document['datetime'], "%m/%d/%y %H:%M:%S")
obj.gamedate = DateTime.strptime(json_document['game_date'], "%m/%d/%Y %H:%M:%S %p")
obj.status = json_document['status']
obj.home_team_abbr = json_document['home_team_abbr']
obj.away_team_abbr = json_document['away_team_abbr']
obj.hp_umpire = json_document['hp_umpire']
obj.fb_umpire = json_document['fb_umpire']
obj.sb_umpire = json_document['sb_umpire']
obj.tb_umpire = json_document['tb_umpire']
p=obj.plays.build(seq_id: json_document['seq_id'])
p.batter = json_document['batter']
p.next_batter = json_document['next_batter'] if json_document['next_batter'].present? && json_document['next_batter'].keys.count >= 1
p.pitchers = json_document['pitchers'] if json_document['pitchers'].present? && json_document['pitchers'].count >= 1
p.pitches = json_document['pitches'] if json_document['pitches'].present? && json_document['pitches'].count >= 1
p.fielders = json_document['fielders'] if json_document['fielders'].present? && json_document['fielders'].count >= 1
p.narrative = json_document['narrative']
p.seq_id = json_document['seq_id']
p.inning = json_document['inning']
p.outs = json_document['outs']
p.no_play = json_document['no_play']
p.home_team_score = json_document['home_team_score']
p.away_team_score = json_document['away_team_score']
obj.save
end
end
end
**注意**
這個問題消失,如果我限制sidekiq 1名工人,這顯然在現實世界裏,我從來沒有這樣做。
另一個解決方案是一個給定的時間之後執行的任務。 'MyWorker.perform_in(5.seconds,1,2,3)'雖然它可能不被接受。 –
Mutex幾乎把工作者的水平可伸縮性置之度外,理想情況下,你需要鎖定整個集羣的東西 – bbozo
@bbozo在這種情況下,如果OP在許多不同的計算機上運行sidekiq線程,Mutex將不起作用。但是,如果OP只在一臺計算機上運行它,它就可以工作。如果OP在許多計算機上運行sidekiq線程,他可能需要另一種解決方案。 – vidaica