Skip to content

Commit d5d167e

Browse files
authored
docs: warn that apps sharing a root container close it for each other (#700)
1 parent 0985dca commit d5d167e

3 files changed

Lines changed: 15 additions & 1 deletion

File tree

‎docs/providers/context.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ assert with_request.resolve(AuditLog).client_host == "10.0.0.1"
119119
The same works with an integration's provider. With `modern-di-fastapi` set up, an
120120
`AuditLog(request: fastapi.Request | None = None)` gets the real request inside a FastAPI handler
121121
and `None` in a FastStream consumer that shares the container. The provider itself stays required,
122-
so `container.resolve(fastapi.Request)` outside a request still raises.
122+
so `container.resolve(fastapi.Request)` outside a request still raises. Both apps then close the
123+
same container at shutdown; see [Closing and reopening](lifecycle.md#closing-and-reopening).
123124

124125
The fallback has limits:
125126

‎docs/providers/lifecycle.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,14 @@ What survives close and reopen depends on `CacheSettings`:
291291
not the outer one. Use one `with` block per container, or build a child container for
292292
the inner scope.
293293

294+
!!! caution "Apps that share a container close it for each other"
295+
Integrations open the root container at startup and close it at shutdown, and opening an
296+
open container does nothing. When two apps share one root container, for example a FastAPI
297+
app and a FastStream app in one process, the first app to stop closes it and runs its APP
298+
finalizers. After that, any resolve in the other app that reaches an APP-scoped provider
299+
raises `ContainerClosedError`. Stop the apps together, or give each app its own container
300+
when they stop independently.
301+
294302
## Validation
295303

296304
`container.validate()` checks the whole graph in one pass: cycles, dependencies on a deeper scope,

‎docs/troubleshooting/container-closed-error.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ comes from and stop it outliving the container. Reopening there would hide the l
6868
cached after the reopen would never be finalized, because the shutdown that should close it has
6969
already run.
7070

71+
Two apps that share one root container close it for each other. Each integration closes the root
72+
at its app's shutdown, so when one app stops, the other's next resolve of an APP-scoped provider
73+
raises. Stop the apps together, or give each app its own container. See
74+
[Lifecycle: closing and reopening](../providers/lifecycle.md#closing-and-reopening).
75+
7176
A finalizer that resolves from its own container fails the same way, because the container counts
7277
as closed while its finalizers run. That `ContainerClosedError` arrives as an entry inside the
7378
[`FinalizerError`](finalizer-error.md) that `close_sync()` or `close_async()` raises. Do not reopen

0 commit comments

Comments
 (0)