Skip to content

feat: increase background stop debounce time - #1146

Open
jvsena42 wants to merge 3 commits into
masterfrom
feat/increase-stop-debounce-time
Open

feat: increase background stop debounce time#1146
jvsena42 wants to merge 3 commits into
masterfrom
feat/increase-stop-debounce-time

Conversation

@jvsena42

@jvsena42 jvsena42 commented Aug 11, 2026

Copy link
Copy Markdown
Member

This PR raises the background stop debounce from 3 to 5 seconds, so a brief trip out of the app no longer tears down and rebuilds the Lightning node.

Description

When the app is backgrounded without the foreground service keeping it alive, the node stop is deferred so a quick background/foreground cycle does not tear it down. Three seconds is short enough that ordinary interruptions — checking a notification, copying an address, fetching a 2FA code — fall outside the window and pay for a full teardown and rebuild.

The ceiling on that window is Android's cached-app freezer, not any API limit. Once the process drops to oom_adj 900 it is frozen after roughly ten seconds, and a frozen process cannot run the pending stop at all: it would fire on unfreeze instead, racing the cancel that runs when the app returns to the foreground. Because the stop runs NonCancellable, losing that race tears the node down exactly as the user comes back. Five seconds sits comfortably inside that window while covering meaningfully more of the short interruptions the debounce exists for.

Device testing also showed the cost of a teardown is far higher than assumed. On a wallet with real payment history the node stop takes a flat 30 seconds and ends by hitting ldk_node's own event-handling deadline, after which the rebuild takes another eight. A user who returns mid-stop waits that out before the wallet is usable again, which is what makes avoiding an unnecessary teardown worth the longer window.

That 30-second timeout is pre-existing and independent of this change — the debounce only decides when the stop begins, not how long it takes — but it is worth a separate look, since every background cycle on a real wallet now burns 30 seconds of the LDK queue and exits through an error path.

The KDoc on stopDebounced records the freezer ceiling so the value is not later raised past it.

Preview

No UI changes.

QA Notes

Manual Tests

  • 1. Home → background the app → return within 5s: wallet stays loaded, no reload or restore screen, balances render immediately.
  • 2. Home → background the app → wait past 5s → return: node restarts cleanly, balances and activity list render.
  • 3. regression: Notifications granted and keep-active-in-background enabled → background the app: foreground service keeps the node alive, no stop occurs at all.
  • 4. regression: Background the app → return mid-restart: no crash, wallet settles into a usable state.

Automated Checks

  • Unit tests modified: LightningRepoTest.kt tracks the new 5s value; its boundary assertions still pin that the stop does not fire just before the window and does fire at it.
  • Device verification on an Android 17 emulator against a wallet loaded with 137 Lightning payments (120 generated via the Blocktank regtest LSP): the debounce fired at 5.002s / 4.999s / 5.001s / 4.997s across four runs.
  • Freezer ceiling measured on the same device: freezer_cutoff_adj=900, freeze_debounce_timeout unset so the AOSP 10s default applies; the process was observed frozen 8.79–9.34s after dropping to cached.
  • CI: standard compile, unit test, and detekt checks run by the PR bot.
Journey used for testing
<journey name="Background stop debounce restart path">
   <description>
      Verifies the Lightning node restart path around BACKGROUND_STOP_DELAY (5s).
      Leg 1 returns to the app inside the debounce window, where the node must never be torn down.
      Leg 2 stays away past the window, so the node stops and must restart cleanly on return.
   </description>
   <actions>
     <action>
       Verify that the wallet Home screen is shown with a balance displayed
     </action>
     <action>
       Tap the Home system navigation button to send the app to the background
     </action>
     <action>
       Relaunch the Bitkit app within 5 seconds
     </action>
     <action>
       Verify that the wallet Home screen is shown with a balance displayed, and that no loading spinner or restore screen is present
     </action>
     <action>
       Tap the Home system navigation button to send the app to the background
     </action>
     <action>
       Wait 20 seconds, then relaunch the Bitkit app
     </action>
     <action>
       Verify that the wallet Home screen is shown with a balance displayed, and that no loading spinner or restore screen is present
     </action>
   </actions>
</journey>

All seven actions passed. Leg 1 confirmed the node is never stopped inside the window; leg 2 confirmed a clean stop and restart past it.

Logs: debounce fires at 5s, inside the window (leg 1)
13:14:40.109 INFO  [BoltzService.kt:168]   Stopped Boltz updates stream
13:14:40.979 INFO  [LightningRepo.kt:474]  LDK node start skipped, lifecycle state: Running
13:14:40.997 DEBUG [LightningService.kt]   LDK event listener started

Returned 2.0s after backgrounding. No Stopping node… entry — the node was never torn down. The event listener cancel and restart 15ms apart is the normal foreground re-subscribe.

Logs: debounce timing across four runs on a 137-payment wallet
run 1   ON_STOP 13:43:48.801 → Stopping node… 13:43:53.803   = 5.002s
run 2   ON_STOP 13:46:18.865 → Stopping node… 13:46:23.864   = 4.999s
run 3   ON_STOP 13:48:49.114 → Stopping node… 13:48:54.115   = 5.001s
run 4   ON_STOP 13:53:22.509 → Stopping node… 13:53:27.506   = 4.997s
Logs: pre-existing 30s stop timeout surfaced during testing
13:48:54.115 DEBUG [LightningService.kt:467]              Stopping node…
13:48:54.116 INFO  [ldk_node:1022]                        Shutting down LDK Node with node ID 024fce4685…
13:48:54.117 DEBUG [ldk_node:685]                         Stopping processing events.
13:48:54.117 TRACE [lightning_background_processor:1299]  Terminating background processor.
13:49:24.123 ERROR [ldk_node::runtime:183]                Stopping event handling timed out: deadline has elapsed
13:49:24.124 INFO  [ldk_node:1074]                        Shutdown complete.
13:49:24.129 INFO  [LightningService.kt:476]              Node stopped

30.014s / 30.022s / 30.030s / 30.047s across the four runs — a flat deadline rather than load-dependent variance. Against a near-empty wallet the same stop took ~0.5s, which is why this only appears with real payment history. Independent of this change; flagged for separate follow-up.

@jvsena42 jvsena42 self-assigned this Aug 11, 2026
@greptile-apps

greptile-apps Bot commented Aug 11, 2026

Copy link
Copy Markdown

Greptile Summary

This PR extends the Lightning node’s background-stop debounce from three to five seconds to avoid unnecessary teardown and restart during brief app switches.

  • Updates the repository debounce constant and documents the Android cached-app freezer constraint.
  • Adjusts lifecycle timing tests to assert the new five-second boundary.
  • Adds a user-facing changelog entry.

Confidence Score: 5/5

The PR appears safe to merge, with the timing update remaining within the documented freezer window and existing atomic cancellation behavior preserved.

The change only extends an already-tested debounce constant and updates its assertions and documentation; no concrete blocking or non-blocking defect remains.

Important Files Changed

Filename Overview
app/src/main/java/to/bitkit/repositories/LightningRepo.kt Increases the existing background-stop delay to five seconds and documents its lifecycle constraints without changing scheduling or cancellation semantics.
app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt Updates the shared expected debounce duration while retaining boundary and cancellation coverage.
changelog.d/next/1146.changed.md Accurately describes the user-visible benefit of retaining the Lightning node during brief app switches.

Reviews (1): Last reviewed commit: "doc: changelog" | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant