web-dev-qa-db-fra.com

Comment annuler un travail planifié avec delay_job dans Rails?

Je programme un travail à exécuter dans 10 minutes. Comment annuler correctement ce travail particulier sans utiliser aucun type de champs supplémentaires encrassés dans le modèle, etc. Existe-t-il un appel à supprimer un travail particulier ou des travaux liés à un modèle, une instance, etc. spécifique?

36
mdrozdziel

disclaimer: Je ne suis pas un utilisateur expert de delay_job ...

" Existe-t-il un appel à supprimer un travail particulier ou des travaux liés à un modèle, une instance, etc.? "

Delayed :: Job est simplement un objet ActiveRecord afin que vous puissiez trouver et détruire l'un de ces enregistrements. Selon votre cas d'utilisation, cela peut être traité de différentes manières. Si quelqu'un va les détruire manuellement, cela peut être géré via une interface d'administration de votre application Web. 

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

si vous avez besoin d'une tâche hors processus pour supprimer des travaux par "type de travail", vous pouvez les parcourir en boucle et les supprimer si cela correspond à votre travail; essayez ceci dans script/console

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"

donc, compte tenu de ce qui précède, si vous souhaitez supprimer tous les travaux de type MyJob

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

cela peut ou peut ne pas aider pour votre situation? dans de nombreux cas, vous voudrez peut-être supprimer un MyJob, mais uniquement dans les cas où l'attribut: some_value était «abc» et non «xyz». Dans ce cas, vous devrez peut-être implémenter un 'display_name' sur votre objet MyJob. job.name l'utilisera s'il existe

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"

de cette façon, vous pourriez être plus sélectif quant aux enregistrements à supprimer?

espérons que cela vous donne assez d'informations sur les moyens possibles de le gérer?

50
house9

delay_job 3 a introduit un attribut queue. Cela peut être détourné pour planifier un travail annulable.

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

Vous pouvez également envisager d'utiliser la méthode payload_object du travail retardé, si vous recherchez un travail uniquement via son paramètre transmis.

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

Cet exemple simpliste n'utilise pas pleinement l'objet payload_object renvoyé:

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

0
fitchMitch