Repository navigation
Transactions are commited in CommitRequest.NON_TRANSACTIONAL mode #903
Description
Activity
We managed to get the correct behaviour by plumbing through
Transaction#idthroughBatch#commit. The result is that the above test code works as intended: one thread doest the complete transaction, the other one gets:File "~/src/python/improbable/db/common/transaction.py", line 15, in commit response = self.connection.commit(self._dataset_id, self.mutation, self._id) File "~/virtualenv/python/local/lib/python2.7/site-packages/gcloud/datastore/connection.py", line 324, in commit datastore_pb.CommitResponse) File "~/virtualenv/python/local/lib/python2.7/site-packages/gcloud/datastore/connection.py", line 108, in _rpc data=request_pb.SerializeToString()) File "~/virtualenv/python/local/lib/python2.7/site-packages/gcloud/datastore/connection.py", line 85, in _request raise make_exception(headers, content, use_json=False) Conflict: 409 too much contention on these datastore entities. please try again.
I think the right solution here would be to catch it in the
Transaction#commitand rethrow it asConcurrentModificationException.- added a commit that references this issue
on Jun 1, 2015 What's the ETA on a version that supports it? :)
Also, this currently has a very clunky API, since there is no
ConcurrentModificationException. This means that the opportunistic concurrency model of Datastore is poorly exposed to the end user.@mwitkow-io I'm going to cut a release today (or tomorrow).
RE: "opportunistic concurrency model of Datastore is poorly exposed to the end user." we expect the error status codes and error messages from the Datastore API (the RPC service) to be useful. If there are issues where they aren't useful, we should take it up with the API folks.
The
ConcurrentModificationExceptionin App Engine corresponds to one of these RPC statuses.@mwitkow-io Also I'd love to chat about lack of thread-safety in
httplib2and how you address it. Want to hop on a video chat?We actually don't require use of it, but this is not at all clear from our docs (and may never be).
@mwitkow-io Also I'd love to chat about lack of thread-safety in
httplib2and how you address it. Want to hop on a video chat?We actually don't require use of it, but this is not at all clear from our docs (and may never be).
Sure thing, would be great to chat!
I'm in London though, so 8h diff to MTV. 5pm tomorrow BST? Please send a
call invite :-)On Thu, 4 Jun 2015 18:47 Danny Hermes notifications@github.com wrote:
@mwitkow-io https://github.com/mwitkow-io Also I'd love to chat about
lack of thread-safety in httplib2 and how you address it. Want to hop on
a video chat?We actually don't require use of it, but this is not at all clear from our
docs (and may never be).—
Reply to this email directly or view it on GitHub
#903 (comment)
.Invite sent for 4pm your time (if you're free). I assumed you use the email listed on your GitHub profile. If 4pm doesn't work I gave you edit privileges on the event.
Thanks, that works great :-)
On Thu, 4 Jun 2015 19:16 Danny Hermes notifications@github.com wrote:
Invite sent for 4pm your time (if you're free). I assumed you use the
email listed on your GitHub profile. If 4pm doesn't work I gave you edit
privileges on the event.—
Reply to this email directly or view it on GitHub
#903 (comment)
.- added 2 commits that reference this issue
on Aug 11, 2015 - addedtype: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.Error or flaw in code with unintended results or allowing sub-optimal usage patterns.api: datastoreIssues related to the Datastore API.Issues related to the Datastore API.
on Dec 31, 2015 - added a commit that references this issue
on Aug 21, 2025 - added a commit that references this issue
on Sep 16, 2025 - added 7 commits that reference this issue
on Nov 22, 2025 - added 4 commits that reference this issue
on Mar 2, 2026
We have just been bitten by this using the latest
0.5.0.We had the following piece of code, run in two different threads:
We've seen two copies of the
archived_entityfor the sameentity. We've managed to reproduce it with two threads performing this concurrently (running separate Connections each, because httplib2 is not thread safe).Having used Datastore's underlying technology before, I expected to get a
ConcurrentModificationExceptionon delete, and one of the threads throwing it, similar to what the Java API for AppEngine describes:https://cloud.google.com/appengine/docs/java/datastore/transactions#Java_Uses_for_transactions
However, both of them succeed creating two copies of
archived_entity, and there's noConcurrentModificationExceptionanywhere ingcloud-pythoncode.We've tracked down to the following:
Transaction#commitcalls theBatch#commithttps://github.com/GoogleCloudPlatform/gcloud-python/blob/master/gcloud/datastore/transaction.py#L177Batch#commitis unaware of theTransaction#id, callsConnection#commitwithout thetransaction_idparameter https://github.com/GoogleCloudPlatform/gcloud-python/blob/master/gcloud/datastore/batch.py#L214Connection#commitgetstransaction_id, and sets the REST request's mode todatastore_pb.CommitRequest.NON_TRANSACTIONALin https://github.com/GoogleCloudPlatform/gcloud-python/blob/master/gcloud/datastore/connection.py#L321Impact: This means that all transactions made through
python-gcloudare non-transactional. Please treat it as a P0 bug.