For discussions, check out the [associated PR](https://github.com/RealOrangeOne/django-background-worker-rfc/pull/1) and [Discussions](https://github.com/RealOrangeOne/django-background-worker-rfc/discussions).
Django currently doesn't have a first-party solution for long-running tasks. Other frameworks such as Laravel have background workers, allowing them to push tasks into the background to be processed at a later date, without requiring the end user to wait for them to occur.
One of the key goals behind this proposal is removing the requirement for the user to wait for tasks they don't need to, moving computation and complexity out of the request-response cycle, towards dedicated background worker processes.
This proposed implementation specifically doesn't assume anything about the user's setup. This not only reduces the chances of Django conflicting with existing task systems a user may be using (eg Celery, RQ), but also allows it to work with almost any hosting environment a user might be using.
A prime example of this kind of improvement is re-indexing pages in Wagtail (where this RFC began). Currently, when a user publishes a page, the "Publish" action also re-indexes the page, so changes are reflected in the search index, which slows down the request unnecessarily. The user doesn't need to wait for the indexes to be updated, meaning they could continue with whatever they need to do next faster. By moving tasks into the background, it also means longer tasks don't tie up the application server, meaning it should be able to handle more traffic.
Other CMSs such as WordPress and Drupal have background workers to accelerate these kinds of non-blocking tasks. These APIs allow both for the tools themselves to push tasks to the background, but also for users to submit tasks themselves.
## Requirements
This feature has some basic requirements for it to be considered "complete":
- Users should need to neither know nor care about the specific implementation details. This includes which backend is being used (mostly applicable to library authors)
The proposed implementation will be in the form of an application wide "Job backend". This backend will be what connects Django to the task runners. The job backend will provide an interface for either third-party libraries, or application developers to specify how jobs should be created and pushed into the background
The default backend will not push jobs into the background, instead running them in-band. This means the change is backwards compatible with current Django, and can be adopted slowly.
Django will also ship with an ORM-powered backend for users to transition too easy should they want the powers of a background worker without a large infrastructure migration or commitment. Whilst this backend will be designed to be performant enough, and considered fine for production use, it won't be designed to fully scale to all needs, and so tools such as Redis still have a place.
In the initial implementation, `enqueue` will not return anything. A response object which tracks in-flight tasks may be possible in a future iteration.
`args` and `kwargs` are intentionally their own dedicated arguments to make the API simpler and backwards-compatible should other attributes be added in future.
#### Deferring tasks
Tasks may also be "deferred" to run at a specific time:
For Django [signals](https://docs.djangoproject.com/en/stabke/ref/signals/), there will be an additional property passed when registering the signal, which will transparently convert the signal to a task, and ensure it's submitted as a task when the signal should be called. Only certain hooks will support background tasks. Others, such as those for requests or migrations, must be run synchronously, and so will raise an error.
Whilst it's possible to define tasks anywhere in an application, the convention will be to put them in a `tasks.py` file, and manually import them during `AppConfig.ready`.
Where the underlying implementation supports it, backends may also provide an `async`-compatible interface for scheduling tasks, using `a`-prefixed methods:
Library maintainers currently must resort to introspecting their runtime, or defining hooks to allow integrators to defer certain code paths to the background