Construction, ownership and partial failure
What this concept is
A factory or composition root decides which objects exist, how they connect and who releases owned resources. A Builder can validate cross-field invariants at build time while still rejecting invalid individual values early. A pattern name cannot guarantee compatible products or leak-free construction.
Why it matters here
If acquiring the second resource fails, the first resource still needs cleanup. Returning a half-built object or relying on garbage collection can leave ownership ambiguous.
Concrete example
The lab’s open_bundle enters managers A then B and exits B then A. If B.enter raises, A is exited; B’s own exit is not called automatically. B must clean up any resources it acquired before failing to enter. If the body raises after both entered, both unwind in reverse order. ExitStack supplies this composition while retaining normal context-manager exception semantics.
Common confusion / misconception
Injected does not mean owned. build_quote borrows its provider and does not close it. open_bundle owns the scopes it explicitly enters. A single shared instance constructed at startup does not require a global Singleton, and a factory interface alone does not prove its products are compatible.
How to use it
Validate configuration before invoking providers or acquiring resources where possible. In the lab all factories must be callable before any acquisition begins; actual context-manager validity can only be checked when produced. Register cleanup immediately after each successful acquisition. State whether cleanup may suppress or replace exceptions: open_bundle delegates that behavior to supplied managers, while our fixtures never suppress and have non-failing exits. Crash recovery is outside this in-process guarantee.
Check yourself
Why is cleanup reverse ordered? What must a failing enter clean up itself, and what belongs to the surrounding composition?
Mini drill or application
Trace enter A, enter B fails, exit A. Then trace a body failure after A and B entered. Draw an ownership list distinguishing a borrowed provider, a caller-owned event list and owned context-manager scopes. Explain what changes if two services share the same owned resource.
Read this only if stuck
Use the existing reference map and composition source guide. The GoF book index supplies vocabulary; the lab’s contracts define the concrete behavior.