q,ex,binding scaffolded

This commit is contained in:
2026-04-14 20:53:09 +00:00
parent abe83af5ab
commit d8b50d753c
11 changed files with 138 additions and 30 deletions
+1
View File
@@ -0,0 +1 @@
__pycache__
+1
View File
@@ -0,0 +1 @@
3.13
+10
View File
@@ -0,0 +1,10 @@
Links\
This page is very good and very structured
https://www.rabbitmq.com/tutorials
What is it?\
It's a queue - message broker is the technical term.
Once you up, dashboard is on :15672, username:pass = guest:guest
You never push directly to the q, it's always via exchanges.
+32 -30
View File
@@ -24,66 +24,68 @@ By the end, you will have a real event flow running through RabbitMQ.
## Lab Stack ## Lab Stack
- Language: **Python** - Language: **Python**
- Broker: RabbitMQ (Docker) - Tooling: `uv`
- Broker: RabbitMQ **4+** (Docker)
- Library: `pika` - Library: `pika`
## Step 1: Project Setup (10 min) ## Step 1: Project Setup (10 min)
- [ ] Create files: - [x] Create files:
- [ ] `docker-compose.yml` - [x] `docker-compose.yml`
- [ ] `requirements.txt` - [x] `pyproject.toml` (created by `uv init`)
- [ ] `producer.py` - [x] `producer.py`
- [ ] `worker.py` - [x] `worker.py`
- [ ] `notifier.py` - [x] `notifier.py`
- [ ] Put this in `requirements.txt`: - [x] Initialize project and dependency with `uv`:
```txt ```bash
pika==1.3.2 uv init --name rabbitmq-lab
uv add pika==1.3.2
``` ```
- [ ] Put this in `docker-compose.yml`: - [x] Put this in `docker-compose.yml`:
```yaml ```yaml
version: "3.9" version: "3.9"
services: services:
rabbitmq: rabbitmq:
image: rabbitmq:3-management image: rabbitmq:4-management
ports: ports:
- "5672:5672" - "5672:5672"
- "15672:15672" - "15672:15672"
``` ```
- [ ] Start RabbitMQ: - [x] Start RabbitMQ:
```bash ```bash
docker compose up -d docker compose up -d
``` ```
- [ ] Open UI: `http://localhost:15672` (`guest` / `guest`). - [x] Open UI: `http://localhost:15672` (`guest` / `guest`).
## Step 2: RabbitMQ Topology (15 min) ## Step 2: RabbitMQ Topology (15 min)
Create these resources from code (preferred) or UI: Create these resources from code (preferred) or UI:
- [ ] Exchange `orders.x` (direct) - [x] Exchange `orders.x` (direct)
- [ ] Exchange `orders.dlx` (direct) - [x] Exchange `orders.dlx` (direct)
- [ ] Queue `orders.q` - [x] Queue `orders.q`
- [ ] Queue `orders.processed.q` - [x] Queue `orders.processed.q`
- [ ] Queue `orders.failed.q` - [x] Queue `orders.failed.q`
- [ ] Queue `orders.dlq` - [x] Queue `orders.dlq`
Bindings: Bindings:
- [ ] `orders.q` <- `orders.x` with `order.created` - [x] `orders.q` <- `orders.x` with `order.created`
- [ ] `orders.processed.q` <- `orders.x` with `order.processed` - [x] `orders.processed.q` <- `orders.x` with `order.processed`
- [ ] `orders.failed.q` <- `orders.x` with `order.failed` - [x] `orders.failed.q` <- `orders.x` with `order.failed`
- [ ] `orders.dlq` <- `orders.dlx` with `order.dead` - [x] `orders.dlq` <- `orders.dlx` with `order.dead`
Queue args for `orders.q`: Queue args for `orders.q`:
- [ ] `x-dead-letter-exchange=orders.dlx` - [x] `x-dead-letter-exchange=orders.dlx`
- [ ] `x-dead-letter-routing-key=order.dead` - [x] `x-dead-letter-routing-key=order.dead`
## Step 3: Producer (20 min) ## Step 3: Producer (20 min)
@@ -98,7 +100,7 @@ Queue args for `orders.q`:
Success check: Success check:
- [ ] Running `python producer.py` prints “Published order …” 5 times. - [ ] Running `uv run producer.py` prints “Published order …” 5 times.
## Step 4: Worker (35 min) ## Step 4: Worker (35 min)
@@ -135,9 +137,9 @@ Success check:
Run in 3 terminals: Run in 3 terminals:
- [ ] Terminal A: `python worker.py` - [ ] Terminal A: `uv run worker.py`
- [ ] Terminal B: `python notifier.py` - [ ] Terminal B: `uv run notifier.py`
- [ ] Terminal C: `python producer.py` - [ ] Terminal C: `uv run producer.py`
Expected behavior: Expected behavior:
+7
View File
@@ -0,0 +1,7 @@
services:
rabbitmq:
# management basically has nicer clis and a dashboard for seeing the q
image: rabbitmq:4.2.5-management
ports:
- 5672:5672 # actual container
- 15672:15672 # web dashboard
+55
View File
@@ -0,0 +1,55 @@
import pika
# this is the physical conn
connection = pika.BlockingConnection(pika.ConnectionParameters("localhost"))
# a channel is a lightweight multiplexer over it
channel = connection.channel()
# first the exchanges
# this is A DECLARE, basically so can run multuple times
# .x = exchange
channel.exchange_declare(
exchange="orders.x", exchange_type="direct", durable=True)
# .dlx = dead letter exchange for failed messages
channel.exchange_declare(exchange="orders.dlx",
exchange_type="direct", durable=True)
# the exchange_types are
# - direct: exact key match for routing
# - topic: pattern based
# - fanout: all
# - headers: defined in headers
# then the queues
# when changing settings, you might need to delete q from adming
# as it'll aready exist and this declare does not delete
channel.queue_declare(
queue="orders.q",
durable=True,
arguments={
# what to do with "dead letters"
# which can be when consumder signals issue
# or q overflow
# or ttl stuff
"x-dead-letter-exchange": "orders.dlx",
"x-dead-letter-routing-key": "order.dead",
},
)
channel.queue_declare(queue="orders.processed.q", durable=True)
channel.queue_declare(queue="orders.failed.q", durable=True)
channel.queue_declare(queue="orders.dlq", durable=True)
# then the bindings
# these are rules on how exchange will route what message
# read as, on order.x, if key is order.created, push to orders.q
channel.queue_bind(exchange="orders.x", queue="orders.q",
routing_key="order.created")
channel.queue_bind(exchange="orders.x", queue="orders.processed.q",
routing_key="order.processed")
channel.queue_bind(exchange="orders.x", queue="orders.failed.q",
routing_key="order.failed")
channel.queue_bind(exchange="orders.dlx", queue="orders.dlq",
routing_key="order.dead")
connection.close()
View File
View File
+9
View File
@@ -0,0 +1,9 @@
[project]
name = "learning-rabbitmq"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"pika>=1.3.2",
]
Generated
+23
View File
@@ -0,0 +1,23 @@
version = 1
revision = 3
requires-python = ">=3.13"
[[package]]
name = "learning-rabbitmq"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "pika" },
]
[package.metadata]
requires-dist = [{ name = "pika", specifier = ">=1.3.2" }]
[[package]]
name = "pika"
version = "1.3.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/db/db/d4102f356af18f316c67f2cead8ece307f731dd63140e2c71f170ddacf9b/pika-1.3.2.tar.gz", hash = "sha256:b2a327ddddf8570b4965b3576ac77091b850262d34ce8c1d8cb4e4146aa4145f", size = 145029, upload-time = "2023-05-05T14:25:43.368Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f9/f3/f412836ec714d36f0f4ab581b84c491e3f42c6b5b97a6c6ed1817f3c16d0/pika-1.3.2-py3-none-any.whl", hash = "sha256:0779a7c1fafd805672796085560d290213a465e4f6f76a6fb19e378d8041a14f", size = 155415, upload-time = "2023-05-05T14:25:41.484Z" },
]
View File