Skip to main content

Weni EDA

weni-eda is a Python library that simplifies Event-Driven Architecture (EDA) with Django and AMQP brokers. It supports:

Broker SSL Params factory Env prefix
RabbitMQ No ConnectionParamsFactory EDA_*
AmazonMQ Yes (port 5671) AMQConnectionParamsFactory AMQ_*

Both scopes share the same consumer and publisher APIs — you only swap the connection params factory (and the matching env vars).

Features

  • Easy integration with Django
  • RabbitMQ (plain AMQP) and AmazonMQ (AMQP over SSL)
  • Transport-agnostic Message and Channel abstractions
  • Optional buffered consumers for high-throughput workloads

Installation

pip install weni-eda

Django setup

Add the app to INSTALLED_APPS:

# settings.py
INSTALLED_APPS = [
    # ...
    "weni.eda.django.eda_app",
]

Point EDA_CONSUMERS_HANDLE to the function that registers your consumers (used by both brokers unless overridden per process):

# settings.py
EDA_CONSUMERS_HANDLE = "myapp.messages.handle.handle_consumers"

RabbitMQ (no SSL)

Use this for a standard RabbitMQ broker on port 5672.

Environment variables

Variable Example Description
EDA_BROKER_HOST "localhost" Broker hostname or IP
EDA_BROKER_PORT 5672 Broker port
EDA_BROKER_USER "guest" Username
EDA_BROKER_PASSWORD "guest" Password
EDA_VIRTUAL_HOST "/" Virtual host
EDA_CONSUMERS_HANDLE "myapp.messages.handle.handle_consumers" Consumer registration function

Publisher

from weni.eda.django import ConnectionParamsFactory
from weni.eda.eda_publisher import EDAPublisher

publisher = EDAPublisher(ConnectionParamsFactory)
publisher.send_message(
    {"event": "order.created", "order_id": 123},
    exchange="orders",
    routing_key="order.created",
)

ConnectionParamsFactory reads the EDA_* settings above.

Consumer

  1. Implement a consumer:
from weni.eda.django.consumers import EDAConsumer
from weni.eda.messages import Message


class ExampleConsumer(EDAConsumer):
    def consume(self, message: Message):
        body = message.json()
        # ... handle body ...
        self.ack()
  1. Register it in handle_consumers:
from weni.eda.channels import Channel
from .example_consumer import ExampleConsumer


def handle_consumers(channel: Channel):
    channel.basic_consume("example-queue", callback=ExampleConsumer().handle)
  1. Start consuming (default params factory = RabbitMQ / no SSL):
python manage.py edaconsume

AmazonMQ (SSL)

Use this for AmazonMQ (or any AMQP broker that requires TLS). Connections use SSL on port 5671 via AMQConnectionParamsFactory.

Environment variables

Variable Example Description
AMQ_BROKER_HOST "b-xxxx.mq.us-east-1.amazonaws.com" Broker hostname
AMQ_BROKER_PORT 5671 SSL port (default 5671)
AMQ_BROKER_USER "myuser" Username
AMQ_BROKER_PASSWORD "mypassword" Password
AMQ_VIRTUAL_HOST "/" Virtual host
AMQ_BROKER_HEARTBEAT 300 Heartbeat interval in seconds (default 300)
AMQ_BROKER_SSL_SERVER_HOSTNAME "b-xxxx.mq.us-east-1.amazonaws.com" Hostname for SSL certificate verification / SNI (defaults to AMQ_BROKER_HOST)

You still need EDA_CONSUMERS_HANDLE (or --handle) so the process knows which consumers to register.

Publisher

from weni.eda.django import AMQConnectionParamsFactory
from weni.eda.eda_publisher import EDAPublisher

publisher = EDAPublisher(AMQConnectionParamsFactory)
publisher.send_message(
    {"event": "order.created", "order_id": 123},
    exchange="orders",
    routing_key="order.created",
)

AMQConnectionParamsFactory reads the AMQ_* settings and enables SSL automatically.

Consumer

Consumers and handle_consumers are identical to RabbitMQ. The only difference is which params factory you pass when starting the process:

python manage.py edaconsume \
  --params-class "weni.eda.django.AMQConnectionParamsFactory"

Consumers reference

Message API

