django-domain-events
A Django domain-event log with in-process fan-out.
fire() records a typed event to a database table inside the caller's
transaction; a relay delivers it to registered receivers afterwards,
at-least-once, with per-receiver retry and dead-lettering. The event exists if
and only if the change committed.
This is not a signals replacement. A database write per event rules out chatty notification use, and buys three things signals cannot give you: a crash story, durable attribution for who caused what, and an event log you can query.
Install
pip install django-domain-events
Add it to INSTALLED_APPS and migrate:
INSTALLED_APPS = [..., "django.contrib.auth", "django_domain_events"]
django.contrib.auth is required: the event row carries a nullable foreign key
to AUTH_USER_MODEL so attribution survives, and the migration depends on it.
python manage.py migrate
Nested event payloads need the decode half of the codec:
pip install "django-domain-events[dacite]"
Quickstart
Declare an event and something that listens for it:
# orders/events.py
from dataclasses import dataclass
from django_domain_events import DURABLE, event, receiver
@event
@dataclass(frozen=True, slots=True)
class OrderPlaced:
order_id: int
total_cents: int
@receiver(OrderPlaced, mode=DURABLE)
def reserve_stock(evt: OrderPlaced) -> None: ...
Fire it inside the transaction that makes the change:
with transaction.atomic():
order = Order.objects.create(...)
fire(OrderPlaced(order_id=order.id, total_cents=order.total_cents))
The event row and one delivery row per durable receiver are written in that same transaction. Run the relay to deliver what is owed:
python manage.py deliver_events # claim and deliver continuously
python manage.py deliver_events --once # one pass, for cron or CI
The relay claims with SELECT ... FOR UPDATE SKIP LOCKED under a lease, so you
can run as many as you like: two workers never take the same row, and one that
dies without acknowledging has its rows reclaimed when the lease lapses. Failed
deliveries retry with exponential backoff and full jitter, then dead-letter.
Add eager=True to a receiver to also attempt it immediately after commit, in
the firing process, with the relay as the fallback.
In tests, drain_outbox() runs the real delivery path to completion, and
assert_fired(OrderPlaced, times=1) reads the log rather than a mock.
Delivery modes
Two independent knobs, not one enum. Timing is what a receiver promises about the
transaction; where its code runs is a separate question, and only meaningful for
DURABLE.
| Mode | Runs | Can veto | Recoverable |
|---|---|---|---|
INLINE |
inside the transaction | yes, by raising | not needed: its failure is a rollback |
ON_COMMIT |
after commit, in the firing process | no | no |
DURABLE (default) |
after commit, at-least-once, retried | no | yes |
For a receiver that touches only this database, the work and the acknowledgement commit together, so delivery is effectively once: the duplicate an at-least-once system owes you cannot be observed. Receivers with side effects outside the database are at-least-once, as promised.
Status
Early development. The API is not stable and the package is not yet usable; see the changelog for what has landed.
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 django_domain_events-0.2.0.tar.gz.
File metadata
- Download URL: django_domain_events-0.2.0.tar.gz
- Upload date:
- Size: 146.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec3c4583128f4f45f58d6b52d916d7c10a93aed1f0d57a8a06c501df7ad0d819
|
|
| MD5 |
2fa15b59bce3ca84b9a9204c04a6a4ab
|
|
| BLAKE2b-256 |
ccc6c8e3d97057e8fa6c7388e62e3a7030beeba4743fe9c13d5425bbf72fa438
|
Provenance
The following attestation bundles were made for django_domain_events-0.2.0.tar.gz:
Publisher:
release.yml on Artui/django-domain-events
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_domain_events-0.2.0.tar.gz -
Subject digest:
ec3c4583128f4f45f58d6b52d916d7c10a93aed1f0d57a8a06c501df7ad0d819 - Sigstore transparency entry: 2664713752
- Sigstore integration time:
-
Permalink:
Artui/django-domain-events@4a199a10c9296ec5aa7654bfdbae7ab196de49d3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Artui
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4a199a10c9296ec5aa7654bfdbae7ab196de49d3 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_domain_events-0.2.0-py3-none-any.whl.
File metadata
- Download URL: django_domain_events-0.2.0-py3-none-any.whl
- Upload date:
- Size: 37.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a323fc103298fee849c762d8fea6b5acbe17442251f35ced05d730fa8286a901
|
|
| MD5 |
16637f021c713f07c90a6e91227849ad
|
|
| BLAKE2b-256 |
ba75c1da53165265f72a7c5a5e272a1f54fa549a968ec568a84b5dd8c8b5171d
|
Provenance
The following attestation bundles were made for django_domain_events-0.2.0-py3-none-any.whl:
Publisher:
release.yml on Artui/django-domain-events
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_domain_events-0.2.0-py3-none-any.whl -
Subject digest:
a323fc103298fee849c762d8fea6b5acbe17442251f35ced05d730fa8286a901 - Sigstore transparency entry: 2664713785
- Sigstore integration time:
-
Permalink:
Artui/django-domain-events@4a199a10c9296ec5aa7654bfdbae7ab196de49d3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Artui
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4a199a10c9296ec5aa7654bfdbae7ab196de49d3 -
Trigger Event:
push
-
Statement type: