You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: config-driven stream routing with allowlist and matchers
Add an opt-in routing layer: when ROUTES_CONFIG points at a YAML file,
omni-pitcher resolves a destination Redis stream per request based on an
ordered rule list (endpoint / system / author / tag_contains /
title_contains substrings, AND-within-rule, first-match-wins). Misses
fall back to default_stream. The streams allowlist is validated at
startup, so typos in route targets fail fast instead of silently
mis-routing.
Threaded the resolved stream through Pitcher.Pitch as a variadic
override, consuming homerun-library v3.1.0's streamOverride parameter.
With ROUTES_CONFIG unset, behavior is unchanged — every message goes to
REDIS_STREAM as before.
Closes#105
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+40Lines changed: 40 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -276,6 +276,46 @@ helmfile apply -f \
276
276
277
277
</details>
278
278
279
+
## Stream routing
280
+
281
+
By default omni-pitcher writes every message to a single Redis stream (`REDIS_STREAM`, default `messages`). Set the `ROUTES_CONFIG` env var to a YAML file path to route messages to different streams based on which endpoint received them or what they contain.
282
+
283
+
```yaml
284
+
# routes.yaml
285
+
streams: # allowlist of valid destination streams
286
+
- messages
287
+
- github-events
288
+
- grafana-alerts
289
+
- releases
290
+
default_stream: messages # fallback when no rule matches; must be in `streams`
291
+
routes: # ordered; first match wins, AND inside a rule
| `title_contains` | `Message.Title` (list — any match wins) |
309
+
310
+
Rules are evaluated top-to-bottom; **first match wins**. Inside a rule, all declared matchers must match (**AND**). If no rule matches, the message goes to `default_stream`.
311
+
312
+
Misconfiguration fails startup. Specifically:
313
+
- `streams`must be non-empty and unique
314
+
- `default_stream`and every `routes[*].stream` must be in `streams`
315
+
- every rule must declare at least one matcher
316
+
317
+
When `ROUTES_CONFIG` is unset, the legacy single-stream behavior is preserved (everything goes to `REDIS_STREAM`). See [`examples/routes.yaml`](examples/routes.yaml) for a full example.
318
+
279
319
## PR preview environments
280
320
281
321
Every open PR against `main` gets an ephemeral preview environment on `homerun2-dev` — omni-pitcher + redis-stack in an isolated namespace, reachable end-to-end so reviewers can pitch test events against the PR build.
0 commit comments