Я использую 3.1.20 (брокер и бэкэнд Redis), и мне нужен способ прервать/отменить текущие запущенные задачи, когда рабочий выключается.
Смысл в том, чтобы по возможности пометить задачи как FAILED и не запускать их повторно в следующий раз, когда рабочий запустится снова.
Я запускаю одну задачу за раз, и, поскольку задача имеет побочный эффект (и я не могу это изменить), убийство работника будет ожидаемым поведением пользователя, когда что-то пойдет не так, и я не хочу, чтобы задача повторялась в следующий раз. время, когда я запускаю работника (поведение sighandler по умолчанию, я полагаю...)
Я пробовал http://stackoverflow.com/a/8230470 безуспешно.
А еще я пробовал кое-что, используя интерфейс управления или воркер из бутстепа:
from celery import Celery, bootsteps
from celery.task.control import revoke
# TODO : configuration for tests...
class BootPyrosNode(bootsteps.StartStopStep):
def __init__(self, worker, **kwargs):
logging.warn('{0!r} is starting from {1}'.format(worker, __file__))
[...]
def create(self, worker):
return self
def start(self, worker):
# our step is started together with all other Worker/Consumer
# bootsteps.
pass # not sure in which process this is run.
def stop(self, worker):
# the Consumer calls stop every time the consumer is restarted
# (i.e. connection is lost) and also at shutdown. The Worker
# will call stop at shutdown only.
logging.warn('{0!r} is stopping. Attempting abort of current tasks...'.format(worker))
for req in worker.state.active_requests:
# worker.app.control.revoke(req.id, terminate=True) # not working
# revoke(req.id, terminate=True) # not working
self.node_proc.shutdown()
установил так:
celeros_app = Celery()
# setting up custom bootstep to start ROS node and pass ROS arguments to it
celeros_app.steps['worker'].add(BootPyrosNode)
celeros_app.user_options['worker'].add(Option('-R', '--ros-arg', action="append", help='Arguments for ros initialisation'))
Однако кажется, что моя задача не может быть отозвана/прервана (возможно, из-за того, что рабочий не обрабатывает управляющие сообщения после остановки?), и у меня заканчиваются идеи.
Если вы хотите увидеть больше, код взят с: https://github.com/asmodehn/celeros.
Есть ли способ, или это настройка, которая пока невозможна?
Вы не можете отправлять команды удаленного управления себе во время выключения, вам нужно отозвать задачи, используя внутренние компоненты worker (см. Как реализована команда удаленного управления в celery/worker/control.py).
Вероятно, вам также следует убедиться, что ваш загрузочный шаг зависит от пула, чтобы ваш метод stop()
вызывался первым во время завершения работы:
class Step..:
requires = ('celery.worker.components:Pool',)
Спасибо !
Мне удалось отозвать запущенные задачи при завершении рабочего процесса. :
def stop(self, worker):
# the Consumer calls stop every time the consumer is restarted
# (i.e. connection is lost) and also at shutdown. The Worker
# will call stop at shutdown only.
logging.warn('{0!r} is stopping. Attempting termination of current tasks...'.format(worker))
# Following code from worker.control.revoke
task_ids = []
terminated = set()
# cleaning all reserved tasks since we are shutting down
signum = _signals.signum('TERM')
for request in [r for r in worker.state.reserved_requests]:
if request.id not in terminated:
task_ids.append(request.id)
terminated.add(request.id)
logger.info('Terminating %s (%s)', request.id, signum)
request.terminate(worker.pool, signal=signum)
# Aborting currently running tasks, and triggering soft timeout exception to allow task to clean up.
signum = _signals.signum('USR1')
for request in [r for r in worker.state.active_requests]:
if request.id not in terminated:
task_ids.append(request.id)
terminated.add(request.id)
logger.info('Terminating %s (%s)', request.id, signum)
request.terminate(worker.pool, signal=signum) # triggering SoftTimeoutException in Task
if terminated:
terminatedstr = ', '.join(task_ids)
logger.info('Tasks flagged as revoked: %s', terminatedstr)
self.node_proc.shutdown()
Сначала я отменяю задачу в списке зарезервированных_запросов, чтобы предотвратить выполнение любой ожидающей задачи непосредственно перед завершением работы.
Затем я отменяю активный запрос, а затем запускаю исключение SoftTimeLimitExceeded в задаче, чтобы иметь возможность инициировать поведение очистки в задаче. Поскольку я использую acks_late (для запуска только одной задачи за раз), мне нужно вернуться или подняться из задачи, чтобы правильно подтвердить ее и не перезапускать в следующий раз, когда я запускаю работника.
Я использую прерываемые задачи, но поведение прерывания закодировано для случаев, когда пользователь хочет сознательно прервать задачу, а системе необходимо выполнить сложную/долгую очистку. Этот случай больше похож на завершение рабочего процесса, и в этом случае я хочу, чтобы текущая задача быстро завершилась сбоем.
Я думаю, что это был бы правильный способ делать что-то в сельдерее?
В будущей версии было бы неплохо иметь возможность просто переопределить поведение в классе Task... например, перегрузить метод on_revoke() или on_abort(). И, возможно, способ иметь несколько вариантов поведения при отзыве, в зависимости от некоторых условий...
Просто мои 2 цента, я еще не проверял celery v4.0.
какие-либо обновления по этому поводу?
Самый полезный комментарий
Спасибо !
Мне удалось отозвать запущенные задачи при завершении рабочего процесса. :
Сначала я отменяю задачу в списке зарезервированных_запросов, чтобы предотвратить выполнение любой ожидающей задачи непосредственно перед завершением работы.
Затем я отменяю активный запрос, а затем запускаю исключение SoftTimeLimitExceeded в задаче, чтобы иметь возможность инициировать поведение очистки в задаче. Поскольку я использую acks_late (для запуска только одной задачи за раз), мне нужно вернуться или подняться из задачи, чтобы правильно подтвердить ее и не перезапускать в следующий раз, когда я запускаю работника.
Я использую прерываемые задачи, но поведение прерывания закодировано для случаев, когда пользователь хочет сознательно прервать задачу, а системе необходимо выполнить сложную/долгую очистку. Этот случай больше похож на завершение рабочего процесса, и в этом случае я хочу, чтобы текущая задача быстро завершилась сбоем.
Я думаю, что это был бы правильный способ делать что-то в сельдерее?
В будущей версии было бы неплохо иметь возможность просто переопределить поведение в классе Task... например, перегрузить метод on_revoke() или on_abort(). И, возможно, способ иметь несколько вариантов поведения при отзыве, в зависимости от некоторых условий...
Просто мои 2 цента, я еще не проверял celery v4.0.