modern-di integration for arq.
Full guide: arq integration docs
Usage example: examples/
Installation
uv add modern-di-arq # or: pip install modern-di-arq
Usage
setup_di seeds the root container into arq's ctx dict and wires four of arq's lifecycle hooks: on_startup/on_shutdown open and close the root container, on_job_start builds a Scope.REQUEST child container per job, and on_job_end closes it as a fallback.
Decorate a task with @inject to resolve its FromDI-marked parameters from that per-job child. The child is open from on_job_start until the last @inject-decorated call for the job exits, which closes it. Nested and concurrent (asyncio.gather) @inject calls over the same job share the one child through a reference count, so it closes exactly once, and teardown still happens if arq skips on_job_end.
import typing
from arq.connections import RedisSettings
from modern_di import Container, Group, Scope, providers
from modern_di_arq import FromDI, inject, setup_di
class Settings:
def __init__(self) -> None:
self.greeting = "hello"
class Greeter:
def __init__(self, settings: Settings) -> None: # auto-injected by type
self._settings = settings
def greet(self, name: str) -> str:
return f"{self._settings.greeting}, {name}"
class AppGroup(Group):
settings = providers.Factory(Settings, scope=Scope.APP, cache=True)
greeter = providers.Factory(Greeter, scope=Scope.REQUEST)
@inject
async def greet(
ctx: dict[str, typing.Any], # arq passes its context dict as the first argument
name: str,
greeter: typing.Annotated[Greeter, FromDI(Greeter)], # resolve by type
) -> str:
return greeter.greet(name)
class WorkerSettings:
functions = [greet]
redis_settings = RedisSettings(host="localhost")
container = Container(groups=[AppGroup])
setup_di(WorkerSettings, container)
container.validate() # optional fail-fast check of the provider graph
Run the worker as usual (arq mymodule.WorkerSettings) and enqueue jobs with only their real arguments, as in await pool.enqueue_job("greet", "world"). The FromDI parameters are resolved for you. A task must declare arq's ctx dict as its first parameter; injection is order-insensitive otherwise. arq's ctx is a plain dict (not a dedicated message type), so no context provider is registered. Read job metadata from ctx, and fetch_di_container(ctx) returns the root container.
API
| Symbol | Description |
|---|---|
setup_di(worker_settings, container) |
Seeds the root container into arq's ctx and wires root + per-job lifecycle onto on_startup/on_shutdown/on_job_start/on_job_end. Accepts a WorkerSettings class/object or a settings dict; composes with existing hooks; returns the container. Raises TypeError if called twice on the same worker_settings |
FromDI(dependency) |
Inert marker for Annotated[T, FromDI(...)] in task signatures; accepts a provider instance or a type |
inject(task) |
Decorator that resolves FromDI-annotated parameters from the per-job Scope.REQUEST child. Order-insensitive; passthrough for tasks with no FromDI; raises TypeError at decoration if the task also declares *args/**kwargs. Raises RuntimeError naming setup_di when a job reaches it without the modern-di hooks installed |
fetch_di_container(ctx) |
Returns the root container from an arq ctx dict |
📦 PyPI
📝 License
Part of modern-python
Built on modern-di, a dependency-injection framework with an IoC container and scopes.
Browse the full list of templates and libraries in
modern-python; the org profile has the categorized index.
Metadata
Release files for modern-di-arq 4.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| modern_di_arq-4.0.0.tar.gz | 6.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| modern_di_arq-4.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 13.5 kB
Release files / modern_di_arq-4.0.0.tar.gz
| Download URL | modern_di_arq-4.0.0.tar.gz |
|---|---|
| Size | 6.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54307b4221241717fdf7ebb86629a0835bba40cb51a02ba93a1763605e30993b
|
|
BLAKE2b-256 checksum How to use checksums |
f2270a9a725327b4dc2e2566ae8635fe74bd2279ad49a19b25e948d5d84767d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / modern_di_arq-4.0.0-py3-none-any.whl
| Download URL | modern_di_arq-4.0.0-py3-none-any.whl |
|---|---|
| Size | 6.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
78261e5d59d395740f2b7af4c3a8dee58f247645aab7eef4bb6c44472c24bba3
|
|
BLAKE2b-256 checksum How to use checksums |
f6aa46f4ffcbb77d50f451fd394b31d0899479aa3fcf4d5d6dceca649ccb3407
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.24 {"installer":{"name":"uv","version":"0.12.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|