Skip to content

Commit c27c0f1

Browse files
committed
refactor: remove periodic sync in favor of events
1 parent fc54b2b commit c27c0f1

File tree

7 files changed

+46
-65
lines changed

7 files changed

+46
-65
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import android.content.Context
44
import dagger.hilt.android.qualifiers.ApplicationContext
55
import kotlinx.coroutines.CoroutineDispatcher
66
import kotlinx.coroutines.CoroutineScope
7+
import kotlinx.coroutines.FlowPreview
78
import kotlinx.coroutines.Job
89
import kotlinx.coroutines.SupervisorJob
910
import kotlinx.coroutines.currentCoroutineContext
1011
import kotlinx.coroutines.delay
1112
import kotlinx.coroutines.flow.MutableStateFlow
1213
import kotlinx.coroutines.flow.StateFlow
1314
import kotlinx.coroutines.flow.asStateFlow
15+
import kotlinx.coroutines.flow.debounce
1416
import kotlinx.coroutines.flow.distinctUntilChanged
1517
import kotlinx.coroutines.flow.drop
1618
import kotlinx.coroutines.flow.first
@@ -262,8 +264,10 @@ class BackupRepo @Inject constructor(
262264
dataListenerJobs.add(activityChangesJob)
263265

264266
// LIGHTNING_CONNECTIONS - Only display sync timestamp, ldk-node manages its own backups
267+
@OptIn(FlowPreview::class)
265268
val lightningConnectionsJob = scope.launch {
266-
lightningService.syncFlow()
269+
lightningService.syncStatusChanged
270+
.debounce(SYNC_STATUS_DEBOUNCE)
267271
.collect {
268272
val lastSync = lightningService.status?.latestLightningWalletSyncTimestamp?.toLong()
269273
?.let { it * 1000 } // Convert seconds to millis
@@ -571,5 +575,6 @@ class BackupRepo @Inject constructor(
571575
private const val BACKUP_CHECK_INTERVAL = 60 * 1000L // 1 minute
572576
private const val FAILED_BACKUP_CHECK_TIME = 30 * 60 * 1000L // 30 minutes
573577
private const val FAILED_BACKUP_NOTIFICATION_INTERVAL = 10 * 60 * 1000L // 10 minutes
578+
private const val SYNC_STATUS_DEBOUNCE = 500L // 500ms debounce for sync status updates
574579
}
575580
}

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
1818
import kotlinx.coroutines.flow.MutableStateFlow
1919
import kotlinx.coroutines.flow.asSharedFlow
2020
import kotlinx.coroutines.flow.asStateFlow
21-
import kotlinx.coroutines.flow.filter
2221
import kotlinx.coroutines.flow.first
2322
import kotlinx.coroutines.flow.update
2423
import kotlinx.coroutines.launch
@@ -828,8 +827,6 @@ class LightningRepo @Inject constructor(
828827
}
829828
}
830829

831-
fun getSyncFlow() = lightningService.syncFlow().filter { lightningState.value.nodeLifecycleState.isRunning() }
832-
833830
fun getNodeId(): String? =
834831
if (_lightningState.value.nodeLifecycleState.isRunning()) lightningService.nodeId else null
835832

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,6 @@ class WalletRepo @Inject constructor(
159159
preActivityMetadataRepo.addPreActivityMetadata(preActivityMetadata)
160160
}
161161

162-
suspend fun observeLdkWallet() = withContext(bgDispatcher) {
163-
// TODO:Refactor: when a sync event is emitted by ldk-node, do the sync, and
164-
// get rid of the entire polling mechanism.
165-
lightningRepo.getSyncFlow()
166-
.collect {
167-
runCatching {
168-
syncNodeAndWallet()
169-
}
170-
}
171-
}
172-
173162
suspend fun syncNodeAndWallet(): Result<Unit> = withContext(bgDispatcher) {
174163
val startHeight = lightningRepo.lightningState.value.block()?.height
175164
Logger.verbose("syncNodeAndWallet started at block height=$startHeight", context = TAG)

app/src/main/java/to/bitkit/services/LightningService.kt

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
package to.bitkit.services
22

33
import kotlinx.coroutines.CoroutineDispatcher
4-
import kotlinx.coroutines.currentCoroutineContext
5-
import kotlinx.coroutines.delay
6-
import kotlinx.coroutines.flow.Flow
4+
import kotlinx.coroutines.flow.MutableSharedFlow
5+
import kotlinx.coroutines.flow.SharedFlow
6+
import kotlinx.coroutines.flow.asSharedFlow
77
import kotlinx.coroutines.flow.first
8-
import kotlinx.coroutines.flow.flow
9-
import kotlinx.coroutines.flow.flowOn
10-
import kotlinx.coroutines.isActive
118
import kotlinx.coroutines.launch
129
import kotlinx.coroutines.withContext
1310
import kotlinx.coroutines.withTimeout
@@ -56,7 +53,6 @@ import javax.inject.Inject
5653
import javax.inject.Singleton
5754
import kotlin.io.path.Path
5855
import kotlin.time.Duration
59-
import kotlin.time.Duration.Companion.seconds
6056

6157
typealias NodeEventHandler = suspend (Event) -> Unit
6258

@@ -72,6 +68,9 @@ class LightningService @Inject constructor(
7268
@Volatile
7369
var node: Node? = null
7470

71+
private val _syncStatusChanged = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
72+
val syncStatusChanged: SharedFlow<Unit> = _syncStatusChanged.asSharedFlow()
73+
7574
private lateinit var trustedPeers: List<PeerDetails>
7675

7776
suspend fun setup(
@@ -230,6 +229,8 @@ class LightningService @Inject constructor(
230229
// launch { setMaxDustHtlcExposureForCurrentChannels() }
231230
}
232231

232+
_syncStatusChanged.tryEmit(Unit)
233+
233234
Logger.debug("LDK synced")
234235
}
235236

@@ -730,13 +731,6 @@ class LightningService @Inject constructor(
730731
val peers: List<PeerDetails>? get() = node?.listPeers()
731732
val channels: List<ChannelDetails>? get() = node?.listChannels()
732733
val payments: List<PaymentDetails>? get() = node?.listPayments()
733-
734-
fun syncFlow(): Flow<Unit> = flow {
735-
while (currentCoroutineContext().isActive) {
736-
emit(Unit)
737-
delay(Env.walletSyncIntervalSecs.toLong().seconds)
738-
}
739-
}.flowOn(bgDispatcher)
740734
// endregion
741735

742736
companion object {

app/src/main/java/to/bitkit/ui/ContentView.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,6 @@ fun ContentView(
243243
}
244244
}
245245

246-
LaunchedEffect(Unit) {
247-
walletViewModel.observeLdkWallet()
248-
}
249-
250246
LaunchedEffect(Unit) { walletViewModel.handleHideBalanceOnOpen() }
251247

252248
LaunchedEffect(appViewModel) {

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

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -226,32 +226,35 @@ class AppViewModel @Inject constructor(
226226
@Suppress("CyclomaticComplexMethod")
227227
private fun observeLdkNodeEvents() {
228228
viewModelScope.launch {
229-
lightningRepo.nodeEvents.collect { event ->
230-
if (!walletRepo.walletExists()) return@collect
231-
Logger.debug("LDK-node event received in $TAG: ${jsonLogOf(event)}", context = TAG)
232-
// TODO maybe use launch
233-
runCatching {
234-
when (event) {
235-
is Event.BalanceChanged -> handleBalanceChanged()
236-
is Event.ChannelClosed -> Unit
237-
is Event.ChannelPending -> Unit
238-
is Event.ChannelReady -> notifyChannelReady(event)
239-
is Event.OnchainTransactionConfirmed -> handleOnchainTransactionConfirmed(event)
240-
is Event.OnchainTransactionEvicted -> handleOnchainTransactionEvicted(event)
241-
is Event.OnchainTransactionReceived -> handleOnchainTransactionReceived(event)
242-
is Event.OnchainTransactionReorged -> handleOnchainTransactionReorged(event)
243-
is Event.OnchainTransactionReplaced -> handleOnchainTransactionReplaced(event)
244-
is Event.PaymentClaimable -> Unit
245-
is Event.PaymentFailed -> handlePaymentFailed(event)
246-
is Event.PaymentForwarded -> Unit
247-
is Event.PaymentReceived -> handlePaymentReceived(event)
248-
is Event.PaymentSuccessful -> handlePaymentSuccessful(event)
249-
is Event.SyncCompleted -> handleSyncCompleted()
250-
is Event.SyncProgress -> Unit
251-
}
252-
}.onFailure { e ->
253-
Logger.error("LDK event handler error", e, context = TAG)
229+
lightningRepo.nodeEvents.collect { handleLdkEvent(it) }
230+
}
231+
}
232+
233+
private fun handleLdkEvent(event: Event) {
234+
if (!walletRepo.walletExists()) return
235+
Logger.debug("LDK-node event received in $TAG: ${jsonLogOf(event)}", context = TAG)
236+
viewModelScope.launch {
237+
runCatching {
238+
when (event) {
239+
is Event.BalanceChanged -> handleBalanceChanged()
240+
is Event.ChannelClosed -> Unit
241+
is Event.ChannelPending -> Unit
242+
is Event.ChannelReady -> notifyChannelReady(event)
243+
is Event.OnchainTransactionConfirmed -> handleOnchainTransactionConfirmed(event)
244+
is Event.OnchainTransactionEvicted -> handleOnchainTransactionEvicted(event)
245+
is Event.OnchainTransactionReceived -> handleOnchainTransactionReceived(event)
246+
is Event.OnchainTransactionReorged -> handleOnchainTransactionReorged(event)
247+
is Event.OnchainTransactionReplaced -> handleOnchainTransactionReplaced(event)
248+
is Event.PaymentClaimable -> Unit
249+
is Event.PaymentFailed -> handlePaymentFailed(event)
250+
is Event.PaymentForwarded -> Unit
251+
is Event.PaymentReceived -> handlePaymentReceived(event)
252+
is Event.PaymentSuccessful -> handlePaymentSuccessful(event)
253+
is Event.SyncCompleted -> handleSyncCompleted()
254+
is Event.SyncProgress -> Unit
254255
}
256+
}.onFailure { e ->
257+
Logger.error("LDK event handler error", e, context = TAG)
255258
}
256259
}
257260
}
@@ -295,14 +298,14 @@ class AppViewModel @Inject constructor(
295298
}
296299

297300
private suspend fun handlePaymentReceived(event: Event.PaymentReceived) {
298-
event.paymentHash?.let { paymentHash ->
301+
event.paymentHash.let { paymentHash ->
299302
activityRepo.handlePaymentEvent(paymentHash)
300303
}
301304
notifyPaymentReceived(event)
302305
}
303306

304307
private suspend fun handlePaymentSuccessful(event: Event.PaymentSuccessful) {
305-
event.paymentHash?.let { paymentHash ->
308+
event.paymentHash.let { paymentHash ->
306309
activityRepo.handlePaymentEvent(paymentHash)
307310
}
308311
notifyPaymentSentOnLightning(event)
@@ -446,7 +449,7 @@ class AppViewModel @Inject constructor(
446449
is SendEvent.ConfirmAmountWarning -> onConfirmAmountWarning(it.warning)
447450
SendEvent.DismissAmountWarning -> onDismissAmountWarning()
448451
SendEvent.PayConfirmed -> onConfirmPay()
449-
SendEvent.ClearPayConfirmation -> _sendUiState.update { it.copy(shouldConfirmPay = false) }
452+
SendEvent.ClearPayConfirmation -> _sendUiState.update { s -> s.copy(shouldConfirmPay = false) }
450453
SendEvent.BackToAmount -> setSendEffect(SendEffect.PopBack(SendRoute.Amount))
451454
SendEvent.NavToAddress -> setSendEffect(SendEffect.NavigateToAddress)
452455
}

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,6 @@ class WalletViewModel @Inject constructor(
168168
}
169169
}
170170

171-
suspend fun observeLdkWallet() {
172-
walletRepo.observeLdkWallet()
173-
}
174-
175171
fun refreshState() = viewModelScope.launch {
176172
walletRepo.syncNodeAndWallet()
177173
.onFailure { error ->
@@ -340,6 +336,7 @@ sealed interface RestoreState {
340336
object Wallet : InProgress
341337
object Metadata : InProgress
342338
}
339+
343340
data object Completed : RestoreState
344341
data object Settled : RestoreState
345342

0 commit comments

Comments
 (0)