[英]Sidekiq: Find last job
我有兩個Sidekiq工作。 首先是使用JSON加載文章供稿,並將其拆分為多個作業。 它還創建一個日志並存儲一個start_time
。
class LoadFeed
include Sidekiq::Worker
def perform url
log = Log.create! start_time: Time.now, url: url
articles = load_feed(url) # this one loads the feed
articles.each do |article|
ProcessArticle.perform_async(article, log.id)
end
end
end
第二個作業處理文章,並更新前一個創建的日志的end_time
字段, 以找出整個過程(加載提要,將其拆分為作業,處理文章)花費了多長時間。
class ProcessArticle
include Sidekiq::Worker
def perform data, log_id
process(data)
Log.find(log_id).update_attribute(:end_time, Time.now)
end
end
但是現在我有一些問題/疑問:
Log.find(log_id).update_attribute(:end_time, Time.now)
不是原子的,並且由於作業的異步行為,這可能導致錯誤的end_time
值。 有沒有辦法用當前時間對MySQL中的datetime
字段進行原子更新?- 提要可能會很長(〜800,000篇文章),並且在您只需要最后一個時,更新值800,000次似乎是很多不必要的工作。 有什么主意如何找出最后一個工作,而僅更新此工作的
end_time
字段?
對於1),您可以使用較少的查詢進行更新,然后讓MySQL查找時間:
Log.where(id: log_id).update_all('end_time = now()')
對於2),解決此問題的一種方法是僅在處理完所有文章后才更新結束時間。 例如,通過具有可以查詢的布爾值。 這不會減少查詢的數量,但是肯定會有更好的性能。
if feed.articles.needs_processing.none?
Log.where(id: log_id).update_all('end_time = now()')
end
這是Sidekiq Pro的“ 批處理”功能解決的問題。 您創建了一組作業,當它們全部完成時,它將調用您的代碼。
class LoadFeed
include Sidekiq::Worker
def on_success(status, options)
Log.find(options['log_id']).update_attribute(:end_time, Time.now)
end
def perform url
log = Log.create! start_time: Time.now, url: url
articles = load_feed(url) # this one loads the feed
batch = Sidekiq::Batch.new
batch.on(:success, self.class, 'log_id' => log.id)
batch.jobs do
articles.each do |article|
ProcessArticle.perform_async(article, log.id)
end
end
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.