Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HOLD for payment 2025-01-13] [HOLD for payment 2024-12-30] [$250] Accounting - Accounting tab loads infinitely when the workspace is created offline #52027

Closed
8 tasks done
IuliiaHerets opened this issue Nov 5, 2024 · 53 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors Weekly KSv2

Comments

@IuliiaHerets
Copy link

IuliiaHerets commented Nov 5, 2024

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: 9.0.57-3
Reproducible in staging?: Y
Reproducible in production?: Y
Email or phone of affected tester (no customers): [email protected]
Issue reported by: Applause Internal Team

Action Performed:

  1. Go to staging.new.expensify.com
  2. Go offline.
  3. Create a new workspace.
  4. Go to workspace settings > More features.
  5. Enable Accounting.
  6. Go to Accounting.
  7. Go online.

Expected Result:

Accounting tab will load after returning online.

Actual Result:

Accounting tab loads infinitely when the workspace is created offline.

Workaround:

Unknown

Platforms:

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6655070_1730782888555.20241105_125138.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021853787863203385081
  • Upwork Job ID: 1853787863203385081
  • Last Price Increase: 2024-11-05
Issue OwnerCurrent Issue Owner: @
Issue OwnerCurrent Issue Owner: @slafortune
@IuliiaHerets IuliiaHerets added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Nov 5, 2024
Copy link

melvin-bot bot commented Nov 5, 2024

