Отмена запланированной работы Sidekiq в Rails

Для некоторых заданий Sidekiq в моем приложении запланировано изменение состояния ресурса на cancelled если пользователь не отвечает в течение определенного периода времени. Существует много информации о том, как лучше всего выполнить эту задачу, но на самом деле ни одна из них не отменяет работу.

Чтобы отменить работу, код в вики говорит:

class MyWorker
 include Sidekiq::Worker

 def perform(thing_id)
  return if cancelled?
  thing = Thing.find thing_id
  thing.renege!
 end

 def cancelled?
  Sidekiq.redis {|c| c.exists("cancelled-#{jid}") }
 end

 def self.cancel!(jid)
  Sidekiq.redis {|c| c.setex("cancelled-#{jid}", 86400, 1) }
 end
end

Тем не менее здесь предлагается, чтобы я сделал что-то вроде

 def perform(thing_id)
  thing = Thing.find thing_id
  while !cancel?(thing)
   thing.ignore!
  end
 end

 def cancel?(thing_id)
  thing = Thing.find thing_id
  thing.matched? || thing.passed?
 end

Что сбивает с толку этот и подобный код в вики, так это то, что он не отменяет работу. Приведенный выше пример просто выполняет обновление thing если cancelled? возвращается false (как и должно быть), но не отменяется, если и когда он вернет true в будущем. Это просто терпит неудачу с сообщением об ошибке перехода AASM и отправляется RetrySet. призвание MyWorker.cancel! jid в коде модели выдает неопределенную переменную ошибку. Как я могу получить доступ к этому jid в модели? Как на самом деле можно отменить или удалить эту конкретную работу? Спасибо!

3 ответа

Решение

Хорошо, так получается, у меня уже был один вопрос. Один из наборов кода, который я включил, был функционально похожей версией кода из вики. Решение другого вопроса ("как я могу получить доступ к этому jid в модели?") Кажется действительно очевидным, если вы еще не знакомы с программированием, но в основном: сохраните jid в столбце базы данных, а затем извлекайте / обновляйте его всякий раз, когда это нужно! Duh!

# The wiki code
class MyWorker
 include Sidekiq::Worker

 def perform(thing_id)
  return if cancelled?

  # do actual work
 end

 def cancelled?
  Sidekiq.redis {|c| c.exists("cancelled-#{jid}") }
 end

 def self.cancel!(jid)
  Sidekiq.redis {|c| c.setex("cancelled-#{jid}", 86400, 1) }
 end
end

# create job
jid = MyWorker.perform_async("foo")

# cancel job
MyWorker.cancel!(jid)

Вы можете сделать это, но это не будет эффективным. Это линейное сканирование для поиска запланированной работы по JID.

require 'sidekiq / api' Sidekiq:: ScheduledSet.new.find_job (jid).try (: delete) В качестве альтернативы ваша работа может посмотреть, насколько она все еще актуальна при запуске.

Другие вопросы по тегам