Skip to content

docs: show grouping subscribers under the FastAPI OutboxRouter - #203

Merged
lesnik512 merged 1 commit into
mainfrom
docs/fastapi-sub-routers
Oct 3, 2026
Merged

lesnik512 merged 1 commit into
mainfrom
docs/fastapi-sub-routers

Conversation

@lesnik512

@lesnik512 lesnik512 commented Oct 3, 2026 •

Copy link
Copy Markdown
Member

Refs #158.

Summary

#158 asked whether faststream_outbox.fastapi.OutboxRouter should forward routers= to the inner broker. It should not, and the capability it would provide already exists through router.include_router(...). This PR documents and tests that path.

Why not forward routers=

  • FastStream's StreamRouter.include_router accepts a broker-level router, wraps each of its subscribers with the FastAPI compatibility decorator, then calls broker.include_router. That is FastStream's documented "multiple routers" pattern for FastAPI.
  • OutboxBroker(routers=...) just calls include_routers in the constructor, skipping that wrap. Under the FastAPI router apply_types=False, so nothing injects arguments: a handler with d: str = Depends(dep) receives the raw OutboxMessage as its body and the Depends(...) object itself as d. No error, wrong values.
  • None of FastStream's own FastAPI routers (Kafka, Rabbit, Redis, NATS, Confluent) accepts routers either.

The two open questions in #158 are settled by observation on the include_router path: nested subscribers belong to the same broker, so they start with it in the FastAPI lifespan, and their channels appear in the /asyncapi document.

Changes

  • docs/usage/fastapi.md: new "Grouping subscribers" section showing a plain faststream_outbox.OutboxRouter included into the FastAPI router, plus the two shapes that do not work (nesting FastAPI routers raises TypeError; router.broker.include_router skips the bridge). The routers bullet under "What's intentionally not exposed" now gives the reason and points to the section.
  • tests/test_fastapi.py: test_included_broker_router_subscriber_resolves_fastapi_depends (INVARIANT) checks that Depends resolves in a nested subscriber and the channel is in the AsyncAPI document. Switching the include to router.broker.include_router(sub) makes it fail.

Checks

  • just lint-ci: pass
  • pytest --no-cov: 518 passed, 107 skipped (Postgres integration tests; not run locally, no SQL touched)
  • just docs-build (mkdocs build --strict): pass

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown

Benchmark gate

✅ gate passed

scenario msg/s delete/msg WALrec/msg WALB/msg fpi upd del dead_tup
consumer/w1/b10 1067 1.000 6.79 916 242 5000 5000 10000
consumer/w1/b100 1066 1.000 6.82 919 243 5000 5000 10000
consumer/w2/b10 1221 1.000 6.80 963 242 5000 5000 10000
consumer/w2/b100 1448 1.000 6.73 954 243 5000 5000 10000
consumer/w4/b10 1132 1.000 6.82 995 261 5000 5000 10000
consumer/w4/b100 1719 1.000 6.87 1039 244 5000 5000 10000
consumer/w1/b100/tfbs100 6688 0.010 6.07 1116 243 5000 5000 10000
producer/w1/b100 2428 0.000 3.04 584 0 0 0 0

Gated (fails the build): delete_calls + tuple counters (upd/del/ins) + the producer's insert_calls, exact; select_calls within +2; wal_records within a 10% band. msg/s, WAL bytes and total calls are informational (timing/FPI noise).

@lesnik512
lesnik512 merged commit ebfaf72 into main Oct 3, 2026
13 checks passed
@lesnik512
lesnik512 deleted the docs/fastapi-sub-routers branch October 3, 2026 20:29
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