Skip to content

Commit 35ea51e

Browse files
committed
feat: use battery saving sync intervals
1 parent 9a50246 commit 35ea51e

4 files changed

Lines changed: 76 additions & 4 deletions

File tree

app/src/main/java/to/bitkit/androidServices/LightningNodeService.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import android.os.IBinder
99
import androidx.annotation.RequiresApi
1010
import androidx.core.app.NotificationCompat
1111
import androidx.core.content.ContextCompat
12+
import androidx.lifecycle.DefaultLifecycleObserver
13+
import androidx.lifecycle.LifecycleOwner
14+
import androidx.lifecycle.ProcessLifecycleOwner
1215
import dagger.hilt.android.AndroidEntryPoint
1316
import kotlinx.coroutines.CoroutineDispatcher
1417
import kotlinx.coroutines.CoroutineScope
@@ -54,10 +57,15 @@ class LightningNodeService : Service() {
5457
@Inject
5558
lateinit var cacheStore: CacheStore
5659

60+
private var lifecycleObserver: AppLifecycleObserver? = null
61+
5762
override fun onCreate() {
5863
super.onCreate()
5964
startForeground(ID_NOTIFICATION_NODE, createNotification())
6065
setupService()
66+
lifecycleObserver = AppLifecycleObserver().also {
67+
ProcessLifecycleOwner.get().lifecycle.addObserver(it)
68+
}
6169
}
6270

6371
private fun setupService() {
@@ -145,6 +153,7 @@ class LightningNodeService : Service() {
145153

146154
override fun onDestroy() {
147155
Logger.debug("onDestroy", context = TAG)
156+
lifecycleObserver?.let { ProcessLifecycleOwner.get().lifecycle.removeObserver(it) }
148157
serviceScope.launch {
149158
lightningRepo.stop()
150159
serviceScope.cancel()
@@ -164,6 +173,24 @@ class LightningNodeService : Service() {
164173

165174
override fun onBind(intent: Intent?): IBinder? = null
166175

176+
private inner class AppLifecycleObserver : DefaultLifecycleObserver {
177+
override fun onStart(owner: LifecycleOwner) {
178+
serviceScope.launch {
179+
lightningRepo.disableBatterySavingMode()
180+
.onSuccess { Logger.debug("Sync intervals exited battery saving mode", context = TAG) }
181+
.onFailure { Logger.warn("Error setting sync intervals out of battery saving", it, context = TAG) }
182+
}
183+
}
184+
185+
override fun onStop(owner: LifecycleOwner) {
186+
serviceScope.launch {
187+
lightningRepo.enableBatterySavingMode()
188+
.onSuccess { Logger.debug("Sync intervals entered battery saving mode", context = TAG) }
189+
.onFailure { Logger.warn("Error setting sync intervals set to battery saving", it, context = TAG) }
190+
}
191+
}
192+
}
193+
167194
companion object {
168195
const val CHANNEL_ID_NODE = "bitkit_notification_channel_node"
169196
const val TAG = "LightningNodeService"

app/src/main/java/to/bitkit/env/Env.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.os.Build
44
import org.lightningdevkit.ldknode.LogLevel
55
import org.lightningdevkit.ldknode.Network
66
import org.lightningdevkit.ldknode.PeerDetails
7+
import org.lightningdevkit.ldknode.RuntimeSyncIntervals
78
import to.bitkit.BuildConfig
89
import to.bitkit.ext.ensureDir
910
import to.bitkit.ext.of
@@ -20,12 +21,17 @@ internal object Env {
2021
val e2eBackend = BuildConfig.E2E_BACKEND.lowercase()
2122
val network = Network.valueOf(BuildConfig.NETWORK)
2223
val locales = BuildConfig.LOCALES.split(",")
23-
const val walletSyncIntervalSecs = 10_uL
2424
val platform = "Android ${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})"
2525
const val version = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
2626

2727
val ldkLogLevel = LogLevel.TRACE
2828

29+
val syncIntervals = RuntimeSyncIntervals(
30+
onchainWalletSyncIntervalSecs = 80_uL, // ldk-node default
31+
lightningWalletSyncIntervalSecs = 30_uL, // ldk-node default
32+
feeRateCacheUpdateIntervalSecs = 600_uL, // ldk-node default (10 min)
33+
)
34+
2935
val trustedLnPeers
3036
get() = when (network) {
3137
Network.BITCOIN -> listOf(Peers.lnd1, Peers.lnd3, Peers.lnd4)

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import org.lightningdevkit.ldknode.ChannelDataMigration
3636
import org.lightningdevkit.ldknode.ChannelDetails
3737
import org.lightningdevkit.ldknode.ClosureReason
3838
import org.lightningdevkit.ldknode.Event
39+
import org.lightningdevkit.ldknode.NodeException
3940
import org.lightningdevkit.ldknode.NodeStatus
4041
import org.lightningdevkit.ldknode.PaymentDetails
4142
import org.lightningdevkit.ldknode.PaymentId
@@ -439,6 +440,30 @@ class LightningRepo @Inject constructor(
439440
/** Clear pending sync flag. Called when manual pull-to-refresh takes priority. */
440441
fun clearPendingSync() = syncPending.set(false)
441442

443+
suspend fun enableBatterySavingMode(): Result<Unit> = executeWhenNodeRunning("enableBatterySavingMode") {
444+
runCatching {
445+
lightningService.updateSyncIntervals(lightningService.batterySavingIntervals())
446+
}.recoverCatching { e ->
447+
if (e is NodeException.BackgroundSyncNotEnabled) {
448+
Logger.warn("Background sync not enabled, skipping sync intervals update", context = TAG)
449+
} else {
450+
throw e
451+
}
452+
}
453+
}
454+
455+
suspend fun disableBatterySavingMode(): Result<Unit> = executeWhenNodeRunning("disableBatterySavingMode") {
456+
runCatching {
457+
lightningService.updateSyncIntervals(lightningService.defaultSyncIntervals())
458+
}.recoverCatching { e ->
459+
if (e is NodeException.BackgroundSyncNotEnabled) {
460+
Logger.warn("Background sync not enabled, skipping sync intervals update", context = TAG)
461+
} else {
462+
throw e
463+
}
464+
}
465+
}
466+
442467
private suspend fun refreshChannelCache() = withContext(bgDispatcher) {
443468
lightningService.channels?.forEach {
444469
channelCache[it.channelId] = it

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import org.lightningdevkit.ldknode.NodeStatus
3434
import org.lightningdevkit.ldknode.PaymentDetails
3535
import org.lightningdevkit.ldknode.PaymentId
3636
import org.lightningdevkit.ldknode.PeerDetails
37+
import org.lightningdevkit.ldknode.RuntimeSyncIntervals
3738
import org.lightningdevkit.ldknode.SpendableUtxo
3839
import org.lightningdevkit.ldknode.Txid
3940
import org.lightningdevkit.ldknode.defaultConfig
@@ -193,9 +194,9 @@ class LightningService @Inject constructor(
193194
serverUrl = serverUrl,
194195
config = ElectrumSyncConfig(
195196
BackgroundSyncConfig(
196-
onchainWalletSyncIntervalSecs = Env.walletSyncIntervalSecs,
197-
lightningWalletSyncIntervalSecs = Env.walletSyncIntervalSecs,
198-
feeRateCacheUpdateIntervalSecs = Env.walletSyncIntervalSecs,
197+
onchainWalletSyncIntervalSecs = Env.syncIntervals.onchainWalletSyncIntervalSecs,
198+
lightningWalletSyncIntervalSecs = Env.syncIntervals.lightningWalletSyncIntervalSecs,
199+
feeRateCacheUpdateIntervalSecs = Env.syncIntervals.feeRateCacheUpdateIntervalSecs,
199200
),
200201
),
201202
)
@@ -275,6 +276,19 @@ class LightningService @Inject constructor(
275276
Logger.debug("LDK synced", context = TAG)
276277
}
277278

279+
suspend fun updateSyncIntervals(intervals: RuntimeSyncIntervals) = withContext(bgDispatcher) {
280+
val node = this@LightningService.node ?: throw ServiceError.NodeNotSetup()
281+
ServiceQueue.LDK.background {
282+
node.updateSyncIntervals(intervals)
283+
}
284+
Logger.info("Sync intervals updated", context = TAG)
285+
}
286+
287+
fun defaultSyncIntervals(): RuntimeSyncIntervals = Env.syncIntervals
288+
289+
fun batterySavingIntervals(): RuntimeSyncIntervals =
290+
org.lightningdevkit.ldknode.batterySavingSyncIntervals()
291+
278292
suspend fun sign(message: String): String {
279293
val node = this.node ?: throw ServiceError.NodeNotSetup()
280294
val msg = runCatching { message.uByteList }.getOrNull() ?: throw ServiceError.InvalidNodeSigningMessage()

0 commit comments

Comments
 (0)