Triggered auto assignment to @slafortune (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@bernhardoj
Copy link
Contributor

Proposal

Please re-state the problem that we are trying to solve in this issue.

Infinity loading in accounting page if creating the workspace while offline.

What is the root cause of that problem?

The loading will show if the condition below is met.

if ((isConnectionDataFetchNeeded || isFetchingData || isOnyxDataLoading) && shouldBlockView) {
return <FullScreenLoadingIndicator />;
}

The one that we need to focus on is hasConnectionsDataBeenFetched.

const [hasConnectionsDataBeenFetched, hasConnectionsDataBeenFetchedResult] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${props.policy?.id ?? '-1'}`);
const isOnyxDataLoading = isLoadingOnyxValue(hasConnectionsDataBeenFetchedResult);
const isConnectionDataFetchNeeded =
!isOnyxDataLoading && !isOffline && !!props.policy && (!!props.policy.areConnectionsEnabled || !isEmptyObject(props.policy.connections)) && !hasConnectionsDataBeenFetched;

The hasConnectionsDataBeenFetched will become true if the OPEN_POLICY_ACCOUNTING_PAGE read is completed. We request it only while online.

function openPolicyAccountingPage(policyID: string) {
const hasConnectionsDataBeenFetchedKey = `${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${policyID}` as const;
const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: hasConnectionsDataBeenFetchedKey,
value: true,
},
];
const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: hasConnectionsDataBeenFetchedKey,
value: false,
},
];
const parameters: OpenPolicyAccountingPageParams = {
policyID,
};
API.read(READ_COMMANDS.OPEN_POLICY_ACCOUNTING_PAGE, parameters, {
successData,
failureData,
});

When we make a read request, it will wait for all write requests to complete first, by using the isReadyPromise.

App/src/libs/API/index.ts

Lines 170 to 179 in b1bffa6

* Ensure all write requests on the sequential queue have finished responding before running read requests.
* Responses from read requests can overwrite the optimistic data inserted by
* write requests that use the same Onyx keys and haven't responded yet.
*/
function waitForWrites<TCommand extends ReadCommand>(command: TCommand) {
if (PersistedRequests.getLength() > 0) {
Log.info(`[API] '${command}' is waiting on ${PersistedRequests.getLength()} write commands`);
}
return SequentialQueue.waitForIdle();
}

function waitForIdle(): Promise<unknown> {
return isReadyPromise;
}

However, in our case, the promise is never resolved even after all write requests are completed. That's because, while waiting for the promise to be resolved, the promise is recreated, so the old one is never resolved.

// Reset the isReadyPromise so that the queue will be flushed as soon as the request is finished
isReadyPromise = new Promise((resolve) => {
resolveIsReadyPromise = resolve;
});

It's recreated every time flush is called. After the flush is called, isSequentialQueueRunning is set to true which prevents any subsequent flush from being processed when there is one already running.

isSequentialQueueRunning = true;

if (isSequentialQueueRunning) {
Log.info('[SequentialQueue] Unable to flush. Queue is already running.');
return;
}

But in our case, isSequentialQueueRunning becomes false. That's because when we create the workspace and enable the accounting while offline, the BE will return shouldPauseQueue for EnablePolicyConnections which pause the queue.

if (response?.shouldPauseQueue) {
Log.info("[SequentialQueue] Handled 'shouldPauseQueue' in response. Pausing the queue.");
pause();
}

When it processes the next request, the promise is resolved because the queue is paused,

if (isQueuePaused) {
Log.info('[SequentialQueue] Unable to process. Queue is paused.');
return Promise.resolve();
}

which sets isSequentialQueueRunning to false.

process().finally(() => {
Log.info('[SequentialQueue] Finished processing queue.');
isSequentialQueueRunning = false;

When the queue is unpaused, we call flush again.

function unpause() {
if (!isQueuePaused) {
Log.info('[SequentialQueue] Unable to unpause queue. We are already processing.');
return;
}
const numberOfPersistedRequests = PersistedRequests.getAll().length || 0;
Log.info(`[SequentialQueue] Unpausing the queue and flushing ${numberOfPersistedRequests} requests`);
isQueuePaused = false;
flush();
}

And because isSequentialQueueRunning is false, the isReadyPromise is recreated.

flush -> process (CreateWorkspace) -> process (EnablePolicyConnections) -> pause -> GetMissingOnyxMessages -> unpause -> flush (new isReadyPromise) -> process (ReconnectApp)

What changes do you think we should make in order to solve the problem?

We shouldn't reset the isReadyPromise when unpausing the queue. To do that, we can accept a new param for flush called resume. If it's true, then don't recreate isReadyPromise.

if (!resume) {
    // Reset the isReadyPromise so that the queue will be flushed as soon as the request is finished
    isReadyPromise = new Promise((resolve) => {
        resolveIsReadyPromise = resolve;
    });
}

And pass true when flushing from unpause.

function unpause() {
if (!isQueuePaused) {
Log.info('[SequentialQueue] Unable to unpause queue. We are already processing.');
return;
}
const numberOfPersistedRequests = PersistedRequests.getAll().length || 0;
Log.info(`[SequentialQueue] Unpausing the queue and flushing ${numberOfPersistedRequests} requests`);
isQueuePaused = false;
flush();
}

@slafortune slafortune added the External Added to denote the issue can be worked on by a contributor label Nov 5, 2024
@melvin-bot melvin-bot bot changed the title Accounting - Accounting tab loads infinitely when the workspace is created offline [$250] Accounting - Accounting tab loads infinitely when the workspace is created offline Nov 5, 2024
Copy link

melvin-bot bot commented Nov 5, 2024

Job added to Upwork: https://www.upwork.com/jobs/~021853787863203385081

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Nov 5, 2024
Copy link

melvin-bot bot commented Nov 5, 2024

Triggered auto assignment to Contributor-plus team member for initial proposal review - @ntdiary (External)

@ntdiary
Copy link
Contributor

ntdiary commented Nov 6, 2024

Under review.

still verifying the RCA, will provide an update tomorrow.

@ntdiary
Copy link
Contributor

ntdiary commented Nov 7, 2024

@bernhardoj's RCA is accurate, with only a slight difference from what I checked. :)
pause is called here (in saveUpdateInformation), and shouldPauseQueue is also set to true here:

// Save the update IDs to Onyx so they can be used to fetch incremental updates if the client gets out of sync from the server
OnyxUpdates.saveUpdateInformation(responseToApply);
// Ensure the queue is paused while the client resolves the gap in onyx updates so that updates are guaranteed to happen in a specific order.
return Promise.resolve({
...response,
shouldPauseQueue: true,
});


BTW, just a note, in our current SequentialQueue, we don’t have an exact concept of "current batch"

// If the queue is running this request will run once it has finished processing the current batch
if (isSequentialQueueRunning) {
isReadyPromise.then(flush);
return;
}
flush();

we just ensure that all requests in persistedRequests are executed in order by calling flush in multiple places.

@ntdiary
Copy link
Contributor

ntdiary commented Nov 7, 2024

image

Additionally, @bernhardoj, just a small question: since our code calls unpause in several places, do you think adding this parameter will be safe enough to avoid causing regressions? 😂

@bernhardoj
Copy link
Contributor

I think it should be safe. unpause will only take effect if the queue is currently paused. I think in all cases where pause and unpause happens, we don't want to have a new isReadyPromise because it's still in one "batch".

@ntdiary
Copy link
Contributor

ntdiary commented Nov 8, 2024

Nice, I think it's fine to move forward with @bernhardoj's proposal.
BTW, just a tiny thought, I'm not entirely sure if resume is clear and accurate enough (my English isn’t good), maybe can use shouldResetPromise(default value is true). Let's see if the internal engineer has any other thoughts. :)

🎀 👀 🎀 C+ reviewed

Copy link

melvin-bot bot commented Nov 8, 2024

Triggered auto assignment to @srikarparsi, see https://stackoverflow.com/c/expensify/questions/7972 for more details.

Copy link

melvin-bot bot commented Nov 11, 2024

@ntdiary, @slafortune, @srikarparsi Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

@melvin-bot melvin-bot bot added the Overdue label Nov 11, 2024
@srikarparsi
Copy link
Contributor

Will look at this tomorrow

Copy link

melvin-bot bot commented Nov 12, 2024

@ntdiary, @slafortune, @srikarparsi Whoops! This issue is 2 days overdue. Let's get this updated quick!

@srikarparsi
Copy link
Contributor

I agree with the RCA and the proposed solution, lets move forward with @bernhardoj's proposal. I agree that shouldResetPromise is better than resume. One thing I'm not completely sure about is this comment, maybe @danieldoglas does this sound right to you? Saw that you worked on some of the SequentialQueue logic.

@danieldoglas
Copy link
Contributor

thanks for that investigation @bernhardoj !

I agree that it looks a lot like an issue in the frontend, but I think it's an issue in the backend. If you're doing 2 sequential writes and constantly finding a gap between the requests (CreateWorkspace -> EnablePolicyConnections) then that means that the first request is not returning all the data the app needs.

@srikarparsi I recommend you try this flow locally, and find out which onyxUpdates were not returned, and check the backend code to confirm if they're being sent back on the HTTPs request before we start anything in the front end here.

Copy link

melvin-bot bot commented Nov 14, 2024

@ntdiary, @slafortune, @srikarparsi Huh... This is 4 days overdue. Who can take care of this?

Copy link

melvin-bot bot commented Nov 18, 2024

@ntdiary, @slafortune, @srikarparsi 8 days overdue is a lot. Should this be a Weekly issue? If so, feel free to change it!

Copy link

melvin-bot bot commented Nov 19, 2024

@ntdiary @slafortune @srikarparsi this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

@muttmuure muttmuure moved this to CRITICAL in [#whatsnext] #quality Nov 19, 2024
@ntdiary
Copy link
Contributor

ntdiary commented Nov 19, 2024

@srikarparsi I recommend you try this flow locally, and find out which onyxUpdates were not returned, and check the backend code to confirm if they're being sent back on the HTTPs request before we start anything in the front end here.

It seems to be waiting for some investigation results from the backend. :)

@melvin-bot melvin-bot bot added the Weekly KSv2 label Dec 13, 2024
@bernhardoj
Copy link
Contributor

PR is ready

cc: @ntdiary

@melvin-bot melvin-bot bot added Weekly KSv2 and removed Weekly KSv2 labels Dec 17, 2024
@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production and removed Weekly KSv2 labels Dec 23, 2024
@melvin-bot melvin-bot bot changed the title [$250] Accounting - Accounting tab loads infinitely when the workspace is created offline [HOLD for payment 2024-12-30] [$250] Accounting - Accounting tab loads infinitely when the workspace is created offline Dec 23, 2024
@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label Dec 23, 2024
Copy link

melvin-bot bot commented Dec 23, 2024

Reviewing label has been removed, please complete the "BugZero Checklist".

Copy link

melvin-bot bot commented Dec 23, 2024

The solution for this issue has been 🚀 deployed to production 🚀 in version 9.0.77-6 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2024-12-30. 🎊

For reference, here are some details about the assignees on this issue:

  • @ntdiary requires payment through NewDot Manual Requests
  • @bernhardoj requires payment through NewDot Manual Requests

Copy link

melvin-bot bot commented Dec 23, 2024

@ntdiary @slafortune @ntdiary The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Dec 30, 2024
Copy link

melvin-bot bot commented Dec 30, 2024

Payment Summary

Upwork Job

BugZero Checklist (@slafortune)

  • I have verified the correct assignees and roles are listed above and updated the neccesary manual offers
  • I have verified that there are no duplicate or incorrect contracts on Upwork for this job (https://www.upwork.com/ab/applicants/1853787863203385081/hired)
  • I have paid out the Upwork contracts or cancelled the ones that are incorrect
  • I have verified the payment summary above is correct

@ntdiary
Copy link
Contributor

ntdiary commented Dec 30, 2024

BugZero Checklist:

  • [Contributor] Classify the bug:
Bug classification

Source of bug:

  • 1a. Result of the original design (eg. a case wasn't considered)
  • 1b. Mistake during implementation
  • 1c. Backend bug
  • 1z. Other:

Where bug was reported:

  • 2a. Reported on production (eg. bug slipped through the normal regression and PR testing process on staging)
  • 2b. Reported on staging (eg. found during regression or PR testing)
  • 2d. Reported on a PR
  • 2z. Other:

Who reported the bug:

  • 3a. Expensify user
  • 3b. Expensify employee
  • 3c. Contributor
  • 3d. QA
  • 3z. Other:
  • [Contributor] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

    Link to comment: https://github.com/Expensify/App/pull/24607/files#r1899540203

  • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

    Link to discussion: N/A

  • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.
    No need, since we have added a unit test.

Regression Test Proposal Template
  • [BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.

    Link to issue:

Regression Test Proposal

Precondition:

Test:

Do we agree 👍 or 👎

@slafortune
Copy link
Contributor

@ntdiary - Role C+ - owed $250 via NewDot
Reviewer: @bernhardoj -Role Contributor - owed $250 via NewDot

@github-project-automation github-project-automation bot moved this from CRITICAL to Done in [#whatsnext] #quality Dec 30, 2024
@JmillsExpensify
Copy link

$250 approved for @ntdiary

@bernhardoj
Copy link
Contributor

Requested in ND.

@melvin-bot melvin-bot bot added Weekly KSv2 and removed Daily KSv2 labels Jan 6, 2025
@melvin-bot melvin-bot bot changed the title [HOLD for payment 2024-12-30] [$250] Accounting - Accounting tab loads infinitely when the workspace is created offline [HOLD for payment 2025-01-13] [HOLD for payment 2024-12-30] [$250] Accounting - Accounting tab loads infinitely when the workspace is created offline Jan 6, 2025
Copy link

melvin-bot bot commented Jan 6, 2025

The solution for this issue has been 🚀 deployed to production 🚀 in version 9.0.80-6 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2025-01-13. 🎊

For reference, here are some details about the assignees on this issue:

  • @ntdiary requires payment through NewDot Manual Requests
  • @bernhardoj requires payment through NewDot Manual Requests

Copy link

melvin-bot bot commented Jan 6, 2025

@ntdiary @slafortune @ntdiary The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

@JmillsExpensify
Copy link

$250 approved for @bernhardoj

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors Weekly KSv2
Projects
Status: Done
Development

No branches or pull requests

10 participants