-
Notifications
You must be signed in to change notification settings - Fork 331
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
fix(core): run getSources
promises in a concurrent-safe way
#347
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit bf6a07f:
|
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 great! I like how clear you made (and tested) this. I'll let the team figure out whether it's mergeable.
Promise.all( | ||
sources.filter(Boolean).map((source) => { | ||
return Promise.resolve(normalizeSource<TItem>(source)); | ||
return runConcurrentSafePromiseForSource( |
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.
If I understand correctly, don't we need to have a difference instance of createConcurrentSafePromise
per source here? For each source, we want to keep the last result, not the last result of all the sources.
Let me know if I'm misunderstanding!
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.
Yeah exactly. This case is complex because of the dynamic nature of sources. This PR doesn't cover this case anymore.
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 need to look even more in detail to the core usage of this, but the util lgtm
packages/autocomplete-core/src/__tests__/createConcurrentSafePromise.test.ts
Outdated
Show resolved
Hide resolved
packages/autocomplete-core/src/__tests__/createConcurrentSafePromise.test.ts
Outdated
Show resolved
Hide resolved
The last commits make sure that the concurrency fix works at the It's however not fixed for |
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 good to me. The concurrency test is super clear.
// The last item must be the one corresponding to the last query. | ||
expect(itemsHistory[itemsHistory.length - 1]).toEqual( | ||
expect.objectContaining({ label: 'abc' }) | ||
); |
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 add a test to check for the presence of { label: 'a' }
as well as the first item?
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 a snapshot of all the labels could make sense?
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.
A snapshot will be fragile because there's no certainty of how many times onStateChange
is called. It's called whenever a setter is called (e.g. setIsOpen
, etc.), and a setter can be called user-land. It means that if we refactor something, this test will become a false negative.
I'll check for the presence of a
though.
getSources
promises in a concurrent-safe way
Description
This fixes an issue where promises coming from
getSources
orgetSuggestions
resolve out of call order.In the scenario above, although R2 is the result resolving last, we shouldn't update the results because R3 is more fresh (although it resolved earlier).
Related
cc @redox @Shipow