Skip to content

Commit a608fc1

Browse files
committed
Delete and retry tasks through Django Admin
1 parent 66213ba commit a608fc1

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

Diff for: django_tasks/backends/database/admin.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,23 @@
33
from django.contrib import admin
44
from django.http import HttpRequest
55

6+
from django_tasks.task import ResultStatus
7+
68
from .models import DBTaskResult
79

810

11+
def reenqueue(modeladmin: admin.ModelAdmin, request, queryset):
12+
tasks = queryset.update(status=ResultStatus.NEW)
13+
modeladmin.message_user(request, f"Rescheduled {tasks} tasks.", "SUCCESS")
14+
15+
16+
def duplicate(modeladmin: admin.ModelAdmin, request, queryset):
17+
tasks = DBTaskResult.objects.bulk_create(
18+
old_task.duplicate() for old_task in queryset
19+
)
20+
modeladmin.message_user(request, f"Rescheduled {tasks} tasks.", "SUCCESS")
21+
22+
923
@admin.register(DBTaskResult)
1024
class DBTaskResultAdmin(admin.ModelAdmin):
1125
list_display = (
@@ -19,17 +33,13 @@ class DBTaskResultAdmin(admin.ModelAdmin):
1933
"queue_name",
2034
)
2135
list_filter = ("status", "priority", "queue_name")
36+
actions = [reenqueue, duplicate]
2237

2338
def has_add_permission(
2439
self, request: HttpRequest, obj: Optional[DBTaskResult] = None
2540
) -> bool:
2641
return False
2742

28-
def has_delete_permission(
29-
self, request: HttpRequest, obj: Optional[DBTaskResult] = None
30-
) -> bool:
31-
return False
32-
3343
def has_change_permission(
3444
self, request: HttpRequest, obj: Optional[DBTaskResult] = None
3545
) -> bool:

Diff for: django_tasks/backends/database/models.py

+10
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,13 @@ def set_failed(self, exc: BaseException) -> None:
169169
logger.exception("Task id=%s unable to save exception", self.id)
170170
self.result = None
171171
self.save(update_fields=["status", "finished_at", "result"])
172+
173+
def duplicate(self):
174+
return type(self)(
175+
args_kwargs=self.args_kwargs,
176+
priority=self.priority,
177+
task_path=self.task_path,
178+
queue_name=self.queue_name,
179+
backend_name=self.backend_name,
180+
run_after=self.run_after,
181+
)

Diff for: tests/tests/test_database_backend.py

+19
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from django_tasks import ResultStatus, Task, default_task_backend, tasks
2020
from django_tasks.backends.database import DatabaseBackend
21+
from django_tasks.backends.database.backend import TaskResult
2122
from django_tasks.backends.database.management.commands.db_worker import (
2223
logger as db_worker_logger,
2324
)
@@ -593,6 +594,8 @@ def test_worker_with_locked_rows(self) -> None:
593594
}
594595
)
595596
class DatabaseTaskResultTestCase(TransactionTestCase):
597+
run_worker = partial(call_command, "db_worker", verbosity=0, batch=True, interval=0)
598+
596599
def execute_in_new_connection(self, sql: Union[str, QuerySet]) -> Sequence:
597600
if isinstance(sql, QuerySet):
598601
sql = str(sql.query)
@@ -792,3 +795,19 @@ def test_get_locked_with_locked_rows(self) -> None:
792795
)
793796
finally:
794797
new_connection.close()
798+
799+
def test_duplicate(self) -> None:
800+
result_1 = cast(TaskResult, test_tasks.calculate_meaning_of_life.enqueue())
801+
db_result_1 = result_1.db_result
802+
db_result_2 = result_1.db_result.duplicate()
803+
db_result_2.save()
804+
result_2 = db_result_2.task_result
805+
806+
assert db_result_1.pk != db_result_2.pk
807+
808+
self.run_worker()
809+
810+
result_1.refresh()
811+
result_2.refresh()
812+
813+
assert result_1.result == result_2.result

0 commit comments

Comments
 (0)