Skip to content

fix: keep foreground inbox checks responsive - #1321

Merged
jvsena42 merged 3 commits into
masterfrom
codex/paykit-ten-second-inbox
Sep 22, 2026
Merged

jvsena42 merged 3 commits into
masterfrom
codex/paykit-ten-second-inbox

Conversation

@ben-kaufman

@ben-kaufman ben-kaufman commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

This PR keeps foreground Paykit inbox checks on a ten-second interval while online so an idle inbox or failed check does not slow down subsequent requests.

iOS counterpart: synonymdev/bitkit-ios#769

Description

  • Uses a fixed ten-second delay between periodic inbox rounds, including after failures, so one contact's error does not back off polling for everyone.
  • Skips periodic inbox and maintenance work while offline without accumulating a longer delay that survives reconnect.
  • Keeps contact discovery, endpoint maintenance and proof reconciliation on their slower schedule, and preserves the initial handshake burst and foreground lifecycle.
  • Reuses existing refresh handling and removes the success/failure result plumbing that was only needed for adaptive polling.

Out of Scope

  • Paykit SDK, private-payment resolution and UI: no changes. SDK peer sequencing and network timeouts remain unchanged, so a slow network call can still extend a round.
  • Background delivery: no new background polling or push mechanism.
  • Resource profiling: no real-device battery or network measurements. Steady-state idle polling increases from roughly two to six rounds per minute, while heavier maintenance remains unchanged.

Design

N/A — no UI changes.

Preview

N/A — no UI changes.

QA Notes

Manual Tests

  • 1. Two linked Paykit wallets → keep the receiving wallet open and idle beyond the initial burst → send a payment request: the existing Payment Request sheet opens after the next inbox check.
  • 2. Receiver → background the app → return to Wallet: foreground request discovery resumes without a new background polling loop.
  • 3. Receiver → disconnect the network after initial sync → reconnect → send a request: previously received requests remain available and polling does not retain a long offline backoff.

Automated Checks

  • AppViewModelSendFlowTest.kt: unchanged and failed inbox rounds retain ten-second checks, maintenance remains slower, offline periodic work is skipped, reconnect resumes promptly and stopping polling cancels subsequent checks. The prior failure-backoff test now verifies fixed cadence through failure and recovery.
  • PaykitPaymentRequestRepoTest.kt: SDK-reported peer errors do not discard received requests.
  • Local compile and full unit suite passed: 2,743 tests, zero failures. Used installed NDK 28.2.13676358 and -Dmaven.repo.local=/private/tmp/bitkit-fixed-inbox-empty-maven to bypass local Maven overrides.
  • Repository detekt and whitespace checks passed with unrelated existing warnings. Existing demo apps and the manual flows above were not changed or exercised.

@greptile-apps

greptile-apps Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge; no actionable correctness, security, or repository-rule violations remain.

Summary

This PR revises foreground Paykit inbox polling so successful checks remain on a ten-second cadence while unsuccessful checks progressively back off.

  • Propagates per-peer intake failures through the repository refresh result without discarding successfully received requests.
  • Skips periodic inbox and maintenance work while offline and performs maintenance once it becomes due again.
  • Adds coverage for unchanged successful inboxes, failure backoff and recovery, offline behavior, cancellation, and partial peer-intake failures.
  • Updates the changelog to describe the revised foreground polling behavior.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Foreground polling active] --> B[Wait for current interval]
    B --> C{Connected?}
    C -- No --> D[Skip inbox and maintenance work]
    D --> E[Increase backoff up to 120 seconds]
    E --> B
    C -- Yes --> F{Maintenance due?}
    F -- Yes --> G[Republish identity and refresh endpoints]
    F -- No --> H[Refresh Paykit inbox]
    G --> H
    H --> I{All peer intake reports successful?}
    I -- Yes --> J[Apply requests and reset interval to 10 seconds]
    I -- No --> K[Retain applied requests and increase backoff]
    J --> B
    K --> B
Loading

Reviews (1) · Last reviewed commit: "fix: keep foreground inbox checks respon..."

@github-actions

github-actions Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Regtest APK

Built from 26faac5 (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@ben-kaufman

ben-kaufman commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor Author

Fixed the matching reconnect issue found during review of synonymdev/bitkit-ios#769 in d8f3e43. Reconnecting now restarts the existing polling job only if foreground polling is active, so it does not remain asleep on the old 120-second backoff or start a background loop. Extended the existing reconnect test to verify ten-second checks after offline backoff and after the initial burst has ended. Compile, all 2,743 unit tests, and lint pass.

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No findings at 26faac5e9.

PaykitPaymentRequestRepo.kt is identical to master at head, so the new repo test peer intake failure does not drop received requests pins behaviour that already existed.

Checked and clean:

  • No auto-pay. The poll path goes refresh() → presentIncomingPaymentRequestOrStop() → beginPaymentRequest(), which only resolves the request, then openContactPayment() opens the Send sheet. Payment still needs user confirmation. Subscription proposals go to the Review sheet.
  • Overlapping polls. The periodic job, the 15-shot burst, the reconnect refresh and the notification-tap refresh all serialise on operationMutex. dismiss, markPresented and dismissSubscriptionPayment take the same mutex, so a stale concurrent refresh cannot bring back a dismissed or declined request. Presentation is single-flighted by isPresentingPaymentRequest and generation counters.
  • Cancellation. Reconnect now cancels the job in the foreground. synchronizeLocked does all remote calls first and writes state at the end, so a cancel mid-refresh leaves state untouched. runSuspendCatching rethrows before discardExpiredRequestsLocked() runs.
  • Reconnect vs ON_STOP. No suspension point sits between cancel() and startPaykitPaymentRequestPolling(), and both run on Main, so a stopped app never gets a background loop.
  • Runaway. The interval is a fixed 10 s, foreground only. Offline ticks do no I/O, and isOnline is conflated. The 30/60/120 s maintenance cadence is unchanged.
  • Gating. refreshIncomingPaykitPaymentRequests and refreshPaymentRequestTargets return early when Paykit is disabled or no wallet exists.
  • Parity with synonymdev/bitkit-ios#769. Both use the same fixed 10 s interval and the same reconnect side effects. iOS cancels the loop while offline, and Android keeps ticking with continue; the net behaviour is the same. The restart-on-reconnect (749-753) is redundant now that the backoff is gone. It is harmless.

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utAck

@jvsena42
jvsena42 merged commit 8be2351 into master Sep 22, 2026
19 checks passed
@jvsena42
jvsena42 deleted the codex/paykit-ten-second-inbox branch September 22, 2026 11:48
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.

2 participants