Problem
CompiledInjector initializes singleton bindings lazily. It checks the singleton cache and then executes the generated dependency script.
In a cooperative coroutine runtime such as Swoole, the first construction can yield from a constructor, provider, setter injection, or PostConstruct. A second coroutine can then observe the same cache miss and construct another instance.
A bounded Swoole reproduction produced two constructions and two distinct instances for the same singleton binding.
BEAR.Package already resolves AppInterface before serializing and caching the production injector, so singleton objects reachable from the application root are retained. Singleton bindings outside that graph remain lazy and can still race on their first request-time resolution.
Proposed direction
- Record every singleton dependency index while compiling the container.
- Expose an explicit warm-up operation on the compiled injector, backed by generated metadata rather than runtime reflection or a directory scan.
- Have BEAR.Package call the warm-up operation before serializing/caching the production injector and before coroutine request handling begins.
- Keep this opt-in at the Ray.Compiler level so generic users are not forced to eagerly construct every singleton.
Design questions
- Define failure behavior when one singleton cannot be initialized.
- Decide how injection-point-sensitive providers should behave when warmed outside their eventual consumer.
- Document the startup-time, side-effect, and memory tradeoffs of eager initialization.
- Decide whether the warmed injector should reject any later singleton cache mutation.
Acceptance criteria
- Every compiled singleton selected for warm-up is instantiated before request concurrency starts.
- The serialized/restored injector retains those singleton instances.
- Concurrent first request handling cannot produce duplicate instances for warmed bindings.
- The implementation does not require runtime container reconstruction or reflection-based binding discovery.
- Tests cover the generated singleton manifest, warm-up, serialization, and failure behavior.
Problem
CompiledInjectorinitializes singleton bindings lazily. It checks the singleton cache and then executes the generated dependency script.In a cooperative coroutine runtime such as Swoole, the first construction can yield from a constructor, provider, setter injection, or
PostConstruct. A second coroutine can then observe the same cache miss and construct another instance.A bounded Swoole reproduction produced two constructions and two distinct instances for the same singleton binding.
BEAR.Package already resolves
AppInterfacebefore serializing and caching the production injector, so singleton objects reachable from the application root are retained. Singleton bindings outside that graph remain lazy and can still race on their first request-time resolution.Proposed direction
Design questions
Acceptance criteria