Consumers receive a weni.eda.messages.Message (transport-agnostic — no need to import amqp):

Method / attribute Description
message.body Raw body (bytes)
message.json(encoding="utf-8") Parse body as JSON → dict
self.ack() Ack the message (remove from queue)
message.reject(requeue=False) Reject the message (called automatically if consume raises)

If consume raises, the message is rejected and the error is logged.

Channel API

handle_consumers receives a weni.eda.channels.Channel:

Method Description
channel.basic_consume(queue, callback=...) Register a queue consumer
channel.basic_qos(...) Set prefetch limits before consuming

edaconsume flags

Useful when one project talks to both brokers (or multiple consumer groups):

python manage.py edaconsume \
  --handle "myapp.messages.handle.handle_consumers" \
  --backend "weni.eda.backends.pyamqp_flush_backend.PyAMQPFlushConnectionBackend" \
  --params-class "weni.eda.django.AMQConnectionParamsFactory"
Flag Default Description
--params-class ConnectionParamsFactory (RabbitMQ) Dotted path to the params factory
--handle settings.EDA_CONSUMERS_HANDLE Dotted path to handle_consumers(channel)
--backend settings.EDA_CONNECTION_BACKEND or PyAMQPConnectionBackend Connection backend

Quick reference:

# RabbitMQ (no SSL)
python manage.py edaconsume

# AmazonMQ (SSL)
python manage.py edaconsume --params-class "weni.eda.django.AMQConnectionParamsFactory"

Buffered consumers (optional)

By default each consumer acks messages one by one. For high-throughput workloads that batch DB writes, use PyAMQPFlushConnectionBackend.

Your handle_consumers must register consumers and return an iterable of flushable objects, each exposing:

  • flush() — persist and ack buffered work
  • flush_interval (optional float) — max seconds between flushes (default 1.0)
from weni.eda.backends.pyamqp_flush_backend import PyAMQPFlushConnectionBackend
from weni.eda.channels import Channel
from weni.eda.django import AMQConnectionParamsFactory


def handle_consumers(channel: Channel):
    consumer = BufferedConsumer()  # exposes flush() and flush_interval
    consumer.setup(channel)        # channel.basic_qos(...) + channel.basic_consume(...)
    return [consumer]


def run():
    params = AMQConnectionParamsFactory.get_params()
    PyAMQPFlushConnectionBackend(handle_consumers).start_consuming(params)

Or via the management command:

python manage.py edaconsume \
  --backend "weni.eda.backends.pyamqp_flush_backend.PyAMQPFlushConnectionBackend" \
  --params-class "weni.eda.django.AMQConnectionParamsFactory"

Returning None (or an empty iterable) disables periodic flushing. You can also set settings.EDA_CONNECTION_BACKEND.

Both backends use Python logging for connection lifecycle and errors — configure handlers in your Django app (or Sentry) as needed.


License

This project is licensed under the Mozilla Public License 2.0. See the LICENSE file for the full text.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

weni_eda-0.2.0.tar.gz (19.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

weni_eda-0.2.0-py3-none-any.whl (29.3 kB view details)

Uploaded Python 3

File details

Details for the file weni_eda-0.2.0.tar.gz.

File metadata

  • Download URL: weni_eda-0.2.0.tar.gz
  • Upload date:
  • Size: 19.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.10.19 Darwin/25.3.0

File hashes

Hashes for weni_eda-0.2.0.tar.gz
Algorithm Hash digest
SHA256 1aaf1f3398c3ab96edcf6dce978ecb7a02b1cbb91fec2247495d9d720723654e
MD5 2a2723b89593db1a4ce9d2b8040c2ca7
BLAKE2b-256 36b4930e923d2d10bd7af73671f5f6234e50fc1dad8e1b584dcc0a20a08c82ba

See more details on using hashes here.

File details

Details for the file weni_eda-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: weni_eda-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 29.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.4.1 CPython/3.10.19 Darwin/25.3.0

File hashes

Hashes for weni_eda-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a4a1b17f676d0da23205568beadba96fe054c2d7e4c1f5991af1a131850bf511
MD5 1d213f708db8a7668722ca605bb4420a
BLAKE2b-256 7ec914b26aa81b2b1de3eaa1d973345d1c6731d61d4772903cc8b25b3f801605

See more details on using hashes here.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page