Skip to content

Unify the teardown-on-shutdown attach behind one guarded seam#130

Merged
lesnik512 merged 7 commits into
mainfrom
feat/unify-teardown-attach
Jun 24, 2026
Merged

Unify the teardown-on-shutdown attach behind one guarded seam#130
lesnik512 merged 7 commits into
mainfrom
feat/unify-teardown-attach

Conversation

@lesnik512

Copy link
Copy Markdown
Member

What

Moves "register this bootstrapper's teardown to run on the framework's shutdown" behind one seam: BaseBootstrapper._attach_teardown_once(target, attach). That method owns detection (a uniform _lite_bootstrap_teardown_attached marker), the double-attach warning, and the skip. Each app-bearing bootstrapper's __init__ shrinks to "here is my target, here is how I attach."

Why

The teardown-attach was wired five different ways. The double-attach guard + warning was copy-pasted between FastAPI and FastMCP (with two different detection mechanisms — a marker vs a structural provider check) and absent from Litestar and FastStream, so the same user error (two bootstrappers on one app) warned on two frameworks and silently double-registered teardown on the other two. (Candidate 2 of the 2026-06-23 architecture review.)

Changes

  • base.py — new _attach_teardown_once + _TEARDOWN_MARKER; attach typed Callable[[], object] (FastStream's on_shutdown returns the callback).
  • FastAPI / FastMCP — routed through the seam; behavior preserved. FastAPI's lifespan merge → _wrap_lifespan, marker renamed to the unified name; FastMCP migrates structural detection → marker (the _TeardownProvider stays as the attach mechanism).
  • Litestar / FastStreamnow guarded (new behavior): a second bootstrapper on the same target warns and skips instead of stacking a hook.
  • Tests — direct unit test of the seam against a dummy target; FastAPI/FastMCP match strings updated; new Litestar/FastStream double-attach tests.
  • Docsarchitecture/bootstrappers.md (new "Teardown-on-shutdown attach" section + sentinel convention), CLAUDE.md; bundle under planning/changes/2026-06-24.01-unify-teardown-attach/.

Behavior change

Litestar and FastStream now emit a warning when a second bootstrapper is constructed against the same app/config. Intended consistency, non-fatal (warn + skip); the first bootstrapper's teardown still runs.

Verification

199 passed, 100% coverage; just lint clean (ruff + ty). FastAPI/FastMCP behavior preserved (lifespan not re-wrapped / single _TeardownProvider).

🤖 Generated with Claude Code

lesnik512 and others added 7 commits June 24, 2026 10:01
One method owns teardown-attach detection (a uniform _lite_bootstrap_teardown_attached
marker), the double-attach warning, and the skip. Framework bootstrappers will route
their per-framework attach through it. Directly unit-tested against a dummy target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both bootstrappers now call BaseBootstrapper._attach_teardown_once with a
framework-specific attach thunk. FastAPI's lifespan merge moves to _wrap_lifespan
and its marker renames to the unified _lite_bootstrap_teardown_attached; FastMCP
migrates from structural _TeardownProvider detection to the marker (the provider
remains the attach mechanism). Behavior preserved; warning wording unified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both now route their on_shutdown attach through _attach_teardown_once, gaining the
double-attach warning they previously lacked. New tests assert a second bootstrapper
on the same target warns (Litestar also: on_shutdown not stacked). attach thunk typed
Callable[[], object] since FastStream's on_shutdown returns the callback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Set the teardown marker only AFTER attach() succeeds, so a raising attach
  leaves the target untagged and a retry can re-attach (was: permanent skip).
- Reword the warning to cover the config target (Litestar tags AppConfig, not
  an app), keeping the remediation accurate.
- Move Litestar's application_config.debug mutation into the attach thunk so a
  skipped second bootstrapper mutates nothing.
- Regression test: a failed attach does not mark the target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lesnik512 lesnik512 merged commit 66c63a6 into main Jun 24, 2026
7 checks passed
@lesnik512 lesnik512 deleted the feat/unify-teardown-attach branch June 24, 2026 08:35
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