-
Notifications
You must be signed in to change notification settings - Fork 89
Trigger callbacks with merged cache data when initializing with default key states #126
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
Conversation
|
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
| const merged = lodashMerge(asObject, defaultKeyStates); | ||
| cache.merge(merged); | ||
| _.each(merged, (val, key) => keyChanged(key, val)); | ||
| _.each(merged, (val, key) => { | ||
| const currentValue = cache.getValue(key); | ||
| keyChanged(key, currentValue); | ||
| }); |
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.
question: It looks like merged is going to end up as the combined result of any existing values for these keys + the defaultKeyStates object? I might just be missing it, but why would it be necessary to ask the cache for this data if merged is the combined result already?
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.
In the case that I'm trying to fix, merged contains only the defaultKeyStates as the Storage is empty. However, the cache is not empty. So if the defaultKeyStates are not merged with the value in the cache then keyChanged is called without up to date values.
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.
However, the cache is not empty.
thought: If we are signing out then both the cache and storage should be empty. Am I missing something?
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.
Lines 711 to 721 in 2d42566
| function clear() { | |
| return getAllKeys() | |
| .then((keys) => { | |
| _.each(keys, (key) => { | |
| keyChanged(key, null); | |
| cache.set(key, null); | |
| }); | |
| }) | |
| .then(Storage.clear) | |
| .then(initializeWithDefaultKeyStates); | |
| } |
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.
It is also surprising to me that the cache is not empty but the storage is. My guess is that Storage.clear takes a while to complete, and during that time the new user is logged in and lots of values are set in Onyx.
When are values written from the cache to storage? Can the storage be out of date temporarily? I will try to look through the code and answer my own questions, but if you can give me a quick explanation / point me in the right direction that would be great.
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.
When are values written from the cache to storage?
I don't think values from the cache are ever written to storage. We should be setting values in the cache and then writing them to storage (async) at the same time.
Can the storage be out of date temporarily?
I'm not sure if I have enough context to explain a situation where the storage could be out of date. But it certainly seems possible.
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 have verified that signing in the new user occurs before Onyx.clear() finishes. Waiting to sign the user in until the storage clears could work, and I guess we could do that, but wouldn't it be better to not wait for that? I also think that this solution makes more sense. Please see the issue for more context and an example if you haven't seen that already.
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.
Waiting to sign the user in until the storage clears could work, and I guess we could do that, but wouldn't it be better to not wait for that?
clarification: By better do we mean faster? Or something else.
thought: Signing out a user and signing in a new one seems like a rare event. So maybe performance is not a concern (assuming that is the concern).
I also think that this solution makes more sense.
I do see how it solves the immediate issue. But just want to make sure we're picking the best solution. I'm not sure if allowing data to be set while we are in the process of re-initializing storage makes sense. I think my expectation is that we'd defer those updates until the app has finished one "clean" cycle.
Mind if we go back to this question?
Should we completely sign the previous user out before starting a new sign in process?
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.
clarification: By better do we mean faster? Or something else.
Yes. I think you're right that it probably wouldn't slow things down too much and that this flow is rare.
I'm not sure if allowing data to be set while we are in the process of re-initializing storage makes sense.
It would be up to the user of Onyx to make sure that no data is set while re-initializing storage right? That seems slightly less robust. If any initialKey is set while re-initializing storage then it could send an out of date value to its subscribers. How do you make your whole app wait while Onyx clears and re-initializes?
Should we completely sign the previous user out before starting a new sign in process?
Probably, yes. I will work on a PR to do that. If that works and we agree that it's a better solution, then I'm happy to do that instead.
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.
It would be up to the user of Onyx to make sure that no data is set while re-initializing storage right?
Yep!
That seems slightly less robust. If any initialKey is set while re-initializing storage then it could send an out of date value to its subscribers. How do you make your whole app wait while Onyx clears and re-initializes?
Onyx.clear() returns a promise so that would be my first instinct. But maybe there's a different solution. Might be something we can get some more opinions on too? I'm not 100% what the best answer would be, but just wanted to think about it for a second. Thanks for hearing me out!
|
I'm going to convert this to a draft while I add a unit test for updating a key with the initialKeyStates after Onyx.clear(). |
|
I couldn't figure out how to add a test where I read a value when the cache is out of date. |
Can you describe the conditions that would lead the storage to go out of date? |
Does that make sense? Am I missing something? |
|
Closing in favor of #129. |
cc @marcaaron
Details
Merge user provided default key value pairs with not only the data in storage, but also the data in the cache. See the issue for more context.
Related Issues
#125
Automated Tests
Linked PRs
Expensify/App#8676