2016-01-23 57 views
1

我有兩個Sidekiq工作。第一個以JSON加載文章提要,並將其分成多個作業。它還創建日誌並存儲start_timeSidekiq:查找最後一份工作

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. 飼料可以得到相當長的時間(約800k條款)和更新值800k次,當你只需要最後一個似乎是很多不必要的工作。 任何想法如何找出哪一個是最後一項工作,並只更新end_time這個工作領域?

回答

1

爲1),你可以做少了一個查詢的更新,讓MySQL的發現時間:

Log.where(id: log_id).update_all('end_time = now()') 

對於2)來解決,這將是更新您的結束時間的一種方式只有在所有文章都被處理的情況下例如通過一個你可以查詢的布爾值。這不會減少查詢的數量,但肯定會有更好的性能。

0

這是Sidekiq Pro的Batch功能解決的問題。您創建了一組作業,它們在完成時調用您的代碼。

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 
+0

這將是一個有用的功能,但我買不起Sidekiq Pro的開源項目;) – 23tux