diff --git a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt index d0c4c2ee5..615f0efac 100644 --- a/app/src/main/java/to/bitkit/repositories/LightningRepo.kt +++ b/app/src/main/java/to/bitkit/repositories/LightningRepo.kt @@ -256,6 +256,12 @@ class LightningRepo @Inject constructor( scope.launch { registerForNotifications() } Unit }.onFailure { e -> + val currentLifecycleState = _lightningState.value.nodeLifecycleState + if (currentLifecycleState.isRunning()) { + Logger.warn("Start error occurred but node is $currentLifecycleState, skipping retry", e, context = TAG) + return@withContext Result.success(Unit) + } + if (shouldRetry) { val retryDelay = 2.seconds Logger.warn("Start error, retrying after $retryDelay...", e, context = TAG) diff --git a/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt b/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt index 2cd88e6c5..6a3695570 100644 --- a/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt +++ b/app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt @@ -23,6 +23,7 @@ import org.mockito.kotlin.inOrder import org.mockito.kotlin.isNull import org.mockito.kotlin.mock import org.mockito.kotlin.spy +import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.verifyBlocking import org.mockito.kotlin.whenever @@ -646,4 +647,28 @@ class LightningRepoTest : BaseUnitTest() { assertTrue(result.isSuccess) verify(lightningService).setup(any(), anyOrNull(), anyOrNull(), isNull(), anyOrNull()) } + + @Test + fun `start should not retry when node lifecycle state is Running`() = test { + sut.setInitNodeLifecycleState() + whenever(lightningService.node).thenReturn(null) + whenever(lightningService.setup(any(), anyOrNull(), anyOrNull(), anyOrNull(), anyOrNull())).thenReturn(Unit) + whenever(settingsStore.data).thenReturn(flowOf(SettingsData())) + val blocktank = mock() + whenever(coreService.blocktank).thenReturn(blocktank) + whenever(blocktank.info(any())).thenReturn(null) + + // lightningService.start() succeeds (state becomes Running at line 241) + whenever(lightningService.start(anyOrNull(), any())).thenReturn(Unit) + // lightningService.nodeId throws during syncState() (called at line 244, AFTER state = Running) + whenever(lightningService.nodeId).thenThrow(RuntimeException("error during syncState")) + + val result = sut.start() + + // Defensive check: state is Running, so don't retry, return success + assertTrue(result.isSuccess) + assertEquals(NodeLifecycleState.Running, sut.lightningState.value.nodeLifecycleState) + // Verify start was only called once (no retry) + verify(lightningService, times(1)).start(anyOrNull(), any()) + } }