I am writing a Google App Engine Golang app. In the Datastore Transaction documentation, there is a note:
Note: If your app receives an error when submitting a transaction, it does not always mean that the transaction failed. You can receive ErrConcurrentTransaction in cases where transactions have been committed and eventually will be applied successfully. Whenever possible, make your Datastore transactions idempotent so that if you repeat a transaction, the end result will be the same.
Which makes me believe that if a transaction returns ErrConcurrentTransaction, it means the Datastore will eventually complete the transaction. However, reading up on RunInTransaction we can see a note:
If f returns nil, RunInTransaction attempts to commit the transaction, returning nil if it succeeds. If the commit fails due to a conflicting transaction, RunInTransaction retries f, each time with a new transaction context. It gives up and returns ErrConcurrentTransaction after three failed attempts.
It looks like ErrConcurrentTransaction is a fail state for the RunInTransaction function which means the Transaction will never commit.
So, which is it? If RunInTransaction returns ErrConcurrentTransaction, what should my code assume? Did the Transaction succeed, will it succeed in the future, or did it fail?