Fix: keep Celery's Django task base for file move scoped tasks

Passing task_cls to Celery replaces the Django fixup's default DjangoTask, so FileMoveScopedTask, built on the plain Task, left every task without delay_on_commit. The workflow AI suggestions trigger failed with an AttributeError.

FileMoveScopedTask now subclasses DjangoTask, which only needs django.db.transaction and is safe to import before apps load. The task scope test also asserts tasks are DjangoTask instances.
This commit is contained in:
stumpylog committed 2026-11-03 15:09:30 -08:00
1 parent 61b9bc3367
commit 7d5e7b1625
2 files changed
+8 -2

No files matched your search

+3
View File
@@ -9,6 +9,7 @@ from typing import TYPE_CHECKING
import pytest
from asgiref.sync import async_to_sync
from asgiref.sync import sync_to_async
from celery.contrib.django.task import DjangoTask
from django.db import transaction
from django.http import HttpRequest
from django.http import HttpResponse
@@ -777,10 +778,12 @@ class TestCeleryTaskScope:
- A registered task is inspected
THEN:
- It runs through FileMoveScopedTask
- It keeps Celery's DjangoTask API, such as delay_on_commit
"""
from paperless.celery import FileMoveScopedTask
assert isinstance(bulk_update_documents, FileMoveScopedTask)
assert isinstance(bulk_update_documents, DjangoTask)
def test_failing_task_still_moves_committed_change(
self,
+5 -2
View File
@@ -1,7 +1,7 @@
import os
from celery import Celery
from celery import Task
from celery.contrib.django.task import DjangoTask
from celery.signals import worker_process_init
from kombu.serialization import register
@@ -28,12 +28,15 @@ register(
)
class FileMoveScopedTask(Task):
class FileMoveScopedTask(DjangoTask):
"""
Run every task inside a document file move scope, so each document a task
changes is moved once when the task ends, after its writes have committed.
The scope also flushes when the task raises, for writes that committed
before the failure.
Subclasses DjangoTask because a custom task_cls replaces the Django fixup's
default, and delay_on_commit lives there.
"""
def __call__(self, *args, **kwargs):