[英]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.