web-dev-qa-db-ja.com

Railsのdelayed_jobでスケジュールされたジョブをキャンセルする方法は?

私は、たとえば10分で実行するジョブをスケジュールしています。モデルなどでダーティな追加フィールドを使用せずに、この特定のジョブを適切にキャンセルする方法。特定のジョブ、または特定のモデル、インスタンスなどに関連するジョブを削除する呼び出しはありますか?

37
mdrozdziel

免責事項:私はdelay_jobのエキスパートユーザーではありません...

"特定のジョブ、または特定のモデル、インスタンスなどに関連するジョブを削除する呼び出しはありますか?"

Delayed :: Jobは単なるActiveRecordオブジェクトなので、これらのレコードを見つけて破棄できます。ユースケースに応じて、これはさまざまな方法で処理できます。誰かが手動でそれらを破壊しようとしている場合、これはあなたのウェブアプリの管理インターフェースを介して処理される可能性があります。

# list all jobs
Delayed::Job.all
# find a job by id
job = Delayed::Job.find(params[:id])
# delete it
job.delete

「ジョブタイプ」でジョブを削除するプロセス外のタスクが必要な場合は、各ジョブをループして、ジョブに一致する場合は削除できます。スクリプト/コンソールでこれを試してください

class MyJob < Struct.new(:some_value);
    def perform
        # ...
    end
end

my_job = MyJob.new('xyz')
job = Delayed::Job.enqueue(my_job, 0, 1.hour.from_now)
job.name
# => "MyJob"
job.handler
# => "--- !Ruby/struct:MyJob \nsome_value: xyz\n"

したがって、MyJobタイプのすべてのジョブを削除する場合は、上記を与えます

Delayed::Job.all.each do |job|
    if job.name == "MyJob" then
        job.delete
    end
end

これはあなたの状況に役立つかもしれないし、そうでないかもしれませんか?多くの場合、MyJobを削除したいのですが、:some_value属性が 'xyz'ではなく 'abc'の場合のみです。この場合、MyJobオブジェクトに「display_name」を実装する必要がある場合があります。 job.nameは、存在する場合にこれを使用します

class MyJob < Struct.new(:user_id);
    def perform
        # ...
    end

    def display_name
        return "MyJob-User-#{user_id}"
    end 
end

# store reference to a User
my_job = MyJob.new(User.first.id) # users.id is 1
job = Delayed::Job.enqueue(my_job, 0, 1.hour.from_now)
job.name
# => "MyJob-User-1"
job.handler
# => "--- !Ruby/struct:MyJob \nuser_id: 1\n"

この方法で、どのレコードを削除するかをより選択できますか?

うまくいけば、これはあなたにそれを処理するための可能な方法に関する十分な情報を提供しますか?

52
house9

delay_job 3にqueue属性が導入されました。これをハイジャックして、キャンセル可能なジョブをスケジュールできます。

class MyJob < Struct.new(:user_id)
  def self.queue_name
    "something-unique"
  end

  def perform
    # ...
  end
end

#scheduler
my_job = MyJob.new(User.first.id)
#'cancel' pending jobs first
Delayed::Job.where(queue: my_job.class.queue_name).destroy_all
#queue it up
Delayed::Job.enqueue(my_job,
  queue: my_job.class.queue_name,
  run_at: 1.hour.from_now
)
7
firien

渡されたパラメーターのみを介してジョブを探している場合は、遅延ジョブのpayload_objectメソッドの使用も検討できます。

Delayed::Job.all.each do |job|
  job.destroy if job_corresponds_to_target?(job, target)
end

def job_corresponds_to_target?(job, target)
  job.payload_object.args.first == target.id
end

このシンプルリストの例では、返されたpayload_objectを完全には使用していません。

=> #<Delayed::PerformableMethod:0x0056551eae3660 @object=ReminderMailJob, @method_name=:perform_later, @args=[3]> 

0
fitchMitch