Current section
Files
Jump to
Current section
Files
README.md
# Kombu for Elixir
[](https://hex.pm/packages/kombu)
[](https://hexdocs.pm/kombu)
[](https://opensource.org/licenses/BSD-3-Clause)
**Kombu** is an Elixir port of the Python [Celery Kombu](https://github.com/celery/kombu) messaging library (`v5.7.0rc1`), designed for **byte-for-byte wire-format and Redis data-structure compatibility** with Python Kombu and Celery.
Publish messages from Python Kombu/Celery and consume them in Elixir—or publish from Elixir and consume in Python—over Redis without any custom adapters or bridges.
---
## Features
- **100% Wire-Format & Redis Key Compatibility** with Python Kombu:
- Identical JSON message envelope (`body`, `content-type`, `content-encoding`, `properties`, `headers` with Base64-encoded body support).
- Compatible Redis exchange binding sets (`_kombu.binding.<exchange>` with `\x06\x16` separator).
- Priority queue lists (`<queue>\x06\x16<pri>` across steps `[0, 3, 6, 9]`).
- Reliable delivery QoS via `unacked` hash, `unacked_index` ZSET, and visibility timeout recovery (`restore_visible`) using atomic Lua scripts.
- **Exchange Types**:
- `direct`, `topic` (AMQP `*` and `#` wildcard matching), and `fanout` (via Redis Pub/Sub).
- **Zero Extra Serialization/Compression Dependencies**:
- Built on Elixir's standard library `JSON` module with Python Kombu's `__type__` / `__value__` extended type tags (`datetime`, `date`, `time`, `decimal`, `uuid`, `bytes`, `set`) and `:zlib` (`application/x-gzip`) compression.
- **High-Level Messaging Primitives**:
- `Kombu.Connection`, `Kombu.Exchange`, `Kombu.Queue`, `Kombu.Binding`
- `Kombu.Producer` (including batch publishing) & `Kombu.Consumer`
- `Kombu.Simple.SimpleQueue` & `Kombu.Simple.SimpleBuffer`
- `Kombu.Pools` (`ConnectionPool` & `ProducerPool`)
- `Kombu.ConsumerServer` (`kombu.mixins.ConsumerMixin` OTP equivalent)
- `Kombu.Pidbox` (`Mailbox` and `Node` for Celery worker control/inspection RPC)
- **Transports**:
- **Redis** (`redis://`, `rediss://`, `redis+socket://`) powered by `Redix`.
- **Memory** (`memory://`) in-process virtual broker for fast, isolated unit tests.
---
## Installation
Add `kombu` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:kombu, "~> 0.1.0"}
]
end
```
---
## Quick Start
### Publishing and Consuming over Redis
```elixir
alias Kombu.{Connection, Exchange, Queue, Producer, Consumer, Message}
# 1. Connect to Redis
conn = Kombu.connection("redis://localhost:6379/0")
# 2. Define an Exchange and Queue
exchange = Kombu.exchange("media", type: "direct", durable: true)
queue = Kombu.queue("video", exchange, "video", durable: true)
# 3. Start a Consumer
consumer =
Kombu.consumer(conn, [queue],
accept: ["json"],
callbacks: [
fn body, message ->
IO.inspect(body, label: "Received payload")
Message.ack(message)
end
]
)
Consumer.consume(consumer)
# 4. Publish a Message (with optional zlib compression and priority)
producer = Kombu.producer(conn, exchange: exchange, routing_key: "video", serializer: "json")
Producer.publish(
producer,
%{"name" => "movie.mp4", "size" => 1024},
compression: "zlib",
headers: %{"x-source" => "elixir"},
priority: 3
)
# 5. Drain events
Connection.drain_events(conn, timeout: 5.0)
Consumer.cancel(consumer)
Connection.close(conn)
```
### SimpleQueue API
For simple one-off point-to-point queues without explicit Exchange/Consumer boilerplate:
```elixir
alias Kombu.{Message, Simple.SimpleQueue}
conn = Kombu.connection("redis://localhost:6379/0")
sq = Kombu.simple_queue(conn, "simple_jobs")
SimpleQueue.put(sq, %{"task" => "send_email", "to" => "user@example.com"})
message = SimpleQueue.get(sq, timeout: 5.0)
IO.inspect(Message.payload(message))
Message.ack(message)
SimpleQueue.close(sq)
Connection.close(conn)
```
### Topic Exchanges & Wildcard Routing
```elixir
conn = Kombu.connection("redis://localhost:6379/0")
exchange = Kombu.exchange("stocks", type: "topic")
nyse_queue = Kombu.queue("nyse_feed", exchange, "stock.*.nyse")
# Bind & declare queue on the channel
ch = Kombu.Connection.default_channel(conn)
nyse_queue |> Kombu.Queue.bind(ch) |> Kombu.Queue.declare()
producer = Kombu.producer(conn, exchange: exchange)
Kombu.Producer.publish(producer, %{"symbol" => "AAPL", "price" => 195.5}, routing_key: "stock.tech.nyse")
```
### Pidbox (Remote Control & Inspection Mailbox)
Compatible with `kombu.pidbox` used by Celery for broadcasting control commands (`ping`, `stats`, ` revoke`, etc.) to worker nodes:
```elixir
alias Kombu.Pidbox.{Mailbox, Node}
conn = Kombu.connection("redis://localhost:6379/0")
mailbox = Mailbox.new("celery", connection: conn)
# Worker node registering a command handler
node =
Node.new("worker1@host", mailbox, state: %{processed: 42})
|> Node.handler("status", fn state, _args ->
%{"ok" => true, "processed" => state.processed}
end)
consumer = Node.listen(node)
# Client calling the worker node and collecting replies
replies = Mailbox.call(mailbox, ["worker1@host"], "status", %{}, timeout: 2.0)
# => [%{"worker1@host" => %{"ok" => true, "processed" => 42}}]
```
---
## Python ↔ Elixir Interoperability
Because `Kombu` for Elixir uses the exact same Redis keys, Lua scripts, and JSON serialization format as Python `kombu`, Python producers and Elixir consumers (or vice versa) work together out of the box:
**Python Producer:**
```python
from kombu import Connection, Exchange, Queue, Producer
exchange = Exchange("tasks", type="direct")
queue = Queue("default", exchange=exchange, routing_key="default")
with Connection("redis://localhost:6379/0") as conn:
producer = Producer(conn, exchange=exchange, routing_key="default", serializer="json", compression="zlib")
producer.publish({"hello": "from_python"}, declare=[queue], priority=6)
```
**Elixir Consumer:**
```elixir
conn = Kombu.connection("redis://localhost:6379/0")
exchange = Kombu.exchange("tasks", type: "direct")
queue = Kombu.queue("default", exchange, "default")
consumer =
Kombu.consumer(conn, [queue],
callbacks: [
fn body, msg ->
# body == %{"hello" => "from_python"}
Kombu.Message.ack(msg)
end
]
)
Kombu.Consumer.consume(consumer)
Kombu.Connection.drain_events(conn, timeout: 5.0)
```
---
## Testing
- **Unit tests** (in-memory virtual transport & mocked Redis):
```bash
mix test
```
- **Live Redis integration tests** (requires Redis on `localhost:6379`):
```bash
mix test --include integration
```
- **Python ↔ Elixir cross-language interop tests**:
```bash
mix test --include interop
```
---
## License
Released under the **BSD 3-Clause License**, matching the original Python [celery/kombu](https://github.com/celery/kombu/blob/main/LICENSE) license. See [LICENSE](LICENSE) for full details.