Description
Context
Our app communicates with multiple (physical) machines, each being driven by a separate bean. When the app starts, each driver bean resets its machine to a known state. This reset can take a few minutes before which the rest of the app (UI, etc) should not be available. The driver beans implement SmartLifecycle, hardware reset is performed on start().
All machines can be reset at the same time, so to minimize startup time I'm currently using a custom LifecycleProcessor
forked off the DefaultLifecycleProcessor
, for which I've implemented concurrent start for beans within the same phase (in LifecycleGroup::start()
). This makes the LifecycleGroup
start take as long as the slowest machine's reset, rather than sequentially resetting each one which would be unnecessarily slow.
Moreover, I've duplicated the existing per-phase (stop) timeout
parameter to a start timeout, to make sure the app fails if starting takes more than some expected limit rather than remain in start limbo forever.
Proposal
My main assumption is that situations where Lifecycle beans depend on external resources happen frequently, not just in our case. Spring applications could gain both in performance and resilience by making it easier to use concurrent start / stop operations.
To do so would involve either:
- Integrate concurrent operation + timeout in the existing DefaultLifecycleProcessor, using an opt-in switch per phase (default behavior would remain sequential start with no timeout) (e.g.
.setConcurrentStart(phase, true)
)
OR
- Make it possible to override the
LifecycleGroup
class with a custom class to allow implementing aforementioned concurrent start mechanism without having to duplicate the entireDefaultLifecycleProcessor
.
Thoughts
-
Beans within the same phase should be safe to start concurrently, since by design they should not have inter-dependencies. While I know this is true for my app, this is not a part of the current
Lifecycle
contract and thus the default should remain sequential, non-timeout start. -
The underlying support for concurrency could vary a lot from case to case (virtual threads? limit number of concurrent processes?), so maybe the extendable
DefaultLifecycleProcessor
option is more interesting.