ti-enxame.com

Como cancelar o trabalho agendado com delayed_job no Rails?

Estou agendando um trabalho para rodar em 10 minutos. Como cancelar corretamente esse trabalho em particular sem usar nenhum tipo de campo extra sujo no modelo e assim por diante. Existe alguma chamada para remover um trabalho específico ou trabalhos relacionados a modelos, instâncias, etc. específicos?

36
mdrozdziel

disclaimer: Eu não sou um usuário especialista de delayed_job ...

" Existe alguma chamada para remover determinado trabalho, ou trabalhos relacionados a modelo específico, instância, etc? "

Delayed :: Job é apenas um objeto ActiveRecord para que você possa encontrar e destruir qualquer um desses registros. Dependendo do seu caso de uso, isso pode ser feito de maneiras diferentes. Se alguém for destruí-los manualmente, isso pode ser feito por meio de uma interface administrativa no seu aplicativo da web.

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

se você precisar de alguma tarefa fora do processo de exclusão de trabalhos por 'tipo de trabalho', você pode passar por cada um deles e excluí-lo se corresponder ao seu trabalho; tente isso no 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"

assim, dado o acima, se você quisesse apagar todos os trabalhos do tipo MyJob

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

isso pode ou não ajudar na sua situação? em muitos casos, você pode querer excluir um MyJob, mas somente quando o atributo: some_value for 'abc' e não 'xyz'. Neste caso, você pode precisar implementar um 'display_name' no seu objeto MyJob. job.name usará isto se existir

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"

dessa forma, você poderia ser mais seletivo sobre quais registros excluir?

espero que isso lhe dê informações suficientes sobre possíveis maneiras de lidar com isso?

50
house9

delayed_job 3 introduziu um atributo queue. Isso pode ser seqüestrado para agendar um trabalho cancelável.

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

Você também pode considerar o uso do método payload_object do trabalho atrasado, se estiver procurando um trabalho somente através do parâmetro passado.

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

Este exemplo simplista não usa totalmente o payload_object retornado:

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

0
fitchMitch