Keep Android taps responsive during vault saves and WebDAV syncs #6

Open
salix wants to merge 1 commit from perf/android-tap-latency into main
Owner

What & why

Taps on Android could sit for seconds with no response: every connect stamped last-used with a full vault save (Argon2 is re-derived on every write), and the whole WebDAV round trip then ran on the same worker loop that answers every other tap — with no indicator, because the busy flag clears before the sync starts. This PR batches last-used stamps into one debounced save, moves background syncs off the worker loop onto a client clone, and shows the busy bar while a sync runs, so taps stay responsive and the remaining stalls are visible.

(No screenshot: worker-level change; the only UI difference is the existing busy bar now also covering syncs.)

Verify

  • cargo test -p ferry-core -p ferry-ffi — 373 tests, including the new touch-batching test and the deferred password-rotation merge
  • Connect to a host with WebDAV configured: taps stay responsive while the sync uploads, and the busy bar shows during it

Follow-ups, deliberately not here: spawn_blocking for the persist itself (the KDF still runs inline, now at most once per 15 s batch), and splitting transfer progress out of the app state (10 Hz full-tree recomposition).

## What & why Taps on Android could sit for seconds with no response: every connect stamped last-used with a full vault save (Argon2 is re-derived on every write), and the whole WebDAV round trip then ran on the same worker loop that answers every other tap — with no indicator, because the busy flag clears before the sync starts. This PR batches last-used stamps into one debounced save, moves background syncs off the worker loop onto a client clone, and shows the busy bar while a sync runs, so taps stay responsive and the remaining stalls are visible. *(No screenshot: worker-level change; the only UI difference is the existing busy bar now also covering syncs.)* ## Verify - `cargo test -p ferry-core -p ferry-ffi` — 373 tests, including the new touch-batching test and the deferred password-rotation merge - Connect to a host with WebDAV configured: taps stay responsive while the sync uploads, and the busy bar shows during it Follow-ups, deliberately not here: `spawn_blocking` for the persist itself (the KDF still runs inline, now at most once per 15 s batch), and splitting transfer progress out of the app state (10 Hz full-tree recomposition).
Keep Android taps responsive during vault saves and WebDAV syncs
Some checks are pending
Build Android nightly and check shared core / android (pull_request) Has started running
711b7ce391
Diagnosed from the tap path: a click dispatches into a serialized Kotlin
worker that only forwards to the Rust backend, so tap latency is decided
by the worker loop in core/src/runtime.rs. Three things stacked there
after the last release:

- Every successful Android connect stamps last-used (touch_host) with a
  full host record, so the worker ran a complete vault save - Argon2id
  at 64 MiB, re-derived by the keepass crate on every write ("keys and
  seeds on the fly when saving") - on the loop, right after the user
  started tapping around the new session.
- save_host then awaited the WebDAV sync inline, so the whole network
  round trip (with retry backoff on failure) also ran on the loop.
  During those seconds no command was processed and no event emitted:
  every further tap queued behind the network.
- Nothing showed on screen, because HostSaved is emitted before the
  sync and clears the busy flag; taps just appeared dead. On a phone
  the KDF is several times slower than the "roughly a second on a
  desktop" the parameters are tuned for, and the sync rides mobile
  network.

Changes:

- touch_host now sends TouchHost; the worker batches stamps like OS
  observations and flushes them in one save after 15 s, skipping
  missing or recycled hosts silently. Lock and shutdown flush first,
  so stamps survive.
- Post-save syncs are debounced (2 s) and run on a clone of the WebDav
  client in a spawned task; the loop keeps taking commands and events
  while the request is on the network. The finished client copy returns
  with its updated sync history, guarded by a generation counter
  against reconfigure or lock mid-flight; a baseline reload requested
  during a password change is replayed when the client is restored. A
  sync requested while one is in flight is remembered and runs after.
  Shutdown still syncs inline and drains an in-flight request first,
  bounded by the existing timeout.
- The Android shell's busy bar also shows while a sync runs, so the
  remaining rare stalls are visible.

Verify: cargo test -p ferry-core -p ferry-ffi (373 tests, including
touch batching and the deferred password-rotation merge). The JVM
contract tests need a JDK/SDK absent here, so the Gradle suite is left
to CI. Debug builds of the native core remain unoptimized by default
(FERRY_ANDROID_PROFILE=release for distribution); that is documented
and unchanged.
Some checks are pending
Build Android nightly and check shared core / android (pull_request) Has started running
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin perf/android-tap-latency:perf/android-tap-latency
git switch perf/android-tap-latency

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff perf/android-tap-latency
git switch perf/android-tap-latency
git rebase main
git switch main
git merge --ff-only perf/android-tap-latency
git switch perf/android-tap-latency
git rebase main
git switch main
git merge --no-ff perf/android-tap-latency
git switch main
git merge --squash perf/android-tap-latency
git switch main
git merge --ff-only perf/android-tap-latency
git switch main
git merge perf/android-tap-latency
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
salix/ferry!6
No description provided.