1

私はsidekiq非同期ジョブを処理するために使用していますが、複雑さが増した後、ジョブの状態を認識するのに苦労しています。

取引は次のとおりです。

Batchコミット後に非同期メソッドを呼び出すモデルがあります。

# app/models/batch.rb
class Batch < ActiveRecord::Base

  after_commit :calculate, on: :create

  def calculate
    job_id = BatchWorker.perform_async(self.id)

    # update_column skips callbacks and validations!
    self.update_column(:job_id, job_id)
  end
end

ワーカーはモデルからデータを読み取り、次のように各データの非同期ジョブを呼び出します。

# app/workers/batch_worker.rb
class BatchWorker

  def perform(batch_id)
    batch = Batch.find(batch_id)

    ## read data to 'tab'    

    tab.each do |ts|
      obj = batch.item.create(name: ts[0], data: ts[1])
      job_id = ItemWorker.perform_async(obj.id)
      obj.update_attribute(:job_id, job_id)
    end
  end

end

問題は次のとおりです。これらの非同期ジョブは計算を実行し、ダウンロード結果のリンクが完了する前に利用できるようにすることはできません。そのため、すべての「子ジョブ」がいつ完了するかを知る必要があります。これにより、モデルstatusから属性を変更できます。 Batch。つまり、すべてのジョブがキューに入れられているかどうかを知る必要はありませんが、代わりに、によって生成されたすべての非同期ジョブItemWorkerが実行され、完了したかどうかを知る必要があります。

  • これを達成するための最良の方法は何でしょうか?「並列計算の世界」では意味がありますか?

Obs .: job_idは揮発性のようであるため、dbに保存するかどうかはわかりません。

4

1 に答える 1

4

おそらく、これに Redis を使用することは、インフラストラクチャに既にあり、Rails アプリで構成されていることを考えると (Sidekiq により)、適している可能性があります。

Redis には組み込みのパブリッシュ/サブスクライブ エンジンと、キーに対するアトミック オペレーションがあり、探している種類の同時実行の管理に適しています。

たぶん、おおよそ次のようなものです:

class BatchWorker

  def perform(batch_id)
    batch = Batch.find(batch_id)

    redis = Redis.new
    redis.set "jobs_remaining_#{batch_id}", tab.count
    redis.subscribe("batch_task_complete.#{batch_id}") do |on|
      on.message do |event, data|
        if redis.decr("jobs_remaining_#{batch_id}") < 1
          #UPDATE STATUS HERE
          redis.del "jobs_remaining_#{batch_id}"
        end
      end
    end

    tab.each do |ts|
      obj = batch.item.create(name: ts[0], data: ts[1])
      job_id = ItemWorker.perform_async(obj.id, batch_id)
    end
  end
end

class ItemWorker
  def perform item_id, batch_id=nil
    #DO STUFF
    if batch_id
      Redis.new.publish "batch_task_complete.#{batch_id}"
    end
  end
end
于 2013-03-11T22:29:16.973 に答える