Skip to content
This repository was archived by the owner on May 6, 2026. It is now read-only.

fix: detect cache write failure for MemcacheCache#665

Merged
chrisrossi merged 6 commits into
googleapis:masterfrom
chrisrossi:fix-656
Jun 7, 2021
Merged

fix: detect cache write failure for MemcacheCache#665
chrisrossi merged 6 commits into
googleapis:masterfrom
chrisrossi:fix-656

Conversation

@chrisrossi
Copy link
Copy Markdown
Contributor

Fixes #656

@chrisrossi chrisrossi requested a review from andrewsg as a code owner May 28, 2021 19:37
@chrisrossi chrisrossi requested review from a team May 28, 2021 19:37
@google-cla google-cla Bot added the cla: yes This human has signed the Contributor License Agreement. label May 28, 2021
@product-auto-label product-auto-label Bot added the api: datastore Issues related to the googleapis/python-ndb API. label May 28, 2021
Copy link
Copy Markdown

@justinkwaugh justinkwaugh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look good to me, apart from the typo

Comment thread google/cloud/ndb/_cache.py Outdated
If there is an exception for the cache call, distribute that to waiting
futures, otherwise examine the result of the cache call. If the result is
:data:`None`, simply set the result to :data:`None` for all waiting futures.
Otherwise, if the result is a `dict`, use that to propogate results for
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: propogate->propagate

Comment thread google/cloud/ndb/global_cache.py
@justinkwaugh
Copy link
Copy Markdown

justinkwaugh commented Jun 1, 2021

@chrisrossi I think I found another issue

if you change the futures property of _GlobalCacheSetBatch to a dict, then if there are duplicates (i.e. a set for the same key gets batched more than once) then you will end up with an unfinished future, as it will never get set in the done_callback. Probably that needs to be a list of tuples of (key, future) instead

Comment thread google/cloud/ndb/_cache.py
@chrisrossi
Copy link
Copy Markdown
Contributor Author

@chrisrossi I think I found another issue

if you change the futures property of _GlobalCacheSetBatch to a dict, then if there are duplicates (i.e. a set for the same key gets batched more than once) then you will end up with an unfinished future, as it will never get set in the done_callback. Probably that needs to be a list of tuples of (key, future) instead

Yeah, that's a good point. I'm trying to think through why the same key would get set twice and what the behavior should be if the values differ. Does the last one "win"? Do we raise an error? When/if not raising an error, we can probably hand the same future back to each caller. So it's maybe less that we need to change data structure, and more we need to add code to handle duplicates in add.

@justinkwaugh
Copy link
Copy Markdown

justinkwaugh commented Jun 1, 2021

@chrisrossi I think I found another issue
if you change the futures property of _GlobalCacheSetBatch to a dict, then if there are duplicates (i.e. a set for the same key gets batched more than once) then you will end up with an unfinished future, as it will never get set in the done_callback. Probably that needs to be a list of tuples of (key, future) instead

Yeah, that's a good point. I'm trying to think through why the same key would get set twice and what the behavior should be if the values differ. Does the last one "win"? Do we raise an error? When/if not raising an error, we can probably hand the same future back to each caller. So it's maybe less that we need to change data structure, and more we need to add code to handle duplicates in add.

Sure, that is true. No problem with returning the same future to multiple callers, the problem is in creating new futures for existing keys. Regarding who wins etc, I don't have a strong sense for the lifecycle of a batch. The main problem would be if a set of a model and a set of a lock value were attempted in the same batch, but I'm hoping that can't happen. If not, then multiple callers trying to set for the same key should be satisfied by a single success or failure. If it can happen, then there are definitely bigger problems. Now that I think about it though, I'm remembering that read threads use cas to set model values so they would not be a problem. Their setting of the lock value is problematic though, and I think should be changed per #651 to an add operation for read threads.

The reason I suggested the tuple is because for my own fix for #651, which involves adding a memcache add operation for read thread locking. That one does care about having only one winner for duplicates, with the rest returning false. For those I have a list of tuples of the form (key, future, is_duplicate) and any that have is_duplicate == True get assigned a result of False in done_callback for that batch operation.

@chrisrossi chrisrossi added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jun 7, 2021
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jun 7, 2021
@chrisrossi chrisrossi merged commit 5d7f163 into googleapis:master Jun 7, 2021
@chrisrossi chrisrossi deleted the fix-656 branch June 7, 2021 17:24
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

api: datastore Issues related to the googleapis/python-ndb API. cla: yes This human has signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloud NDB - suppressed failures to set and delete in memcache cause cache inconsistency

4 participants