qx-events
NATS JetStream publisher/consumer, transactional outbox relay, and mediator-bridge event dispatcher for the Qx framework.
What lives here
qx.events.OutboxRelay— pollsqx_outbox_events, publishes unpublished events to NATS JetStream, and marks them delivered. Runs as a background task alongside the HTTP server or as a standalone process. Supports optional leader election so only one relay instance publishes at a time.qx.events.NatsPublisher— publishes a singleIntegrationEventto a JetStream subject derived fromevent_name.qx.events.NatsConsumer— durable pull consumer over a JetStream stream. Used byWorkerRuntimeto fetch and ack/nak messages.qx.events.NatsSettings— Pydantic settings for NATS connection (URL, credentials, stream name, consumer name).qx.events.EventRegistry— mapsevent_namestrings to concreteIntegrationEventsubclasses. Required by both the relay (for serialisation) and the worker (for deserialisation).qx.events.MediatorEventDispatcher—EventDispatcherimplementation that routes domain events to their in-process handlers via the Mediator after a UnitOfWork commit.qx.events.create_nats_connection— async factory that opens a NATS connection with retry.
Usage
Outbox relay (alongside the API server)
from qx.events import OutboxRelay, NatsPublisher, NatsSettings, EventRegistry
registry = EventRegistry()
registry.register(UserRegisteredIntegration)
publisher = NatsPublisher(nc, registry)
relay = OutboxRelay(session_factory, publisher, registry)
# Run in background
asyncio.create_task(relay.run())
Consuming events in a worker
from qx.events import NatsConsumer, NatsSettings
settings = NatsSettings(url="nats://localhost:4222", stream="events", consumer="identity-worker")
consumer = NatsConsumer(nc, settings)
# WorkerRuntime handles the fetch/ack loop
worker = WorkerRuntime(container, consumer, registry, mediator)
await worker.run()
Design rules
- At-least-once delivery — the outbox guarantees every
INSERTed event is eventually published. Consumers are expected to be idempotent (useIdempotencyStorefromqx-cache). - Transactional outbox —
UnitOfWork(inqx-db) writes events toqx_outbox_eventsin the same transaction as the aggregate; the relay reads and publishes asynchronously. No event is lost even if the process crashes between commit and publish. - Event envelope — each NATS message carries
event_name,event_version, payload JSON,correlation_id,tenant_id, and OTel trace context headers for full observability continuity.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
qx_events-1.1.0.tar.gz
(9.8 kB
view details)
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
qx_events-1.1.0-py3-none-any.whl
(10.2 kB
view details)
File details
Details for the file qx_events-1.1.0.tar.gz.
File metadata
- Download URL: qx_events-1.1.0.tar.gz
- Upload date:
- Size: 9.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
762ea581e1adcaca8f72bca50c1aaebf8e09e911c45d55d84bcae3f0e105cb53
|
|
| MD5 |
475fc62fc385957b03892ac5faef75c5
|
|
| BLAKE2b-256 |
5096c1560ca8f28c46c659719f7c75dbc473e48e09903102ca6b7cc0226520b7
|
File details
Details for the file qx_events-1.1.0-py3-none-any.whl.
File metadata
- Download URL: qx_events-1.1.0-py3-none-any.whl
- Upload date:
- Size: 10.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1e8fb89d408703c72806dba18bb3a63639e4b319af8a463aca79f5730bbd8176
|
|
| MD5 |
3fbb6db659edb5936dbef42202874a12
|
|
| BLAKE2b-256 |
3d8119bb779bb31094edcd5b8ded99ee56840e5bbe8fd633bae2894e973621a2
|