Skip to content
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

Transaction "add"s are not multi-thread safe #295

Closed
rich-j opened this issue Dec 29, 2020 · 3 comments · Fixed by #1082
Closed

Transaction "add"s are not multi-thread safe #295

rich-j opened this issue Dec 29, 2020 · 3 comments · Fixed by #1082
Assignees
Labels
api: datastore Issues related to the googleapis/java-datastore API. type: docs Improvement to the documentation for an API.

Comments

@rich-j
Copy link

rich-j commented Dec 29, 2020

The add(entity) method in a Transaction object is not multi-thread safe. Other methods (e.g. put, delete) may also not be safe but we have traced a failure in our server specifically to add. Our server uses Scala Futures and so uses multiple threads of execution.

The particular scenario we tracked down was in our new user creation processing where we add 4 entities in a transaction. However there was a probability that one of the entities didn't get saved. It wasn't always the same entity kind that "disappeared". We traced this by adding debug logging after the 'add' calls that shows the adds successfully completing - but subsequent processing would find one of the entities missing. We did note that it always seemed to be just one entity missing and when an entity did go missing it seemed to be the first entity kind to be added (thread execution order was not consistent across invocations).

We added synchronize on each of our DataStore calls and haven't encountered this issue since. So at a minimum this issue can serve as a warning to others. Maybe a note could be added to the documentation. But we are also patiently waiting for issue #22 (async support) to be implemented and would hope that explicit synchronization to not be needed.

@product-auto-label product-auto-label bot added the api: datastore Issues related to the googleapis/java-datastore API. label Dec 29, 2020
@yoshi-automation yoshi-automation added triage me I really want to be triaged. 🚨 This issue needs some love. labels Dec 30, 2020
@dmahugh dmahugh added documentation Improvements or additions to documentation type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. and removed 🚨 This issue needs some love. triage me I really want to be triaged. labels Jan 11, 2021
@yoshi-automation yoshi-automation added 🚨 This issue needs some love. triage me I really want to be triaged. labels Jan 11, 2021
@dmahugh dmahugh added priority: p2 Moderately-important priority. Fix may not be included in next release. and removed triage me I really want to be triaged. labels Jan 12, 2021
@yoshi-automation yoshi-automation removed the 🚨 This issue needs some love. label Jan 12, 2021
@BenWhitehead BenWhitehead assigned crwilcox and unassigned BenWhitehead Feb 9, 2021
@crwilcox
Copy link

seems like we may want to at minimum document this. I am unsure if they are intended to be used in this way and if there aren't other issues or not. @kolea2 is multithread usage of a client a supported scenario for java clients?

@yoshi-automation yoshi-automation added 🚨 This issue needs some love. and removed 🚨 This issue needs some love. labels May 12, 2021
@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Jun 28, 2021
@crwilcox crwilcox removed their assignment Jul 27, 2021
@meredithslota meredithslota added type: docs Improvement to the documentation for an API. and removed documentation Improvements or additions to documentation type: bug Error or flaw in code with unintended results or allowing sub-optimal usage patterns. 🚨 This issue needs some love. labels Nov 2, 2021
@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Nov 3, 2021
@Neenu1995
Copy link
Contributor

@kolea2 ping

@Neenu1995 Neenu1995 removed priority: p2 Moderately-important priority. Fix may not be included in next release. 🚨 This issue needs some love. labels Mar 29, 2022
@jainsahab
Copy link
Contributor

I was able to replicate this using this code. A transaction getting modified multiple times through 4 threads. To successfully replicate, this needs to run in loop as it's nondeterministic behaviour.

Digging deeper into this, Transaction class maintains an internal state in terms of LinkedHashMap which gets updated on every Transaction#add call to record the mutations, I also want to highlight the fact that LinkedHashMap is not thread safe as per its documentation.

Note that this implementation is not synchronized. If multiple threads access a linked hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map:

There are higher chances that Transaction#put, Transaction#update and Transaction#delete are carrying this bug too, as they also uses same/similar data structures internally.

I feel this is by design as the early developers of the library wanted to access the Transaction object through only one thread to keep things simple. May be the intention was to never access the Transaction object from multiple threads.

For now, documenting the thread unsafe behaviour of Transaction, Batch and DatastoreBatchWriter classes to have users be aware of the existing behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: datastore Issues related to the googleapis/java-datastore API. type: docs Improvement to the documentation for an API.
Projects
None yet
9 participants