簡體   English   中英

Sidekiq:找到最后一份工作

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

但是現在我有一些問題/疑問:

  1. Log.find(log_id).update_attribute(:end_time, Time.now)不是原子的,並且由於作業的異步行為,這可能導致錯誤的end_time值。 有沒有辦法用當前時間對MySQL中的datetime字段進行原子更新?
  2. 提要可能會很長(〜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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM