-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Update optimistic IDs in sequential queue #27996
Conversation
Opening this up for review while I work on screenshots. |
@s77rt fyi we're looking to get this one reviewed by early tomorrow. If you're able to review today, that would be amazing! If not, no worries, we'll assign an internal engineer tomorrow. |
This test is also broken on main atm |
Reviewer Checklist
Screenshots/VideosWebweb-ios.movMobile Web - ChromeMobile Web - SafariDesktopiOSios-web.movAndroid |
Test is still failing Screen.Recording.2023-09-28.at.2.38.05.AM-1.mov |
Thanks @s77rt – updated and ready for another review. |
@roryabraham Still looking broken Screen.Recording.2023-09-28.at.3.11.42.AM-1.mov |
Thanks – I was having difficulties with my dev environment but managed to get them sorted so now I'm seeing the same thing, and can see why this isn't working quite yet. Working on a fix now |
Exploring a new version of function replaceReportIDInNavigationStack(oldReportID, newReportID) {
const updatedState = deepReplaceKeysAndValues(navigationRef.getRootState(), oldReportID, newReportID);
navigationRef.resetRoot(updatedState);
} Edit: i think it's putting the navigator in the correct state, but it doesn't appear to be actually performing a navigation action. Going to keep noodling with this approach because I think it will end up being more robust. Edit 2: Got a bit further by using |
Asked for help in slack: https://expensify.slack.com/archives/C03UK30EA1Z/p1696205332369089 |
Going to split this up and move the navigation piece to a separate PR. We can address it in a separate issue. |
Created #28572 to address the navigation issues separately. |
I have tested on Web <- iOS and iOS <- Web. Let me know if you feel we need more tests here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel free to merge once the last review comment is resolved.
.slice(offset) | ||
.forEach((persistedRequest, index) => { | ||
const persistedRequestClone = _.clone(persistedRequest); | ||
persistedRequestClone.data = deepReplaceKeysAndValues(persistedRequest.data, oldReportID as string, preexistingReportID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea for future improvement: return a boolean if deepReplaceKeysAndValues
made any change to the clone, only use PersistedRequests.update
if something changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Onyx will also check this, but it incurs an extra object comparison so - maybe it can make some difference.
.forEach((persistedRequest, index) => { | ||
const persistedRequestClone = _.clone(persistedRequest); | ||
persistedRequestClone.data = deepReplaceKeysAndValues(persistedRequest.data, oldReportID as string, preexistingReportID); | ||
PersistedRequests.update(index + offset, persistedRequestClone); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Idea for future improvement: don't run PersistedRequests.update
in a loop, because it will result in n
calls to Onyx.set
instead of potentially just 1 call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably depends on the number of pending requests. I would keep this how it is but keep an eye on it. Alternatively test it by going offline and triggering a bunch of different action. Then go online and observe how quickly the UI updates (non-scientific approach).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another school of thought is that this is gonna be pretty edge case so maybe we can get away with what we've got here..
LMK if those sound like good improvements. I imagine they'll be better for performance, so maybe worth including in the V1... |
Calling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes LGTM!
return; | ||
} | ||
const oldReportID = request.data?.reportID; | ||
const offset = isFromSequentialQueue ? 1 : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would explain this with a code comment just a little bit. Something like:
If we are in the sequential queue then we want to ignore the first request in the queue as we know that it's values are correct. If we are not in the sequential queue then all of the requests queued to run after this are safe to modify.
.forEach((persistedRequest, index) => { | ||
const persistedRequestClone = _.clone(persistedRequest); | ||
persistedRequestClone.data = deepReplaceKeysAndValues(persistedRequest.data, oldReportID as string, preexistingReportID); | ||
PersistedRequests.update(index + offset, persistedRequestClone); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another school of thought is that this is gonna be pretty edge case so maybe we can get away with what we've got here..
I'm gonna proceed with merging this as there really aren't any major blocking comments from me. |
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by https://github.com/marcaaron in version: 1.3.77-0 🚀
|
🚀 Deployed to production by https://github.com/mountiny in version: 1.3.77-7 🚀
|
const responseOnyxData = response?.onyxData ?? []; | ||
responseOnyxData.forEach((onyxData) => { | ||
const key = onyxData.key; | ||
if (!key.startsWith(ONYXKEYS.COLLECTION.REPORT)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
key
could be undefined
which caused this issue - #28748 (comment)
Details
This PR adds a new middleware that will:
preexistingReportID
in an API responseFixed Issues
$ https://github.com/Expensify/Expensify/issues/319031
Tests / Offline Tests / QA Steps
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Web
Mobile Web - Chrome
Mobile Web - Safari
Desktop
iOS
iOS.mov
Android