2017-12-22 4 views
0

私はActiveJobでsidekiqを使用しています。キューのバランスをとってみたい。だから私はこの方法で使う。Sidekiqのqueue.sizeはリアルタイムで更新されません

while queue.size < 10 
    SomeJob.perform_later(some_args) # This should add one job to the queue right away, but it doesn't, it takes some time for the job to enter the queue. 
end 

これは悪い方法で失敗しています。これにより、50、60、またはそれ以上のジョブがスケジュールされます。原因は、キューがジョブによって直接投入されるのではなく、ジョブがキューに入るまでに時間がかかることです。そのため、メソッドqueue.sizeは数秒間0を返し、実際のキューサイズを取得します。

更新日: 問題が見つかりました。ジョブをスケジュールするために使用するクラスは設定されていることが判明し、SomeJob.set(wait:wait_time)、wait_timeは0でした。アクティブなジョブは、ジョブをしばらくスケジュールされたセットに入れますキューに入る前に、1秒未満の時間)。これは、queue.sizeが私が待ち行列にあると予想したものを反映していなかった理由です。

答えて

-1

queueが既に初期化されているため、ジョブがエンキューされるたびに新しいqueueオブジェクトが再初期化されないため、この問題が発生しています。それはあなたが言うように「リアルタイムで更新」再初期化よりも

は、より効率的な(同様にあなたが持っているだろう方法は、ActiveRecordのオブジェクトに#reloadを呼び出す)はありません、同じ効果:

size = queue.size 
max_queue_size = 10 
number_of_jobs_to_perform = max_queue_size - size 

number_of_jobs_to_perform = 0 if number_of_jobs_to_perform < 0 

number_of_jobs_to_perform.times do 
    SomeJob.perform_later(args) 
end 

編集:本当に必要な場合は、Proc.new { queue.size }.times do ...

+0

などのprocを使用してください。SidekiqはRedisリストをキューとして使用しています。問題は、Redisクライアントを作成してそれを使用してキューのサイズやキューの内容をチェックしても、すぐに正しいサイズが返されないことです。これはRedisのリストの仕組みではありません。 Redisはシングルスレッドなので、要素をリストにプッシュしてサイズをチェックすると、リストがすでに更新されており、サイズが正しいことがわかります。 –

+0

これは、Sidekiqがキューの人口を何とか遅らせることを意味しています。 –

+0

私はそれがおそらくちょうどsub-msの待ち時間のようにそれを遅らせているとは思わない。 https://github.com/mperham/sidekiq/blob/master/lib/sidekiq/api.rb#L218 しかし、関係なく、あなたの 'queue.size'はrubyインタープリタによって一度読み込まれ、ループは' 'queue.size'は整数です。 procが助けなければならない。 –

関連する問題