LifecycleInitializer recovers from init failures (#549)

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
This commit is contained in:
Daniel Garnier-Moiroux 2025-09-12 13:59:51 +02:00 • committed by Christian Tzolov
commit bc3a925bdc
2 changed files with 14 additions and 1 deletions

View file

@ -289,6 +289,7 @@ class LifecycleInitializer {
return initializationJob.map(initializeResult -> this.initializationRef.get())
.timeout(this.initializationTimeout)
.onErrorResume(ex -> {
this.initializationRef.compareAndSet(newInit, null);
return Mono.error(new RuntimeException("Client failed to initialize " + actionName, ex));
})
.flatMap(operation);

View file

@ -230,7 +230,10 @@ class LifecycleInitializerTests {
@Test
void shouldHandleInitializationFailure() {
when(mockClientSession.sendRequest(eq(McpSchema.METHOD_INITIALIZE), any(), any()))
.thenReturn(Mono.error(new RuntimeException("Connection failed")));
// fail once
.thenReturn(Mono.error(new RuntimeException("Connection failed")))
// succeeds on the second call
.thenReturn(Mono.just(MOCK_INIT_RESULT));
StepVerifier.create(initializer.withIntitialization("test", init -> Mono.just(init.initializeResult())))
.expectError(RuntimeException.class)
@ -238,6 +241,15 @@ class LifecycleInitializerTests {
assertThat(initializer.isInitialized()).isFalse();
assertThat(initializer.currentInitializationResult()).isNull();
// The initializer can recover from previous errors
StepVerifier
.create(initializer.withIntitialization("successful init", init -> Mono.just(init.initializeResult())))
.expectNext(MOCK_INIT_RESULT)
.verifyComplete();
assertThat(initializer.isInitialized()).isTrue();
assertThat(initializer.currentInitializationResult()).isEqualTo(MOCK_INIT_RESULT);
}
@Test