Metadata-Version: 2.5
Name: benzene-rabbitmq
Version: 0.1.0b1
Summary: Benzene RabbitMQ transport binding — a self-hosted consumer and a RabbitMQ-publish outbound client.
Project-URL: Homepage, https://github.com/daniellepelley/benzene-python
Project-URL: Specification, https://github.com/daniellepelley/Benzene/tree/main/docs/specification
Author: Benzene
License-Expression: MIT
License-File: LICENSE
Keywords: amqp,benzene,consumer,hexagonal,pika,rabbitmq
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: benzene-core>=0.0.1
Provides-Extra: rabbitmq
Requires-Dist: pika>=1.3; extra == 'rabbitmq'
Description-Content-Type: text/markdown

# benzene-rabbitmq

Host [Benzene Python](https://github.com/daniellepelley/benzene-python) handlers on **RabbitMQ** —
a self-hosted consumer and a RabbitMQ-publish outbound client — the same handlers, no rewrite. Depends
only on `benzene-core`.

```bash
pip install benzene-rabbitmq               # the binding + testing helpers
pip install "benzene-rabbitmq[rabbitmq]"   # + pika for the real clients
```

```python
from benzene.core import application_from, build_application
from benzene.rabbitmq import RabbitMqConsumerApp, RabbitMqMessageSender, run_consumer_loop

# Inbound: one delivery -> one pipeline invocation -> one scope; ack/log, no reply.
definition, _ = build_application(OrdersStartUp)
app = RabbitMqConsumerApp(application_from(definition))
await run_consumer_loop(app, channel, queue="orders")  # channel: a pika channel

# Outbound: publish to an exchange, Benzene topic carried in the `topic` header.
sender = RabbitMqMessageSender("orders-events", host="localhost")
await sender.send_message("orders:created", order, headers={"x-correlation-id": "abc"})
```

- **Consumer** — the Benzene topic comes from the `topic` header carried in the delivery's AMQP
  `properties.headers` (the cross-port convention); the other headers are the Benzene headers (UTF-8),
  the body is the JSON body. One delivery is one scope; there is **no response channel**, so the result
  is acknowledge/log only — `run_consumer_loop` acks the delivery on success (at-least-once) and nacks a
  failed one for redelivery. A poison delivery can never crash the loop.
- **Outbound** — `RabbitMqMessageSender` implements the `benzene.core.MessageSender` port over
  `pika` (optional extra), forwarding the header dictionary onto the AMQP `properties.headers` so
  correlation/trace propagation rides across the hop.

The binding is duck-typed against `pika`, so decode, dispatch, and publish are exercised in memory with
fakes — no broker, no SDK. Test through `benzene.rabbitmq.testing` (a native-delivery builder + a test
host) or the shared harness (`create_test_host(StartUp).build_rabbitmq()` + `send_rabbitmq`) — see the
runnable `examples/rabbitmq_orders/`. Mirrors .NET's `Benzene.RabbitMq`, and contributes the
`benzene.rabbitmq` subpackage to the shared `benzene` namespace.
