Skip to content

[No QA] stop syncing app data when the app comes to the foreground - #98888

Merged
mountiny merged 5 commits into
Expensify:mainfrom
callstack-internal:2801-reconnect-dedup
Aug 31, 2026
Merged

mountiny merged 5 commits into
Expensify:mainfrom
callstack-internal:2801-reconnect-dedup

Conversation

@adhorodyski

@adhorodyski adhorodyski commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Explanation of Change

Removes the foreground reconnect() call: every foreground fired a ReconnectApp, and the Pusher resubscription fires the same sync a second later. A resubscription proves the socket came back, a foreground proves nothing. Queue flushing stays. Native only — web never fired this listener.

Drops 5.0% of pushed ReconnectApp: 15,568 of 194,497 triggers in 2026-08-17T10:30-14:30Z. The 6.7% of foregrounds without a same-minute resubscribe wait for the next event, up to 150s (pusher-js activityTimeout + pongTimeout) until #98884 lands.

NetworkState.onReachabilityConfirmed() still calls reconnect(): two of its three publishers are hard stops where the socket never dropped, so nothing resubscribes (src/libs/NetworkState.ts:158-162). #2803 owns that duplicate.

The issue's 4s dedup window would need a constant re-measured whenever #98884 or #99084 change the trigger set.

Before and after

Run on a matched window: same weekday, same hours UTC.

Metric Before Pass
Pushed ReconnectApp 173,896 / 33,487 users = 5.19 per user falls about 5%
Native foreground pairs sending both 3,823 of 6,316 = 60.5% under 10%
[Reconnect] Triggering reconnection 194,497 falls by about 15,568

Control, must not move

"GetMissingOnyxMessages did not advance the client" | stats count() n, count_uniq(email) users

Gap-detection escalation ran at 0.39%, 141 of 35,720, on 08-12. A rise means full syncs were traded for stalled clients.

Fixed Issues

$ #93966
PROPOSAL:

Tests

  1. npx jest tests/unit/ReconnectTest.ts — 7 pass, including foreground flushes the queue without syncing.
  2. npx jest tests/unit/NetworkStateTest.ts tests/unit/NetworkStateReachabilityTest.ts — reachability recovery still syncs.
  3. iOS or Android: sign in, background the app for 5 minutes, send yourself a message from another account, then foreground. The message appears. The log shows one [Reconnect] Triggering reconnection for that foreground, after Pusher re-subscribed to private user channel.
  4. Filter the log to command:ReconnectApp "Conflict action determined" and repeat step 3. One push, no second determination.
  5. Send a message while offline, then foreground the app. The queued message sends immediately.
  6. Web control, identical before and after: hide the tab for a few minutes, then focus it. Messages received while hidden are present. shouldReportActivity is false on web, so this listener never ran there and this PR does not touch web behaviour.
  • Verify that no errors appear in the JS console

Offline tests

  1. Go offline, then foreground the app. No sync is attempted, NetworkState.refresh() still runs, and the offline indicator stays up.
  2. Come back online. Reachability recovery syncs as before and the queue flushes.
  3. Go offline, send a message, then foreground the app while still offline. The message stays queued (nothing to flush over the wire yet); once back online it sends.

QA Steps

No QA. This PR has no user-visible UI or copy change. It removes a duplicate background sync so one fewer network request fires on foreground. The behavior is covered by the unit tests and the manual steps in the Tests section.

  • Verify that no errors appear in the JS console

Same as tests.

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I followed proper code patterns (see Reviewing the code)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

This PR has no visual or UI-facing surface — it deletes one function call from a background sync listener, so there is nothing to capture on any platform.

Android: Native

N/A — no visual change.

Android: mWeb Chrome

N/A — no visual change.

iOS: Native

N/A — no visual change.

iOS: mWeb Safari

N/A — no visual change.

MacOS: Chrome / Safari

N/A — no visual change.

A foreground proves nothing about missed events, so this call is a guess. If the
socket died while the app was backgrounded, it resubscribes on foreground and
that resubscription already syncs. If the socket survived, nothing was missed.
If it is a zombie, the Pusher SDK's own activity timeout drops it and the
resubscription syncs there too.

