Commit f87ce9c
authored
feat(runtime): add virtual cluster lifecycle state tracking (kroxylicious#3640)
* Add virtual cluster lifecycle state model
Introduce VirtualClusterLifecycleState as a sealed interface with
records for each state (Initializing, Serving, Draining, Failed, Stopped).
Each state exposes typed transition methods enforcing the state machine
from proposal 016. Failed carries its cause, and Stopped retains the
prior failure cause for diagnostics.
VirtualClusterLifecycleManager wraps the state in an AtomicReference
for thread-safe transitions, with structured logging on each transition.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Wire lifecycle manager into KafkaProxy startup and shutdown
Create a VirtualClusterLifecycleManager per virtual cluster during
startup, transitioning each to Serving on success. On shutdown,
beginShutdown() transitions serving clusters to Draining before the
Netty graceful shutdown, then completeShutdown() transitions them to
Stopped afterwards. Existing fail-fast behaviour is preserved.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Address review feedback on lifecycle manager
- Remove beginShutdown/completeShutdown composite methods from
VirtualClusterLifecycleManager; KafkaProxy now calls startDraining,
drainComplete, and stop directly
- Call initializationFailed(cause) from KafkaProxy startup catch block
so Failed state carries the real failure cause
- Fix race in transition(): use transitionFn.apply(previous) instead of
state.get() to avoid observing another thread's update
- Log at DEBUG for most transitions, INFO only for initial and terminal
states
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Remove unused toInitializing() transitions from Draining and Failed
These transitions are valid in the proposal's state machine but have no
callers today — reload/recovery is deferred. Removing to avoid premature
API commitment; they can be re-added when reload is implemented.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Remove unnecessary throws declaration from test method
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Address review feedback: fix double-apply, log levels, and Initializing→Stopped
- Fix transition() to use get()+updateAndGet() instead of re-applying the
transition function to derive the new state for logging
- Log all transitions at INFO, Failed transitions at WARN
- Support Initializing→Stopped transition so VCs are not orphaned if
shutdown occurs during startup
- Assert failure cause on Stopped state in startup failure test
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Replace AtomicReference with synchronized in VirtualClusterLifecycleManager
The AtomicReference approach had a race between state.get() and
state.updateAndGet() where another thread could advance the state,
causing incorrect log messages. Using synchronized makes the
read-transition-log sequence atomic. This is sufficient for the
single-shot proxy lifecycle where contention is not a concern.
Also adjusts log levels: INFO for significant states (Serving, Failed,
Stopped), DEBUG for intermediate transitions (Draining).
Closes kroxylicious#3696
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* refactor(runtime): extract VirtualClusterManager from KafkaProxy (#87)
* Add VirtualClusterManager with construction, accessors, and tests
Introduces VirtualClusterManager as the single source of truth for which
virtual clusters exist and their current lifecycle state. VCM owns the
cluster config tree and lifecycle managers but does not manage networking,
endpoint registration, or metrics — those remain with KafkaProxy.
The onVirtualClusterStopped callback notifies the owner when a VC reaches
terminal Stopped state, allowing proxy-level policy decisions.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Add per-VC lifecycle transitions with callback
Adds initializationSucceeded(clusterName) and initializationFailed(clusterName, cause)
to VirtualClusterManager. On failure, the VC transitions immediately from Failed to
Stopped (no recovery path today) and fires the onVirtualClusterStopped callback with
the failure cause.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Add bulk shutdown transitions and return value
Adds transitionAllToDraining() and transitionAllToStopped() to VirtualClusterManager.
transitionAllToStopped() returns boolean indicating whether all clusters are now stopped,
so KafkaProxy doesn't need to poll individual lifecycle managers.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Wire VirtualClusterManager into KafkaProxy
KafkaProxy now delegates virtual cluster lifecycle management to
VirtualClusterManager instead of managing lifecycle managers directly.
Removes private transitionAllToDraining/transitionAllToStopped methods
and the lifecycleManagers map in favour of VCM.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Make VirtualClusterManager non-nullable in KafkaProxy
Move VCM construction from startup() to the constructor so it can be
final and non-nullable, eliminating null guards throughout.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Improve onVirtualClusterStopped callback logging
Log at WARN with a message that reflects the serve:none policy intent.
Add TODO noting the callback should eventually drive proxy shutdown
rather than relying on the caller.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
---------
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Address review feedback: naming conventions, javadoc, and logging
- Rename getState()/getClusterName() to state()/clusterName() on
VirtualClusterLifecycleManager per project accessor conventions
- Rename getVirtualClusterModels() to virtualClusterModels() on
VirtualClusterManager
- Rename terse field 'vcm' to 'virtualClusterManager' in KafkaProxy
- Fix transitionAllToDraining() javadoc: clarify that Failed/Stopped
clusters are skipped, not transitioned by this method
- Fix logging key from 'cause' to 'error' with Throwable::getMessage
per logging conventions
- Add comment documenting the all-or-nothing startup assumption at
the initializationFailed call site
Assisted-by: Claude claude-opus-4-6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Address review feedback: lazy logging, argumentSet, and javadoc fixes
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
* Rename transitionAllToStopped to completeDraining
The previous name implied all clusters would be transitioned, but the
method only completes the draining→stopped transition. The new name
better describes the actual behaviour.
Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>
---------
Signed-off-by: Sam Barker <sam@quadrocket.co.uk>1 parent 58c1cc2 commit f87ce9c
7 files changed
Lines changed: 1033 additions & 0 deletions
File tree
- kroxylicious-runtime/src
- main/java/io/kroxylicious/proxy
- internal
- test/java/io/kroxylicious/proxy
- internal
Lines changed: 28 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| 60 | + | |
| 61 | + | |
60 | 62 | | |
61 | 63 | | |
62 | 64 | | |
| |||
149 | 151 | | |
150 | 152 | | |
151 | 153 | | |
| 154 | + | |
152 | 155 | | |
153 | 156 | | |
154 | 157 | | |
| |||
160 | 163 | | |
161 | 164 | | |
162 | 165 | | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
163 | 170 | | |
164 | 171 | | |
165 | 172 | | |
| |||
216 | 223 | | |
217 | 224 | | |
218 | 225 | | |
| 226 | + | |
219 | 227 | | |
220 | 228 | | |
221 | 229 | | |
| |||
252 | 260 | | |
253 | 261 | | |
254 | 262 | | |
| 263 | + | |
| 264 | + | |
255 | 265 | | |
256 | 266 | | |
257 | 267 | | |
| |||
260 | 270 | | |
261 | 271 | | |
262 | 272 | | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
263 | 278 | | |
264 | 279 | | |
265 | 280 | | |
| |||
357 | 372 | | |
358 | 373 | | |
359 | 374 | | |
| 375 | + | |
360 | 376 | | |
361 | 377 | | |
362 | 378 | | |
| |||
378 | 394 | | |
379 | 395 | | |
380 | 396 | | |
| 397 | + | |
381 | 398 | | |
382 | 399 | | |
383 | 400 | | |
| |||
394 | 411 | | |
395 | 412 | | |
396 | 413 | | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
397 | 425 | | |
398 | 426 | | |
399 | 427 | | |
| |||
Lines changed: 127 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
Lines changed: 96 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
0 commit comments