Skip to content

Commit e559aef

Browse files
authored
Merge branch 'master' into fix/node-stopping-bg-payments
2 parents 2f55273 + 1767828 commit e559aef

3 files changed

Lines changed: 59 additions & 19 deletions

File tree

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ class BlocktankRepo @Inject constructor(
134134
}
135135
}
136136

137-
suspend fun refreshOrders() = withContext(bgDispatcher) {
138-
if (isRefreshing) return@withContext
137+
suspend fun refreshOrders(): Result<Unit> = withContext(bgDispatcher) {
138+
if (isRefreshing) return@withContext Result.success(Unit)
139139
isRefreshing = true
140140

141141
runCatching {
@@ -172,11 +172,9 @@ class BlocktankRepo @Inject constructor(
172172
context = TAG
173173
)
174174
openChannelWithPaidOrders()
175-
}.onFailure {
176-
Logger.error("Failed to refresh orders", it, context = TAG)
175+
}.also {
176+
isRefreshing = false
177177
}
178-
179-
isRefreshing = false
180178
}
181179

182180
suspend fun refreshMinCjitSats() = withContext(bgDispatcher) {
@@ -303,7 +301,7 @@ class BlocktankRepo @Inject constructor(
303301
): Result<IBtOrder?> = withContext(bgDispatcher) {
304302
runCatching {
305303
if (refresh) {
306-
refreshOrders()
304+
refreshOrders().getOrThrow()
307305
}
308306
val order = _blocktankState.value.orders.find { it.id == orderId }
309307
return@runCatching order

app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -263,19 +263,40 @@ class TransferViewModel @Inject constructor(
263263
}
264264

265265
private suspend fun pollUntil(orderId: String, condition: (IBtOrder) -> Boolean): IBtOrder? {
266+
var consecutiveErrors = 0
267+
266268
while (true) {
267-
val order = blocktankRepo.getOrder(orderId, refresh = true).getOrNull()
268-
if (order == null) {
269-
Logger.error("Order not found: '$orderId'", context = TAG)
270-
return null
271-
}
272-
if (order.state2 == BtOrderState2.EXPIRED) {
273-
Logger.error("Order expired: '$orderId'", context = TAG)
274-
return null
275-
}
276-
if (condition(order)) {
277-
return order
278-
}
269+
blocktankRepo.getOrder(orderId, refresh = true).fold(
270+
onSuccess = { order ->
271+
consecutiveErrors = 0
272+
273+
if (order == null) {
274+
Logger.error("Order not found: '$orderId'", context = TAG)
275+
return null
276+
}
277+
if (order.state2 == BtOrderState2.EXPIRED) {
278+
Logger.error("Order expired: '$orderId'", context = TAG)
279+
return null
280+
}
281+
if (condition(order)) {
282+
return order
283+
}
284+
},
285+
onFailure = {
286+
consecutiveErrors++
287+
Logger.warn(
288+
"Failed to fetch order '$orderId' (attempt $consecutiveErrors/$MAX_CONSECUTIVE_ERRORS)",
289+
it,
290+
context = TAG
291+
)
292+
293+
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
294+
Logger.error("Too many consecutive errors polling order '$orderId', giving up", context = TAG)
295+
return null
296+
}
297+
}
298+
)
299+
279300
delay(POLL_INTERVAL_MS)
280301
}
281302
}
@@ -539,6 +560,7 @@ class TransferViewModel @Inject constructor(
539560
private const val TAG = "TransferViewModel"
540561
private const val MIN_STEP_DELAY_MS = 500L
541562
private const val POLL_INTERVAL_MS = 2_500L
563+
private const val MAX_CONSECUTIVE_ERRORS = 5
542564
const val LN_SETUP_STEP_0 = 0
543565
const val LN_SETUP_STEP_1 = 1
544566
const val LN_SETUP_STEP_2 = 2

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,24 @@ class BlocktankRepoTest : BaseUnitTest() {
172172
assertTrue(result.isSuccess)
173173
assertNull(result.getOrThrow())
174174
}
175+
176+
@Test
177+
fun `refreshOrders returns failure when server throws`() {
178+
sut = createSut()
179+
whenever { coreService.blocktank.orders(refresh = true) }.thenThrow(RuntimeException("Network error"))
180+
test {
181+
val result = sut.refreshOrders()
182+
assertTrue(result.isFailure)
183+
}
184+
}
185+
186+
@Test
187+
fun `getOrder returns failure when refresh fails`() {
188+
sut = createSut()
189+
whenever { coreService.blocktank.orders(refresh = true) }.thenThrow(RuntimeException("Network error"))
190+
test {
191+
val result = sut.getOrder(testOrder1.id, refresh = true)
192+
assertTrue(result.isFailure)
193+
}
194+
}
175195
}

0 commit comments

Comments
 (0)