[WIP] Feedback request: task framework

Review Request #14501 — Created July 9, 2025 and updated

Information

Review Board
master

Reviewers

This change adds the beginnings of celery-based tasks for Review Board
proper. The stuff that's worth looking at now are:

reviewboard/celery.py:

Setup for core Celery instance. This is used both in the web-server
(from reviewboard.initialize()) and the worker (via the worker_init
signal).

reviewboard/tasks.py:

Base definitions for task classes and decorators. This has:

  • Task: The base class for tasks which can run in the "django"
    context. This provides an API kind of similar to the otherwise
    too-early-to-use django-tasks, where we can use .using() to set
    defaults for how the task is invoked, and .enqueue() to actually
    queue the task (preserving type hinting). This class also handles
    serialization of Pydantic models for tasks which use it.

  • MaybeEagerTask: A base class that can be used for "core" tasks that
    may need database access. This allows us to have those tasks run eager
    in the devserver, but use a worker if available. I will be enhancing
    this to also check the task_worker_enabled setting, so depending on
    what we end up doing for deployment (and upgrades), existing users can
    still have any tasks work even without a worker present.

  • @task: A decorator to create tasks that use Task as the base class
    by default, as well as preserve typing on the decorated methods.

  • ExternalTask and @external_task: A class and decorator that work
    similar to Task and @task, but does not register the task with
    the celery instance, and uses celery.send_task() directly to invoke
    it. This allows us to decorate a stub function inside the RB code,
    but have the task implementation live elsewhere (for example, the
    Review Bot extension would use this, and then the task implementation
    actually lives in the worker).

 
Summary ID
[WIP] Feedback request: task framework
This change adds the beginnings of celery-based tasks for Review Board proper. The stuff that's worth looking at now are: `reviewboard/celery.py`: ----------------------- Setup for core Celery instance. This is used both in the web-server (from `reviewboard.initialize()`) and the worker (via the `worker_init` signal). `reviewboard/tasks.py`: ----------------------- Base definitions for task classes and decorators. This has: * `Task`: The base class for tasks which can run in the "django" context. This provides an API kind of similar to the otherwise too-early-to-use `django-tasks`, where we can use `.using()` to set defaults for how the task is invoked, and `.enqueue()` to actually queue the task (preserving type hinting). This class also handles serialization of Pydantic models for tasks which use it. * `MaybeEagerTask`: A base class that can be used for "core" tasks that may need database access. This allows us to have those tasks run eager in the devserver, but use a worker if available. I will be enhancing this to also check the `task_worker_enabled` setting, so depending on what we end up doing for deployment (and upgrades), existing users can still have any tasks work even without a worker present. * `@task`: A decorator to create tasks that use `Task` as the base class by default, as well as preserve typing on the decorated methods. * `ExternalTask` and `@external_task`: A class and decorator that work similar to `Task` and `@task`, but does not register the task with the celery instance, and uses `celery.send_task()` directly to invoke it. This allows us to decorate a stub function inside the RB code, but have the task implementation live elsewhere (for example, the Review Bot extension would use this, and then the task implementation actually lives in the worker).
263c5d62813ea4d4779b588a099e358bec52cc73
Description From Last Updated

continuation line missing indentation or outdented Column: 14 Error code: E122

reviewbotreviewbot

'typing.cast' imported but unused Column: 1 Error code: F401

reviewbotreviewbot
Checks run (1 failed, 1 succeeded)
flake8 failed.
JSHint passed.

flake8