dr-queues 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. dr_queues-0.1.0/.gitignore +4 -0
  2. dr_queues-0.1.0/.python-version +1 -0
  3. dr_queues-0.1.0/AGENTS.md +39 -0
  4. dr_queues-0.1.0/CHANGELOG.md +21 -0
  5. dr_queues-0.1.0/CLAUDE.md +1 -0
  6. dr_queues-0.1.0/LICENSE +21 -0
  7. dr_queues-0.1.0/PKG-INFO +243 -0
  8. dr_queues-0.1.0/README.md +219 -0
  9. dr_queues-0.1.0/docker-compose.yml +11 -0
  10. dr_queues-0.1.0/nbs/hello_world.py +35 -0
  11. dr_queues-0.1.0/pyproject.toml +95 -0
  12. dr_queues-0.1.0/scripts/pre-check.sh +57 -0
  13. dr_queues-0.1.0/scripts/run_pipeline_demo.py +4 -0
  14. dr_queues-0.1.0/scripts/run_stage_workers.py +4 -0
  15. dr_queues-0.1.0/src/dr_queues/__init__.py +77 -0
  16. dr_queues-0.1.0/src/dr_queues/amqp/__init__.py +18 -0
  17. dr_queues-0.1.0/src/dr_queues/amqp/connection.py +194 -0
  18. dr_queues-0.1.0/src/dr_queues/amqp/queues.py +66 -0
  19. dr_queues-0.1.0/src/dr_queues/analysis/__init__.py +3 -0
  20. dr_queues-0.1.0/src/dr_queues/analysis/filter.py +19 -0
  21. dr_queues-0.1.0/src/dr_queues/cli/__init__.py +6 -0
  22. dr_queues-0.1.0/src/dr_queues/cli/commands.py +14 -0
  23. dr_queues-0.1.0/src/dr_queues/cli/demo.py +143 -0
  24. dr_queues-0.1.0/src/dr_queues/cli/stage_worker.py +132 -0
  25. dr_queues-0.1.0/src/dr_queues/demo_handlers.py +38 -0
  26. dr_queues-0.1.0/src/dr_queues/events/__init__.py +21 -0
  27. dr_queues-0.1.0/src/dr_queues/events/amqp.py +118 -0
  28. dr_queues-0.1.0/src/dr_queues/events/memory.py +45 -0
  29. dr_queues-0.1.0/src/dr_queues/events/mongo.py +63 -0
  30. dr_queues-0.1.0/src/dr_queues/events/schema.py +34 -0
  31. dr_queues-0.1.0/src/dr_queues/events/sink.py +14 -0
  32. dr_queues-0.1.0/src/dr_queues/manifest/__init__.py +29 -0
  33. dr_queues-0.1.0/src/dr_queues/manifest/manifest.py +110 -0
  34. dr_queues-0.1.0/src/dr_queues/pipeline/__init__.py +10 -0
  35. dr_queues-0.1.0/src/dr_queues/pipeline/job.py +47 -0
  36. dr_queues-0.1.0/src/dr_queues/pipeline/runner.py +207 -0
  37. dr_queues-0.1.0/src/dr_queues/pipeline/tap.py +102 -0
  38. dr_queues-0.1.0/src/dr_queues/pipeline/workers.py +155 -0
  39. dr_queues-0.1.0/src/dr_queues/py.typed +0 -0
  40. dr_queues-0.1.0/src/dr_queues/utils.py +10 -0
  41. dr_queues-0.1.0/src/dr_queues/workflow/__init__.py +16 -0
  42. dr_queues-0.1.0/src/dr_queues/workflow/definition.py +20 -0
  43. dr_queues-0.1.0/src/dr_queues/workflow/pipeline.py +61 -0
  44. dr_queues-0.1.0/src/dr_queues/workflow/registry.py +28 -0
  45. dr_queues-0.1.0/tests/.gitkeep +0 -0
  46. dr_queues-0.1.0/tests/conftest.py +99 -0
  47. dr_queues-0.1.0/tests/test_amqp_sink.py +25 -0
  48. dr_queues-0.1.0/tests/test_filter_events.py +31 -0
  49. dr_queues-0.1.0/tests/test_job_envelope.py +25 -0
  50. dr_queues-0.1.0/tests/test_manifest.py +50 -0
  51. dr_queues-0.1.0/tests/test_memory_sink.py +44 -0
  52. dr_queues-0.1.0/tests/test_mongo_sink.py +20 -0
  53. dr_queues-0.1.0/tests/test_pipeline.py +78 -0
  54. dr_queues-0.1.0/tests/test_pipeline_mongo.py +55 -0
  55. dr_queues-0.1.0/tests/test_registry.py +29 -0
  56. dr_queues-0.1.0/uv.lock +1730 -0
