A queue agnostic worker for Django's task framework.
Project description
Threadmill
Documentation |
Issues |
Changelog |
Funding 💚
A queue agnostic worker for Django's task framework.
Design Principles
- Durability – We recover from any failures, even poorly written tasks.
- Consistency – We never lose data, even if someone unplugs the power or network.
- Utilization – We keep the CPU saturated with tasks, not with idle time or waiting for locks.
[!WARNING] Threadmill requires a development version of Django and is in a preview stage.
Setup
You need to have [Django's Task framework][django-tasks] setup properly.
uv add threadmill
Add threadmill to your INSTALLED_APPS in settings.py:
# settings.py
INSTALLED_APPS = [
"threadmill",
# ...
]
Finally, you launch the worker pool:
uv run manage.py threadmill
Usage
The workers are inspired by Gunicorn, and the CLI is very similar.
Utilization
Depending on your workload, you can tweak the number of processes and threads. Processes allow for parallel compute (no GIL) while threads are great for low-memory concurrent IO.
uv run manage.py threadmill --processes 4 --threads 2
Health
If your tasks leak memory, you can recycle (restart) the workers after a certain number of tasks have been processed:
uv run manage.py threadmill --max-tasks 1000 --max-tasks-jitter 100
This will restart the workers after 1000 tasks have been processed, with a random jitter of up to 100 tasks to avoid all workers restarting at the same time.
Should a worker crash or be killed, the pool will automatically restart it.
Shutdown
A graceful shutdown is possible with the SIGTERM or a keyboard interrupt.
All workers will finish the tasks they acquired and publish them.
You can use --exit-empty to exit immediately after all tasks have been processed,
which might be useful for draining a one-off queue.
Task Backlog
You can prefetch tasks from a queue to avoid IO latency bottlenecks. However, this will increase the memory usage of the worker pool.
uv run manage.py threadmill --prefetch 100
Task Timeouts
[!WARNING] Work in progress, this feature is not yet stable.
Task timeouts are important to ensure the long-term health of your pool. However, they need to be aligned with your queueing system's timeout settings. The message queue needs to requeue a task that hasn't been acknowledged within the timeout.
Integration
[!NOTE] This section is for people who want to integrate Threadmill into their queueing system.
Threadmill is designed to be durable and requires a queueing system to support late acknowledgement.
To use Threadmill, your backend will need to inherit from threadmill.backends.AcknowledgeableTaskBackend and implement the following methods:
class AcknowledgeableTaskBackend(BaseTaskBackend, ABC):
"""Provide an interface for tasks queues to be processed by the executor."""
def acquire(
self, *queue_names: str, timeout: datetime.timedelta | None = None
) -> TaskResult:
"""
Return and lock the next task to be processed without removing it from the queue.
Args:
queue_names: The names of the queues to acquire tasks from.
timeout: The maximum time to wait for a task. If None, wait indefinitely.
Raises:
TimeoutError: If no task is available within the specified timeout.
"""
raise NotImplementedError
def acknowledge(self, task_result: TaskResult) -> None:
"""Remove the task from the queue and publish the result."""
raise NotImplementedError
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file threadmill-0.1.0.tar.gz.
File metadata
- Download URL: threadmill-0.1.0.tar.gz
- Upload date:
- Size: 10.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0500bb9e47c08415cc7bea74cac81400cd512d9f28dd9e4842b61bfe0e48963
|
|
| MD5 |
6d8ba54707196b82f3da6a95d0f8b9fa
|
|
| BLAKE2b-256 |
2570e05df7545ce28acd6afc9503dd3d31c0c8f7b1e0f916de864caa6e500047
|
Provenance
The following attestation bundles were made for threadmill-0.1.0.tar.gz:
Publisher:
release.yml on codingjoe/threadmill
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
threadmill-0.1.0.tar.gz -
Subject digest:
d0500bb9e47c08415cc7bea74cac81400cd512d9f28dd9e4842b61bfe0e48963 - Sigstore transparency entry: 1704058442
- Sigstore integration time:
-
Permalink:
codingjoe/threadmill@7270fd3201cd67f0c48a2ad4bc181a65e8a3244c -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/codingjoe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7270fd3201cd67f0c48a2ad4bc181a65e8a3244c -
Trigger Event:
release
-
Statement type:
File details
Details for the file threadmill-0.1.0-py3-none-any.whl.
File metadata
- Download URL: threadmill-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56dd47f276bf46b9614c041d8dd363fe3940c4bd94b6522f4fe68b00d5d95117
|
|
| MD5 |
89da336cdb5ec7c4d98e522a4ec489f4
|
|
| BLAKE2b-256 |
ee886da3c927c2b20a0b8d459f503b90dfd0130aa5c98b6c3d021b46c80522ee
|
Provenance
The following attestation bundles were made for threadmill-0.1.0-py3-none-any.whl:
Publisher:
release.yml on codingjoe/threadmill
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
threadmill-0.1.0-py3-none-any.whl -
Subject digest:
56dd47f276bf46b9614c041d8dd363fe3940c4bd94b6522f4fe68b00d5d95117 - Sigstore transparency entry: 1704058451
- Sigstore integration time:
-
Permalink:
codingjoe/threadmill@7270fd3201cd67f0c48a2ad4bc181a65e8a3244c -
Branch / Tag:
refs/tags/0.1.0 - Owner: https://github.com/codingjoe
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7270fd3201cd67f0c48a2ad4bc181a65e8a3244c -
Trigger Event:
release
-
Statement type: