diff --git a/django_celery_monitor/admin.py b/django_celery_monitor/admin.py index 25d8a9e6..64538bca 100644 --- a/django_celery_monitor/admin.py +++ b/django_celery_monitor/admin.py @@ -1,7 +1,7 @@ """Result Task Admin interface.""" from __future__ import absolute_import, unicode_literals -from __future__ import absolute_import, unicode_literals +import ast from django.contrib import admin from django.contrib.admin import helpers @@ -15,6 +15,7 @@ from celery import current_app from celery import states from celery.task.control import broadcast, revoke, rate_limit +from celery.utils.imports import symbol_by_name from celery.utils.text import abbrtask from .admin_utils import action, display_field, fixedwidth @@ -32,6 +33,8 @@ NODE_STATE_COLORS = {'ONLINE': 'green', 'OFFLINE': 'gray'} +RETRY_TASK_COUNTDOWN = 10 + class MonitorList(main_views.ChangeList): """A custom changelist to set the page title automatically.""" @@ -191,6 +194,19 @@ def kill_tasks(self, request, queryset): revoke(state.task_id, connection=connection, terminate=True, signal='KILL') + @action(_('Retry selected tasks')) + def retry_tasks(self, request, queryset): + with current_app.default_connection() as connection: + for state in queryset: + task = symbol_by_name(state.name) + kwargs = { + 'args': ast.literal_eval(state.args), + 'kwargs': ast.literal_eval(state.kwargs), + 'countdown': RETRY_TASK_COUNTDOWN, + 'connection': connection + } + task.apply_async(**kwargs) + @action(_('Rate limit selected tasks')) def rate_limit_tasks(self, request, queryset): tasks = set([task.name for task in queryset])