Skip to content

Commit bf5e8f0

Browse files
committed
fix: wait for channel state
1 parent bdc6d95 commit bf5e8f0

3 files changed

Lines changed: 55 additions & 8 deletions

File tree

app/src/main/java/to/bitkit/repositories/LightningRepo.kt

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,23 +1020,50 @@ class LightningRepo @Inject constructor(
10201020
}
10211021

10221022
suspend fun waitForUsableChannels() = withContext(bgDispatcher) {
1023-
val state = _lightningState.value
1023+
var state = _lightningState.value
1024+
if (!state.nodeLifecycleState.canRun()) return@withContext
1025+
if (state.hasUsableChannels()) return@withContext
1026+
1027+
state = waitForChannelsToLoadIfNeeded(state) ?: return@withContext
10241028
if (!state.nodeLifecycleState.canRun()) return@withContext
10251029

1026-
if (state.channels.isEmpty()) return@withContext // no channel exists, don't wait
1027-
if (state.channels.any { it.isUsable }) return@withContext
1030+
if (state.channels.isEmpty()) {
1031+
if (state.nodeLifecycleState.isRunning()) {
1032+
syncState()
1033+
state = _lightningState.value
1034+
}
1035+
1036+
if (state.channels.isEmpty()) return@withContext // no channel exists, don't wait
1037+
if (state.hasUsableChannels()) return@withContext
1038+
}
10281039

10291040
Logger.info("Waiting for usable channels before sending payment", context = TAG)
10301041

10311042
withTimeoutOrNull(CHANNELS_USABLE_TIMEOUT_MS) {
1032-
_lightningState.first {
1033-
!it.nodeLifecycleState.canRun() ||
1034-
it.channels.isEmpty() ||
1035-
it.channels.any { channel -> channel.isUsable }
1036-
}
1043+
_lightningState.first { it.shouldStopWaitingForUsableChannels() }
10371044
} ?: Logger.warn("Timed out waiting for usable channels", context = TAG)
10381045
}
10391046

1047+
private suspend fun waitForChannelsToLoadIfNeeded(state: LightningState): LightningState? {
1048+
if (state.channels.isNotEmpty() || state.nodeLifecycleState.isRunning()) return state
1049+
1050+
Logger.info("Waiting for node to load channels before sending payment", context = TAG)
1051+
return withTimeoutOrNull(CHANNELS_USABLE_TIMEOUT_MS) {
1052+
_lightningState.first { it.shouldStopWaitingForLoadedChannels() }
1053+
} ?: run {
1054+
Logger.warn("Timed out waiting for node to load channels", context = TAG)
1055+
null
1056+
}
1057+
}
1058+
1059+
private fun LightningState.hasUsableChannels() = channels.any { it.isUsable }
1060+
1061+
private fun LightningState.shouldStopWaitingForLoadedChannels() =
1062+
!nodeLifecycleState.canRun() || nodeLifecycleState.isRunning() || channels.isNotEmpty()
1063+
1064+
private fun LightningState.shouldStopWaitingForUsableChannels() =
1065+
!nodeLifecycleState.canRun() || channels.isEmpty() || hasUsableChannels()
1066+
10401067
@Suppress("LongParameterList")
10411068
suspend fun sendOnChain(
10421069
address: Address,

app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,25 @@ class LightningRepoTest : BaseUnitTest() {
392392
assertFalse(sut.canSend(1000uL))
393393
}
394394

395+
@Test
396+
fun `waitForUsableChannels waits for running state before treating empty channels as absent`() = test {
397+
sut.setInitNodeLifecycleState()
398+
val channel = createChannelDetails().copy(
399+
isUsable = true,
400+
nextOutboundHtlcLimitMsat = 2_000_000u,
401+
)
402+
whenever(lightningService.channels).thenReturn(listOf(channel))
403+
404+
val wait = async { sut.waitForUsableChannels() }
405+
406+
assertFalse(wait.isCompleted)
407+
408+
startNodeForTesting()
409+
410+
assertTrue(wait.isCompleted)
411+
assertEquals(listOf(channel), sut.lightningState.value.channels)
412+
}
413+
395414
@Test
396415
fun `wipeStorage should stop node and call service wipe`() = test {
397416
startNodeForTesting()

changelog.d/next/925.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Payment QR scans now route reliably and avoid unnecessary delays when Lightning channels are unavailable.

0 commit comments

Comments
 (0)