Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ class BlocktankRepo @Inject constructor(
}
}

suspend fun refreshOrders() = withContext(bgDispatcher) {
if (isRefreshing) return@withContext
suspend fun refreshOrders(): Result<Unit> = withContext(bgDispatcher) {
if (isRefreshing) return@withContext Result.success(Unit)
isRefreshing = true

runCatching {
Expand Down Expand Up @@ -172,11 +172,9 @@ class BlocktankRepo @Inject constructor(
context = TAG
)
openChannelWithPaidOrders()
}.onFailure {
Logger.error("Failed to refresh orders", it, context = TAG)
}.also {
isRefreshing = false
}

isRefreshing = false
}

suspend fun refreshMinCjitSats() = withContext(bgDispatcher) {
Expand Down Expand Up @@ -303,7 +301,7 @@ class BlocktankRepo @Inject constructor(
): Result<IBtOrder?> = withContext(bgDispatcher) {
runCatching {
if (refresh) {
refreshOrders()
refreshOrders().getOrThrow()
}
val order = _blocktankState.value.orders.find { it.id == orderId }
return@runCatching order
Expand Down
46 changes: 34 additions & 12 deletions app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -263,19 +263,40 @@ class TransferViewModel @Inject constructor(
}

private suspend fun pollUntil(orderId: String, condition: (IBtOrder) -> Boolean): IBtOrder? {
var consecutiveErrors = 0

while (true) {
val order = blocktankRepo.getOrder(orderId, refresh = true).getOrNull()
if (order == null) {
Logger.error("Order not found: '$orderId'", context = TAG)
return null
}
if (order.state2 == BtOrderState2.EXPIRED) {
Logger.error("Order expired: '$orderId'", context = TAG)
return null
}
if (condition(order)) {
return order
}
blocktankRepo.getOrder(orderId, refresh = true).fold(
onSuccess = { order ->
consecutiveErrors = 0

if (order == null) {
Logger.error("Order not found: '$orderId'", context = TAG)
return null
}
if (order.state2 == BtOrderState2.EXPIRED) {
Logger.error("Order expired: '$orderId'", context = TAG)
return null
}
if (condition(order)) {
return order
}
},
onFailure = {
consecutiveErrors++
Logger.warn(
"Failed to fetch order '$orderId' (attempt $consecutiveErrors/$MAX_CONSECUTIVE_ERRORS)",
it,
context = TAG
)

if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
Logger.error("Too many consecutive errors polling order '$orderId', giving up", context = TAG)
return null
}
}
)

delay(POLL_INTERVAL_MS)
}
}
Expand Down Expand Up @@ -539,6 +560,7 @@ class TransferViewModel @Inject constructor(
private const val TAG = "TransferViewModel"
private const val MIN_STEP_DELAY_MS = 500L
private const val POLL_INTERVAL_MS = 2_500L
private const val MAX_CONSECUTIVE_ERRORS = 5
const val LN_SETUP_STEP_0 = 0
const val LN_SETUP_STEP_1 = 1
const val LN_SETUP_STEP_2 = 2
Expand Down
20 changes: 20 additions & 0 deletions app/src/test/java/to/bitkit/repositories/BlocktankRepoTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,24 @@ class BlocktankRepoTest : BaseUnitTest() {
assertTrue(result.isSuccess)
assertNull(result.getOrThrow())
}

@Test
fun `refreshOrders returns failure when server throws`() {
sut = createSut()
whenever { coreService.blocktank.orders(refresh = true) }.thenThrow(RuntimeException("Network error"))
test {
val result = sut.refreshOrders()
assertTrue(result.isFailure)
}
}

@Test
fun `getOrder returns failure when refresh fails`() {
sut = createSut()
whenever { coreService.blocktank.orders(refresh = true) }.thenThrow(RuntimeException("Network error"))
test {
val result = sut.getOrder(testOrder1.id, refresh = true)
assertTrue(result.isFailure)
}
}
}
Loading