@@ -0,0 +1,4 @@
1
+ .runs/
2
+ .cache/
3
+ __pycache__/
4
+ *.py[cod]
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,39 @@
1
+ # Agent Instructions
2
+
3
+ ## Verification
4
+
5
+ - **Cursor agents:** Do not run `scripts/pre-check.sh` unless the user
6
+ explicitly asks you to run checks or verification.
7
+ - **Other agents:** Run `scripts/pre-check.sh` after making code changes.
8
+ - Skip `scripts/pre-check.sh` after documentation-only or configuration-only
9
+ changes (non-Cursor agents).
10
+ - When running checks, treat every issue reported by `scripts/pre-check.sh` as
11
+ in scope to fix, even when the issue is outside the files you touched.
12
+ - Read failed check output from `.cache/pre-check/`.
13
+
14
+ ## Tests
15
+
16
+ - Do not add tests unless the user explicitly asks for tests.
17
+
18
+ ## Commits
19
+
20
+ - After completing a requested sequence of changes, commit the result unless
21
+ the user specifically asks not to commit at the end.
22
+ - Use a single-line commit message.
23
+ - If your own changes are easy to isolate, commit only your own changes.
24
+ - If your own changes are not cleanly extractable, commit all changes in the
25
+ files you touched.
26
+ - Before committing code changes, run `scripts/pre-check.sh` (non-Cursor agents,
27
+ or when the user explicitly asked you to run checks).
28
+ - Before committing documentation-only or configuration-only changes, do not run
29
+ `scripts/pre-check.sh`.
30
+
31
+ ## Multi-Player Workflow
32
+
33
+ - Assume other agents and users may be operating in this repo at the same time.
34
+ - Never delete, revert, reset, or otherwise undo unexpected changes in the repo.
35
+ - Assume unexpected changes were made intentionally by the user or another
36
+ process.
37
+ - If unexpected changes appear suspect or make the requested work difficult,
38
+ ask how to proceed and describe the concern.
39
+ - Do not undo suspect changes while waiting for guidance.
@@ -0,0 +1,21 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2026-06-21
9
+
10
+ ### Added
11
+
12
+ - RabbitMQ multi-stage pipeline runtime (`WorkerPool`, `TerminalTap`, queue chaining)
13
+ - Slim `JobEnvelope` for job state on the wire
14
+ - `PipelineDefinition`, `HandlerRegistry`, and `Pipeline` workflow engine
15
+ - Append-only event sinks: `MongoEventSink` (default), `AmqpEventSink`, `MemoryEventSink`
16
+ - Run manifest for multi-process worker coordination
17
+ - `filter_run_events` analysis helper
18
+ - Console entry points: `dr-queues-demo`, `dr-queues-stage-worker`
19
+ - Reference dummy handlers in `dr_queues.demo_handlers`
20
+
21
+ [0.1.0]: https://github.com/danielle-rothermel/dr-queues/releases/tag/v0.1.0
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 danielle rothermel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,243 @@
1
+ Metadata-Version: 2.4
2
+ Name: dr-queues
3
+ Version: 0.1.0
4
+ Summary: RabbitMQ multi-stage pipeline runtime with append-only event sinks
5
+ Project-URL: Homepage, https://github.com/danielle-rothermel/dr-queues
6
+ Project-URL: Repository, https://github.com/danielle-rothermel/dr-queues
7
+ Project-URL: Issues, https://github.com/danielle-rothermel/dr-queues/issues
8
+ Author-email: Danielle Rothermel <danielle.rothermel@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: amqp,mongodb,pipeline,queue,rabbitmq,workflow
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: System :: Distributed Computing
18
+ Requires-Python: >=3.13
19
+ Requires-Dist: pika>=1.4.1
20
+ Requires-Dist: pydantic>=2.13.4
21
+ Requires-Dist: pymongo>=4.16.0
22
+ Requires-Dist: typer>=0.26.7
23
+ Description-Content-Type: text/markdown
24
+
25
+ # dr-queues
26
+
27
+ RabbitMQ multi-stage pipeline runtime with append-only event sinks.
28
+
29
+ dr-queues is a domain-free library for running jobs through chained stage
30
+ queues, scaling worker pools per stage, and recording pipeline lifecycle
31
+ events to durable storage. It is the execution substrate for experiment
32
+ applications such as [dr-bottleneck](https://github.com/danielle-rothermel/dr-bottleneck).
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ pip install dr-queues
38
+ ```
39
+
40
+ Or with [uv](https://docs.astral.sh/uv/):
41
+
42
+ ```bash
43
+ uv add dr-queues
44
+ ```
45
+
46
+ RabbitMQ and MongoDB are **not** bundled with the package — run them locally
47
+ (Docker Compose) or point `AMQP_URL` / `MONGODB_URL` at your infrastructure.
48
+
49
+ After install, try the demo CLI:
50
+
51
+ ```bash
52
+ dr-queues-demo --repeats 2 --lanes 1
53
+ ```
54
+
55
+ ## What dr-queues is
56
+
57
+ - AMQP staged pipeline: per-stage pending/completed queue pairs chained together
58
+ - Slim `JobEnvelope` for job state on the wire
59
+ - `WorkerPool` and `TerminalTap` with pluggable step handlers
60
+ - Append-only `EventSink` implementations (MongoDB happy path, AMQP optional)
61
+ - Run manifest for multi-process worker coordination
62
+ - Minimal workflow engine: ordered steps + `HandlerRegistry`
63
+
64
+ ## What dr-queues is not
65
+
66
+ - LLM calls, prompts, or model profiles
67
+ - Dataset loading, HumanEval, or experiment metrics
68
+ - JSONL report assembly
69
+ - General domain EventBus / webhook dispatch (deferred to a future layer)
70
+
71
+ Workers append pipeline events **before** acking and forwarding jobs to the
72
+ next stage. That append-before-forward invariant matches an event-sourced
73
+ write-ahead log: durable telemetry precedes propagation.
74
+
75
+ ## Requirements
76
+
77
+ - Python 3.13+ with [uv](https://docs.astral.sh/uv/)
78
+ - Docker Compose for local RabbitMQ and MongoDB
79
+
80
+ ## Environment
81
+
82
+ | Variable | Default | Purpose |
83
+ |----------|---------|---------|
84
+ | `AMQP_URL` | `amqp://guest:guest@localhost:5672/` | RabbitMQ connection |
85
+ | `MONGODB_URL` | `mongodb://localhost:27017/dr_queues` | MongoDB event store |
86
+
87
+ ## Local services
88
+
89
+ ```bash
90
+ docker compose up -d
91
+ ```
92
+
93
+ - RabbitMQ management UI: http://localhost:15672 (guest/guest)
94
+ - MongoDB: `mongodb://localhost:27017/dr_queues`
95
+
96
+ ## Quick start
97
+
98
+ From a git checkout:
99
+
100
+ ```bash
101
+ uv sync
102
+ docker compose up -d
103
+ uv run dr-queues-demo \
104
+ --repeats 5 \
105
+ --workers slow=4,transform=4,finalize=2
106
+ ```
107
+
108
+ Or use the repo script wrapper (same CLI):
109
+
110
+ ```bash
111
+ uv run python scripts/run_pipeline_demo.py \
112
+ --repeats 5 \
113
+ --workers slow=4,transform=4,finalize=2
114
+ ```
115
+
116
+ The demo runs a 3-stage dummy pipeline (`sleep_ms` → `add_prefix` →
117
+ `record_artifact`) with MongoDB as the default event sink.
118
+
119
+ Options:
120
+
121
+ ```bash
122
+ dr-queues-demo --sink amqp --repeats 2
123
+ dr-queues-demo --sink both --lanes 1 --repeats 1
124
+ ```
125
+
126
+ Each run writes a manifest to `.runs/{run_id}/manifest.json`. The demo prints
127
+ `run_id=...` at the start — use that value when querying MongoDB (do not use the
128
+ literal placeholder `demo-...`).
129
+
130
+ On success you should see output like `events=70 terminals=10` for
131
+ `--repeats 5` with the default 2 lanes (10 jobs × 7 events per job).
132
+
133
+ ### Inspect events in MongoDB
134
+
135
+ Events are stored in the `pipeline_events` collection. Replace
136
+ `YOUR_RUN_ID` with the `run_id` printed by the demo (e.g. `demo-56bd0ce5`).
137
+
138
+ Count events for one run:
139
+
140
+ ```bash
141
+ mongosh mongodb://localhost:27017/dr_queues \
142
+ --eval 'db.pipeline_events.countDocuments({run_id: "YOUR_RUN_ID"})'
143
+ ```
144
+
145
+ List all run IDs that have events:
146
+
147
+ ```bash
148
+ mongosh mongodb://localhost:27017/dr_queues \
149
+ --eval 'db.pipeline_events.distinct("run_id")'
150
+ ```
151
+
152
+ Count all events in the collection (across every run):
153
+
154
+ ```bash
155
+ mongosh mongodb://localhost:27017/dr_queues \
156
+ --eval 'db.pipeline_events.countDocuments({})'
157
+ ```
158
+
159
+ Preview a few events from a run:
160
+
161
+ ```bash
162
+ mongosh mongodb://localhost:27017/dr_queues \
163
+ --eval 'db.pipeline_events.find({run_id: "YOUR_RUN_ID"}).limit(3).pretty()'
164
+ ```
165
+
166
+ If counts are zero, check:
167
+
168
+ - You used the **actual** `run_id` from demo output, not the placeholder text.
169
+ - The demo used the default Mongo sink (`--sink mongo`). AMQP-only runs
170
+ (`--sink amqp`) do not write to MongoDB.
171
+ - MongoDB is running (`docker compose up -d`) and reachable at `MONGODB_URL`.
172
+ - You re-ran the demo after starting Mongo if the first attempt failed to connect.
173
+
174
+ ## Package layout
175
+
176
+ | Module | Role |
177
+ |--------|------|
178
+ | `amqp/` | Connection helpers, stage queue pairs |
179
+ | `pipeline/` | `JobEnvelope`, `WorkerPool`, `TerminalTap`, runner |
180
+ | `events/` | `PipelineEvent`, `EventSink`, Mongo/AMQP/memory sinks |
181
+ | `manifest/` | Run manifest read/write, worker CLI helpers |
182
+ | `workflow/` | `PipelineDefinition`, `HandlerRegistry`, `Pipeline` |
183
+ | `analysis/` | `filter_run_events` |
184
+
185
+ ## Public API
186
+
187
+ Import from `dr_queues`:
188
+
189
+ - **Setup / run:** `setup_run_queues`, `run_in_process`, `seed_jobs`, `seed_manifest_jobs`
190
+ - **Runtime:** `WorkerPool`, `TerminalTap`, `JobEnvelope`
191
+ - **Workflow:** `PipelineDefinition`, `HandlerRegistry`, `Pipeline`
192
+ - **Events:** `PipelineEvent`, `EventSink`, `MongoEventSink`, `AmqpEventSink`, `MemoryEventSink`
193
+ - **Analysis:** `filter_run_events`
194
+
195
+ ## Detached stage workers
196
+
197
+ Resize or run a single stage in a separate process:
198
+
199
+ ```bash
200
+ dr-queues-stage-worker \
201
+ --run-id demo-abc123 \
202
+ --stage transform \
203
+ --workers 5 \
204
+ --replace
205
+ ```
206
+
207
+ Handlers must be registered in the worker process via `--handlers-module`
208
+ (default: `dr_queues.demo_handlers`).
209
+
210
+ ## Future layers
211
+
212
+ A general EventBus, domain EventAdapter, and webhook/hook dispatch will likely
213
+ live in a separate package or in dr-bottleneck, built on top of dr-queues.
214
+ Pipeline lifecycle events may eventually map to versioned domain event types;
215
+ dr-queues stays focused on queue-based execution and pipeline telemetry.
216
+
217
+ ## Development
218
+
219
+ ```bash
220
+ uv sync
221
+ docker compose up -d
222
+ scripts/pre-check.sh # ruff, ty, pytest (14 tests)
223
+ uv run pytest -m integration # integration tests only; needs docker compose
224
+ ```
225
+
226
+ Full manual smoke test:
227
+
228
+ ```bash
229
+ dr-queues-demo \
230
+ --repeats 5 \
231
+ --workers slow=4,transform=4,finalize=2
232
+
233
+ # optional: exercise AMQP event sink instead of Mongo
234
+ dr-queues-demo --sink amqp --repeats 2
235
+ ```
236
+
237
+ Build a wheel locally before publishing:
238
+
239
+ ```bash
240
+ uv build
241
+ tar -tzf dist/dr_queues-*.tar.gz | head
242
+ unzip -l dist/dr_queues-*.whl
243
+ ```
@@ -0,0 +1,219 @@
1
+ # dr-queues
2
+
3
+ RabbitMQ multi-stage pipeline runtime with append-only event sinks.
4
+
5
+ dr-queues is a domain-free library for running jobs through chained stage
6
+ queues, scaling worker pools per stage, and recording pipeline lifecycle
7
+ events to durable storage. It is the execution substrate for experiment
8
+ applications such as [dr-bottleneck](https://github.com/danielle-rothermel/dr-bottleneck).
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install dr-queues
14
+ ```
15
+
16
+ Or with [uv](https://docs.astral.sh/uv/):
17
+
18
+ ```bash
19
+ uv add dr-queues
20
+ ```
21
+
22
+ RabbitMQ and MongoDB are **not** bundled with the package — run them locally
23
+ (Docker Compose) or point `AMQP_URL` / `MONGODB_URL` at your infrastructure.
24
+
25
+ After install, try the demo CLI:
26
+
27
+ ```bash
28
+ dr-queues-demo --repeats 2 --lanes 1
29
+ ```
30
+
31
+ ## What dr-queues is
32
+
33
+ - AMQP staged pipeline: per-stage pending/completed queue pairs chained together
34
+ - Slim `JobEnvelope` for job state on the wire
35
+ - `WorkerPool` and `TerminalTap` with pluggable step handlers
36
+ - Append-only `EventSink` implementations (MongoDB happy path, AMQP optional)
37
+ - Run manifest for multi-process worker coordination
38
+ - Minimal workflow engine: ordered steps + `HandlerRegistry`
39
+
40
+ ## What dr-queues is not
41
+
42
+ - LLM calls, prompts, or model profiles
43
+ - Dataset loading, HumanEval, or experiment metrics
44
+ - JSONL report assembly
45
+ - General domain EventBus / webhook dispatch (deferred to a future layer)
46
+
47
+ Workers append pipeline events **before** acking and forwarding jobs to the
48
+ next stage. That append-before-forward invariant matches an event-sourced
49
+ write-ahead log: durable telemetry precedes propagation.
50
+
51
+ ## Requirements
52
+
53
+ - Python 3.13+ with [uv](https://docs.astral.sh/uv/)
54
+ - Docker Compose for local RabbitMQ and MongoDB
55
+
56
+ ## Environment
57
+
58
+ | Variable | Default | Purpose |
59
+ |----------|---------|---------|
60
+ | `AMQP_URL` | `amqp://guest:guest@localhost:5672/` | RabbitMQ connection |
61
+ | `MONGODB_URL` | `mongodb://localhost:27017/dr_queues` | MongoDB event store |
62
+
63
+ ## Local services
64
+
65
+ ```bash
66
+ docker compose up -d
67
+ ```
68
+
69
+ - RabbitMQ management UI: http://localhost:15672 (guest/guest)
70
+ - MongoDB: `mongodb://localhost:27017/dr_queues`
71
+
72
+ ## Quick start
73
+
74
+ From a git checkout:
75
+
76
+ ```bash
77
+ uv sync
78
+ docker compose up -d
79
+ uv run dr-queues-demo \
80
+ --repeats 5 \
81
+ --workers slow=4,transform=4,finalize=2
82
+ ```
83
+
84
+ Or use the repo script wrapper (same CLI):
85
+
86
+ ```bash
87
+ uv run python scripts/run_pipeline_demo.py \
88
+ --repeats 5 \
89
+ --workers slow=4,transform=4,finalize=2
90
+ ```
91
+
92
+ The demo runs a 3-stage dummy pipeline (`sleep_ms` → `add_prefix` →
93
+ `record_artifact`) with MongoDB as the default event sink.
94
+
95
+ Options:
96
+
97
+ ```bash
98
+ dr-queues-demo --sink amqp --repeats 2
99
+ dr-queues-demo --sink both --lanes 1 --repeats 1
100
+ ```
101
+
102
+ Each run writes a manifest to `.runs/{run_id}/manifest.json`. The demo prints
103
+ `run_id=...` at the start — use that value when querying MongoDB (do not use the
104
+ literal placeholder `demo-...`).
105
+
106
+ On success you should see output like `events=70 terminals=10` for
107
+ `--repeats 5` with the default 2 lanes (10 jobs × 7 events per job).
108
+
109
+ ### Inspect events in MongoDB
110
+
111
+ Events are stored in the `pipeline_events` collection. Replace
112
+ `YOUR_RUN_ID` with the `run_id` printed by the demo (e.g. `demo-56bd0ce5`).
113
+
114
+ Count events for one run:
115
+
116
+ ```bash
117
+ mongosh mongodb://localhost:27017/dr_queues \
118
+ --eval 'db.pipeline_events.countDocuments({run_id: "YOUR_RUN_ID"})'
119
+ ```
120
+
121
+ List all run IDs that have events:
122
+
123
+ ```bash
124
+ mongosh mongodb://localhost:27017/dr_queues \
125
+ --eval 'db.pipeline_events.distinct("run_id")'
126
+ ```
127
+
128
+ Count all events in the collection (across every run):
129
+
130
+ ```bash
131
+ mongosh mongodb://localhost:27017/dr_queues \
132
+ --eval 'db.pipeline_events.countDocuments({})'
133
+ ```
134
+
135
+ Preview a few events from a run:
136
+
137
+ ```bash
138
+ mongosh mongodb://localhost:27017/dr_queues \
139
+ --eval 'db.pipeline_events.find({run_id: "YOUR_RUN_ID"}).limit(3).pretty()'
140
+ ```
141
+
142
+ If counts are zero, check:
143
+
144
+ - You used the **actual** `run_id` from demo output, not the placeholder text.
145
+ - The demo used the default Mongo sink (`--sink mongo`). AMQP-only runs
146
+ (`--sink amqp`) do not write to MongoDB.
147
+ - MongoDB is running (`docker compose up -d`) and reachable at `MONGODB_URL`.
148
+ - You re-ran the demo after starting Mongo if the first attempt failed to connect.
149
+
150
+ ## Package layout
151
+
152
+ | Module | Role |
153
+ |--------|------|
154
+ | `amqp/` | Connection helpers, stage queue pairs |
155
+ | `pipeline/` | `JobEnvelope`, `WorkerPool`, `TerminalTap`, runner |
156
+ | `events/` | `PipelineEvent`, `EventSink`, Mongo/AMQP/memory sinks |
157
+ | `manifest/` | Run manifest read/write, worker CLI helpers |
158
+ | `workflow/` | `PipelineDefinition`, `HandlerRegistry`, `Pipeline` |
159
+ | `analysis/` | `filter_run_events` |
160
+
161
+ ## Public API
162
+
163
+ Import from `dr_queues`:
164
+
165
+ - **Setup / run:** `setup_run_queues`, `run_in_process`, `seed_jobs`, `seed_manifest_jobs`
166
+ - **Runtime:** `WorkerPool`, `TerminalTap`, `JobEnvelope`
167
+ - **Workflow:** `PipelineDefinition`, `HandlerRegistry`, `Pipeline`
168
+ - **Events:** `PipelineEvent`, `EventSink`, `MongoEventSink`, `AmqpEventSink`, `MemoryEventSink`
169
+ - **Analysis:** `filter_run_events`
170
+
171
+ ## Detached stage workers
172
+
173
+ Resize or run a single stage in a separate process:
174
+
175
+ ```bash
176
+ dr-queues-stage-worker \
177
+ --run-id demo-abc123 \
178
+ --stage transform \
179
+ --workers 5 \
180
+ --replace
181
+ ```
182
+
183
+ Handlers must be registered in the worker process via `--handlers-module`
184
+ (default: `dr_queues.demo_handlers`).
185
+
186
+ ## Future layers
187
+
188
+ A general EventBus, domain EventAdapter, and webhook/hook dispatch will likely
189
+ live in a separate package or in dr-bottleneck, built on top of dr-queues.
190
+ Pipeline lifecycle events may eventually map to versioned domain event types;
191
+ dr-queues stays focused on queue-based execution and pipeline telemetry.
192
+
193
+ ## Development
194
+
195
+ ```bash
196
+ uv sync
197
+ docker compose up -d
198
+ scripts/pre-check.sh # ruff, ty, pytest (14 tests)
199
+ uv run pytest -m integration # integration tests only; needs docker compose
200
+ ```
201
+
202
+ Full manual smoke test:
203
+
204
+ ```bash
205
+ dr-queues-demo \
206
+ --repeats 5 \
207
+ --workers slow=4,transform=4,finalize=2
208
+
209
+ # optional: exercise AMQP event sink instead of Mongo
210
+ dr-queues-demo --sink amqp --repeats 2
211
+ ```
212
+
213
+ Build a wheel locally before publishing:
214
+
215
+ ```bash
216
+ uv build
217
+ tar -tzf dist/dr_queues-*.tar.gz | head
218
+ unzip -l dist/dr_queues-*.whl
219
+ ```
@@ -0,0 +1,11 @@
1
+ services:
2
+ rabbitmq:
3
+ image: rabbitmq:3-management
4
+ ports:
5
+ - "5672:5672"
6
+ - "15672:15672"
7
+
8
+ mongodb:
9
+ image: mongo:7
10
+ ports:
11
+ - "27017:27017"
@@ -0,0 +1,35 @@
1
+ import marimo
2
+
3
+ __generated_with = "0.23.9"
4
+ app = marimo.App(width="columns")
5
+
6
+ with app.setup:
7
+ import marimo as mo
8
+
9
+
10
+ @app.cell
11
+ def _():
12
+ mo.md(r"""
13
+ ## Load Data
14
+ """)
15
+ return
16
+
17
+
18
+ @app.cell(column=1)
19
+ def _():
20
+ mo.md(r"""
21
+ ## Do Exploration
22
+ """)
23
+ return
24
+
25
+
26
+ @app.cell(column=2, hide_code=True)
27
+ def _():
28
+ mo.md(r"""
29
+ (leave space)
30
+ """)
31
+ return
32
+
33
+
34
+ if __name__ == "__main__":
35
+ app.run()
@@ -0,0 +1,95 @@
1
+ [project]
2
+ name = "dr-queues"
3
+ version = "0.1.0"
4
+ description = "RabbitMQ multi-stage pipeline runtime with append-only event sinks"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ authors = [
9
+ { name = "Danielle Rothermel", email = "danielle.rothermel@gmail.com" }
10
+ ]
11
+ requires-python = ">=3.13"
12
+ keywords = ["rabbitmq", "pipeline", "workflow", "queue", "amqp", "mongodb"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Topic :: System :: Distributed Computing",
20
+ ]
21
+ dependencies = [
22
+ "pika>=1.4.1",
23
+ "pydantic>=2.13.4",
24
+ "pymongo>=4.16.0",
25
+ "typer>=0.26.7",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://github.com/danielle-rothermel/dr-queues"
30
+ Repository = "https://github.com/danielle-rothermel/dr-queues"
31
+ Issues = "https://github.com/danielle-rothermel/dr-queues/issues"
32
+
33
+ [project.scripts]
34
+ dr-queues-demo = "dr_queues.cli.demo:run"
35
+ dr-queues-stage-worker = "dr_queues.cli.stage_worker:run"
36
+
37
+ [build-system]
38
+ requires = ["hatchling"]
39
+ build-backend = "hatchling.build"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/dr_queues"]
43
+
44
+ [dependency-groups]
45
+ dev = [
46
+ "marimo[recommended]>=0.23.10",
47
+ "pytest>=9.1.1",
48
+ "ruff>=0.15.18",
49
+ "ty>=0.0.51",
50
+ ]
51
+
52
+ [tool.pytest.ini_options]
53
+ testpaths = ["tests"]
54
+ markers = [
55
+ "integration: tests requiring RabbitMQ and/or MongoDB",
56
+ ]
57
+
58
+ [tool.ruff]
59
+ include = ["scripts/**/*.py", "src/**/*.py", "tests/**/*.py"]
60
+ line-length = 79
61
+
62
+ [tool.ruff.lint]
63
+ select = [
64
+ "A",
65
+ "ARG",
66
+ "ASYNC",
67
+ "DTZ",
68
+ "FA",
69
+ "FLY",
70
+ "FURB",
71
+ "G",
72
+ "I",
73
+ "ICN",
74
+ "ISC",
75
+ "LOG",
76
+ "N",
77
+ "NPY",
78
+ "PD",
79
+ "PIE",
80
+ "PTH",
81
+ "PT",
82
+ "RET",
83
+ "RSE",
84
+ "RUF",
85
+ "SLOT",
86
+ "T10",
87
+ "TID",
88
+ "UP",
89
+ "W",
90
+ "YTT",
91
+ ]
92
+
93
+ [tool.ty.src]
94
+ include = ["scripts", "src"]
95
+ exclude = ["nbs", "tests"]