Skip to content

feat: forward dlq_table + metrics_recorder through the FastAPI OutboxRouter (F8-01)#88

Merged
lesnik512 merged 1 commit into
mainfrom
feat/f8-01-fastapi-router-dlq-recorder
Jun 14, 2026
Merged

feat: forward dlq_table + metrics_recorder through the FastAPI OutboxRouter (F8-01)#88
lesnik512 merged 1 commit into
mainfrom
feat/f8-01-fastapi-router-dlq-recorder

Conversation

@lesnik512

Copy link
Copy Markdown
Member

What

Closes F8-01 from the 2026-06-14 pass-3 deep audit (the long-standing deferred FastAPI item).

The FastAPI OutboxRouter builds its inner OutboxBroker internally and didn't expose dlq_table or metrics_recorder, with no handle to inject a pre-built broker — so a FastAPI deployment could not enable the dead-letter queue or the metrics-recorder seam at all (fetched / lease_lost / nacked_terminal / dlq_written). The only path was abandoning the router for a standalone broker.

Fix

Both are plain OutboxBroker.__init__ kwargs that flow through StreamRouter's **connection_kwars (the same mechanism that already carries outbox_table), so this is a forwarding change: add dlq_table + metrics_recorder to OutboxRouter.__init__ and pass them through super().__init__.

outbox_router = OutboxRouter(
    engine,
    outbox_table=outbox_table,
    dlq_table=make_dlq_table(metadata),
    metrics_recorder=my_recorder,
)

routers stays unforwarded — its start/AsyncAPI semantics through the FastAPI lifespan are unsettled (the router already contributes its own subscribers via include_router), so it needs a design call. It's now the sole open FastAPI item in planning/deferred.md.

Tests

tests/test_fastapi.py::test_outbox_router_forwards_dlq_table_and_metrics_recorder_to_inner_broker asserts both kwargs reach the inner broker and that the forwarded recorder actually fires on the dispatch path under the FastAPI router (not just that it's wired). Failed before (router rejected dlq_table), passes after.

  • just test503 passed, 100% coverage
  • just lint clean (ruff + ty)

Docs

  • docs/usage/fastapi.md — DLQ + recorder are now documented as available via the router (with an example); only routers listed as not exposed. This also clears F8-02 (the docs previously claimed observability was unavailable via the router — wrong, since native Prometheus/OTel middleware always worked via OutboxRouter(middlewares=[...])).
  • planning/deferred.md — FastAPI item narrowed to just routers.
  • Pass-3 findings doc — F8-01 + F8-02 marked resolved.

🤖 Generated with Claude Code

…Router (F8-01)

The FastAPI OutboxRouter built its inner broker internally and didn't expose
dlq_table or metrics_recorder, so FastAPI deployments could not enable dead-letter
archival or the recorder seam (fetched/lease_lost/nacked_terminal/dlq_written) at
all — the operability features a production service needs.

Both are plain OutboxBroker.__init__ kwargs that flow through StreamRouter's
**connection_kwars (same mechanism as outbox_table), so add them to
OutboxRouter.__init__ and forward them through super().__init__. routers stays
unforwarded pending a design call (its lifespan/AsyncAPI semantics through the
FastAPI router are unsettled) — now the sole open FastAPI item in planning/deferred.md.

Test asserts both reach the inner broker and that the forwarded recorder actually
fires on the dispatch path under the FastAPI router. Docs corrected
(docs/usage/fastapi.md) — this also clears F8-02 (the docs wrongly said
observability was unavailable via the router). Pass-3 findings doc + deferred.md updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lesnik512 lesnik512 merged commit b841bbe into main Jun 14, 2026
3 checks passed
@lesnik512 lesnik512 deleted the feat/f8-01-fastapi-router-dlq-recorder branch June 14, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant