-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Only fetch report history we need on reconnect + fix sign out issue #2616
Conversation
add way to extract collection key use array in fetchOrCreateChatReport fix return types Add Timers namespace so there is some way to prevent delayed requests on sign out undo changes revert login form change undo sleep timer change again
efc7f00
to
99f025d
Compare
@@ -61,7 +61,7 @@ function getDisplayName(login, personalDetail) { | |||
// If we have a number like [email protected] then let's remove @expensify.sms | |||
// so that the option looks cleaner in our UI. | |||
const userLogin = Str.removeSMSDomain(login); | |||
const userDetails = personalDetail || personalDetails[login]; | |||
const userDetails = personalDetail || lodashGet(personalDetails, login); |
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.
minor fix here to get rid of a propTypes
warning
// If we are already on the signin page, don't redirect | ||
if (currentURL.indexOf('signin') !== -1) { | ||
return; | ||
} |
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.
This change here no longer made sense since there is no signin
route
@@ -26,7 +25,6 @@ Onyx.connect({ | |||
* @param {String} [errorMessage] error message to be displayed on the sign in page | |||
*/ | |||
function redirectToSignIn(errorMessage) { | |||
NetworkConnection.stopListeningForReconnect(); |
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.
There is a duplicate call here and this should only need to trigger once when the AuthScreens
unmount
@tgolen I'd like to get your review, but want to give @jasperhuangg and @Beamanator a shot at reviewing first if that's OK. I'm open to feedback on any alternative ways to tackle these problems if we can identify some together. Thanks! |
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.
Tested and it works great, plus the URL issue was fixed! Thanks for the opportunity to review, it was very insightful. Feel free to add #2620 to the OP as another issue that's fixed!
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.
Looks pretty slick! Nice work! Tests also worked out well 💪
Added only a few NAB comments
Updated |
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'm a bit confused how the two datasets play with each other, but I like the general idea!
src/libs/actions/Report.js
Outdated
* to fetch from the server. maxSequenceNumber is retrieved when getting the reportList whereas these keep track of | ||
* the actual reportActions saved in Onyx. | ||
*/ | ||
const maxReportActionsSequenceNumbers = {}; |
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.
This is definitely confusing with maxSequenceNumber
now and unfortunately, the comment doesn't clear it up enough. I think they are both listening to different keys, but I can't figure out why there would be a difference between the two, why that difference is OK, and what that difference has to do with history being available to download from the server. I think the comment can do a better job of explaining why each map is different, as well as explaining why they can get out of sync, why it's OK that they get out of sync, and what is useful about that information as it pertains to downloading new content from the server. If you want me to take a stab at it, let me know, but I think I need to make sure I get my head wrapped around this logic first before I can be of any more help.
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.
Lemme try a bit harder here. It sounds like you're getting it, but the comment doesn't explain some things that make sense to me because I wrote this code.
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 part of the confusing is just a byproduct of having two sources to tell us about the most recent sequence number.
There might be a more holistic way to solve this. But for now, I wonder if an acceptable solution would be to:
- Add a very verbose comment about what the difference between these two maps are and some background on where things are stored and why.
- Take a page out of React's book and rename this map to something like
UNSAFE_reportActionsMaxSequenceNumbers
so that people think twice before using it.
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.
Just went for this! I think it works and resolves a concern I have about people getting confused about which map to refer to in the future.
src/libs/actions/Report.js
Outdated
|
||
// The most recent reportAction we have stored is less than the maxSequenceNumber for a report. | ||
// This works because the reportMaxSequenceNumber is based on the reportActionList whereas the | ||
// maxReportActionsSequenceNumbers can only be populated by adding reportActions to Onyx. |
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.
Maybe this is a more helpful context to put up by the Onyx connections.
src/libs/actions/Report.js
Outdated
// We are waiting 8 seconds since this provides a good time window to allow the UI to finish loading before | ||
// bogging it down with more requests and operations. | ||
}, shouldDelayActionsFetch ? 8000 : 0); | ||
// Register the timer so we can clean it up on sign out if it has not yet fired. |
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.
How is it even possible that this timer would never fire?
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.
Will add a comment but the case is just logging in then logging out before the timer goes.
Ok so after chatting with @tgolen for a while about this I eventually landed on... Moving the The intent here is that eventually other "reportActions" related actions can be moved into that file, but it would take too long to unwind right now. The biggest concern I have with adding this new map is that it's confusing and people should find very few reasons to use it. To encourage this, I made a helper method that is exported by |
Updated |
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 love the new structure and the recommendation not to use the new function you created (if possible)!
I have only a few suggestions to make some comments clearer, let me know if you disagree with any of them 👍
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 like the new changes. It makes the situation much more clear what's happening. Thank you!
src/libs/actions/Report.js
Outdated
|
||
// Register the timer so we can clean it up if the user logs out after logging in. If we don't cancel the | ||
// timer we'll make unnecessary API requests from the sign in page. | ||
Timers.register(timerID); |
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.
Just a small thing, but the other code that users Timers.register()
is passing an anonymous function, and I actually like that pattern better because it forces me to know to use Timers.register()
. With this down here below the definition of the setTimeout
I think it is easy to miss, so I vote for the consistency of the other pattern.
Updated |
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.
Noice 💪 #LGTM
✋ 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 in version: 1.0.36-1🚀
|
🚀 Deployed to production in version: 1.0.39-5🚀
|
function clearAll() { | ||
_.each(timers, (timer) => { | ||
// We don't know whether it's a setTimeout or a setInterval, but it doesn't really matter. If the id doesn't | ||
// exist nothing bad happens. | ||
clearTimeout(timer); | ||
clearInterval(timer); | ||
}); | ||
} |
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.
const timers = [];
is never emptied
clearAll
will be foreach-ing already cleared timers
Maybe it can be refactored to something like
const timers = {};
function clearSingle(id) {
clearTimeout(id);
clearInterval(id);
delete timers[id];
}
function clearAll() {
_.each(timers, clearSingle);
}
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.
That's a good point. But there is no danger in clearing already cleared timers so this might never be a problem.
.then((createdReportID) => { | ||
reportIDs = [createdReportID]; | ||
}); | ||
return fetchOrCreateChatReport([currentUserEmail, '[email protected]'], false); |
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.
Instead of modifying fetchOrCreateChatReport
you could just return the array like:
return fetchOrCreateChatReport([currentUserEmail, '[email protected]'], false)
.then(reportId => [reportId]);
IMO it's better than having to justify something fishy with a comment
// We are returning an array with the reportID here since fetchAllReports calls this method or
// fetchChatReportsByIDs which returns an array of reportIDs.
return [data.reportID];
- this just discloses a coupling to the
fetchAllReports
usage
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.
Thanks for your notes here. I see no major problem with doing it either way.
Details
This PR is a little all over the place since I cleaned a few things up as I went, but mostly addresses two major issues:
Timers
namespace. We register a timer id and then just clear them all on sign out.Other minor issues also being cleaned up here:
NetworkConnection.stopListeningForReconnect()
was being called twice for no clear reason on sign outsignin
route when signing out but that route was recently removedFixed Issues
Fixes #2615
Tests
Report_GetHistory
and only see the one for the report with new contenthistory
array only has as many comments as were added on the previous report.QA Steps
Tested On
Screenshots
Web
Mobile Web
Desktop
iOS
Android