The guess costs a duplicate: the foreground sync fires at t=0 and completes in
282ms, the resubscription fires a median 1.08s later, so the coverage resolver
finds an empty queue and both go on the wire.

Queue flushing on foreground is unchanged, so pending writes still go out
immediately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions

This comment has been minimized.

@IuliiaHerets

Copy link
Copy Markdown

Hi @adhorodyski. The build isn't working for testing. Could you please check?

image

cc @mountiny

@mountiny

Copy link
Copy Markdown
Contributor

Can you sync with main?

@github-actions

Copy link
Copy Markdown
Contributor

🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions

This comment has been minimized.

@mountiny

Copy link
Copy Markdown
Contributor

@adhorodyski please sync up with main we need new builds as the min app version got bumped

@adhorodyski

Copy link
Copy Markdown
Contributor Author

Updated

@jponikarchuk

jponikarchuk commented Aug 27, 2026

Copy link
Copy Markdown

Onboarding - User lands on workspace page instead to home page when signup

Version Number: v9.4.58-0 PR:98888
Reproducible in staging?: No
Reproducible in production?: No
If this was caught during regression testing, add the test name, ID and link from BrowserStack: https://test-management.browserstack.com/projects/2219752/test-runs/71000319/folder/40579099/88288794/1699532193?sort=%2Bstatus_id
Email or phone of affected tester (no customers): gocemate+wo228@gmail.com
Issue reported by: Applause Internal Team
Device used: windows 10/chrome

Action Performed:

  1. Signup with new gmail account
  2. From onboarding modal select Manage my team expenses > 1-4 employees > QBO and complete the flow

Expected Result:

User should land on Home page

Actual Result:

User lands on workspace page

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari

Screenshots/Videos

Video.mp4

@lanitochka17

lanitochka17 commented Aug 27, 2026

Copy link
Copy Markdown

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Android - Track distance page becomes unresponsive when open start point

Version Number: 9.4.58-0 PR:98888
Reproducible in staging?: N
Reproducible in production?: N
If this was caught during regression testing, add the test name, ID and link from TestRail: https://test-management.browserstack.com/projects/2219752/test-runs/71000339/folder/53992883/41237161/1699534097?sort=%2Bstatus_id
Issue reported by: Applause - Internal Team

Action Performed:

  1. Go to FAB_ Track distance> Map
  2. Tap on Start
  3. Tap on Back button on left or add a start point destination

Expected Result:

Page should response

Actual Result:

Page becomes unresponsive, map preview is missing and all tabs (Map ,Manual, GPS, Odometar) does not response

Workaround:

Unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

  • Android: Native
  • Android: mWeb Chrome
  • iOS: Native
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug7244379_1787841999328.Recording__1511.mp4
Upwork Automation - Do Not Edit

    @IuliiaHerets

    Copy link
    Copy Markdown

    @codecov

    codecov Bot commented Aug 31, 2026

    Copy link
    Copy Markdown

    Codecov Report

    ✅ Changes either increased or maintained existing code coverage, great job!

    Files with missing lines Coverage Δ
    src/libs/actions/Reconnect.ts 100.00% <ø> (ø)
    ... and 8 files with indirect coverage changes

    @adhorodyski
    adhorodyski marked this pull request as ready for review August 31, 2026 09:57
    @adhorodyski
    adhorodyski requested review from a team as code owners August 31, 2026 09:57
    @melvin-bot
    melvin-bot Bot requested review from JmillsExpensify and Krishna2323 and removed request for a team August 31, 2026 09:57
    @melvin-bot

    melvin-bot Bot commented Aug 31, 2026

    Copy link
    Copy Markdown

    @Krishna2323 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

    @melvin-bot
    melvin-bot Bot removed the request for review from a team August 31, 2026 09:57

    @chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

    Copy link
    Copy Markdown

    Choose a reason for hiding this comment

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

    💡 Codex Review

    Here are some automated review suggestions for this pull request.

    Reviewed commit: d6756b5663

    ℹ️ About Codex in GitHub

    Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

    • Open a pull request for review
    • Mark a draft as ready
    • Comment "@codex review".

    If Codex has suggestions, it will comment; otherwise it will react with 👍.

    When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

    Comment thread src/libs/actions/Reconnect.ts

    @mountiny mountiny left a comment

    Copy link
    Copy Markdown
    Contributor

    Choose a reason for hiding this comment

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

    Reviewer Checklist

    • I have verified the author checklist is complete (all boxes are checked off).
    • I verified the correct issue is linked in the ### Fixed Issues section above
    • I verified testing steps are clear and they cover the changes made in this PR
      • I verified the steps for local testing are in the Tests section
      • I verified the steps for Staging and/or Production testing are in the QA steps section
      • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
      • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I checked that screenshots or videos are included for tests on all platforms
    • I included screenshots or videos for tests on all platforms
    • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
    • I verified tests pass on all platforms & I tested again on:
      • Android: HybridApp
      • Android: mWeb Chrome
      • iOS: HybridApp
      • iOS: mWeb Safari
      • MacOS: Chrome / Safari
    • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
    • I verified proper code patterns were followed (see Reviewing the code)
      • I verified that comments were added to code that is not self explanatory
      • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
      • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
    • I verified that this PR follows the guidelines as stated in the Review Guidelines
    • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
    • If a new component is created I verified that:
      • A similar component doesn't exist in the codebase
      • All props are defined accurately
      • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
      • The only data being stored in the state is data necessary for rendering and nothing else
      • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
    • If a new CSS style is added I verified that:
      • A similar style doesn't already exist
      • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
    • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
    • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
    • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
    • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
    • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
      • I verified that all the inputs inside a form are aligned with each other.
      • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
    • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
    • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
    • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

    Screenshots/Videos

    Android: HybridApp
    Android: mWeb Chrome
    iOS: HybridApp
    iOS: mWeb Safari
    MacOS: Chrome / Safari

    @mountiny

    Copy link
    Copy Markdown
    Contributor

    QA ran full regression testing on these builds and did not find anything specific to these changes. Going to move this ahead and we will carefully observe if anything odd is reported in staging

    @mountiny
    mountiny merged commit 9159c69 into Expensify:main Aug 31, 2026
    39 of 45 checks passed
    @github-actions

    Copy link
    Copy Markdown
    Contributor

    🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here.

    @OSBotify

    Copy link
    Copy Markdown
    Contributor

    ✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

    @OSBotify

    Copy link
    Copy Markdown
    Contributor

    🚀 Deployed to staging by https://github.com/mountiny in version: 9.4.65-0 🚀

    platform result
    🕸 web 🕸 success ✅
    🤖 android 🤖 success ✅
    🍎 iOS 🍎 success ✅

    @MelvinBot

    Copy link
    Copy Markdown
    Contributor

    No help site changes are required. I did not create a docs PR.

    This PR removes one internal network call and changes no user-facing behavior, UI, or copy, so nothing under docs/articles needs updating.

    Why

    The change deletes the reconnect() call from the app-foreground listener in src/libs/actions/Reconnect.ts. Queue flushing still runs on foreground, and the Pusher resubscription still syncs missed data, so users see the same thing: messages and expenses received while the app was backgrounded still appear when they return. Offline behavior is unchanged — queued writes still send once the app is back online.

    Checks I ran:

    • The only doc touched is contributingGuides/NETWORK_STATE_DETECTION.md, a developer guide, not a help site article.
    • I searched docs/articles for "reconnect", "foreground", "background sync", "offline mode", "reopen the app", and "come back online". Every hit was an unrelated integration article (QuickBooks Desktop, NetSuite, Sage Intacct connection or sync errors). No article documents app foreground syncing or offline queue behavior.
    • The PR body itself marks the change [No QA] with no user-visible UI or copy change, which matches what the diff does.

    Since there is no help site PR to review, there is nothing for you to mark Ready for review. If you think a specific article should describe this behavior, tell me which one and I will draft the update.


    view run

    @OSBotify

    OSBotify commented Sep 2, 2026

    Copy link
    Copy Markdown
    Contributor

    🚀 Deployed to production by https://github.com/francoisl in version: 9.4.65-3 🚀

    platform result
    🕸 web 🕸 success ✅
    🤖 android 🤖 success ✅
    🍎 iOS 🍎 success ✅

    Bundle Size Analysis (Sentry):

    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.

    7 participants