Understanding what operation types will cause a failed transaction in GAE datastore - google-cloud-datastore

After reading the documentation, there is one thing that is not completely clear to me, I am hoping someone can clarify.
Obviously if you have two read-then-write transactions that occur concurrently, one of them will fail. However, if you have one read-then-write transaction in progress, and then another read occurs that was not part of a transaction, will that other non transactional read cancel the transaction, i.e. A transaction to read-then-write on a payment/transaction record should not be cancelled by the non transactional "Get all payment data" report. Is that correct?

Yes, that's correct. Non-transactional reads and read-only transactions do not contend with read-then-write transactions.

Related

Is the order of firestore snapshot events guaranteed?

If I have have multiple clients writing to the same document in a transaction, is every transaction triggering the snapshot listener? If yes is it guarenteed that the listener are triggered in the order the transactions are commited? I would expect yes, but am a bit unsure because:
If a document write is performed the local Snapshot gets notified immediately cause of latency concerns. Does this "local" notification only get triggered if the transaction is guranteed to be successfull? Otherwise order would not be guaranteed right?
There is a onSnapshotsInSync method. Out of the documentation I don't really get if this is related to my question, but the method irritates me a bit. When should this method be considered, is my question somehow related to it?
Thanks
I would assume that a listener is only triggered, when the transaction is actually completed. And after the transaction is finished, I'd expect all changes to be committed to the database at once.
onSnapshotInSync only ensures that multiple listeners are in sync with each other.

Firestore (Datastore mode) - how many writes are billed if a transaction is rolled-back?

Can anyone shed some light on how billing works in Firestore (Datastore mode) when a transaction is rolled back? How many writes is one going to be billed if one batch deletes 500 entities (DeleteMulti) then rolls back the transaction?
From a billing/quota perspective, operations are tracked exactly the same in a transaction regardless of whether the transaction succeeds and is committed, or rolled back.
This means that if a you attempts to create 5 items, then delete 2 existing ones, then create one more, they will be charged for 6 write operations and 2 deletes. This will be the case if the whole transaction succeeds, or if the transaction fails on any of the individual operations, even if those operations are never committed and do not appear in the data after the transaction has been rolled back.
So answering your question, you would be billed for 500 deletes, regardless of whether the transaction succeeds or is rolled back.

Cloud Datastore transaction terminated without explicit rollback defined

From following document: https://cloud.google.com/datastore/docs/concepts/transactions
What would happen if transaction fails with no explicit rollback defined? For example, if we're performing put() operation on value arguments.
The document states that transaction should be idempotent, what does this mean with respect to put() operation? It is not clear how idempotency is applied in this context.
How do we detect failure if failure from commit is not reliable according to the documentation?
We are seeing some symptoms where put() against value argument is sometimes partially saving the data. Note we do not have explicit rollback defined.
As you may already know, Datastore transactions are guaranteed to be atomic, which means that it applies the all-or-nothing principle; either all operations succeed or they all fail. This ensures that the data in your database remains consistent over time.
Now, regardless whether you execute put or any other operation in your transaction, your implementation of the code should always ensure that your transaction has either successfully commited or rolled back. This means that if you aren't fully sure whether the commit succeeded, you should explicitly issue a rollback.
However, there may be some exceptions where a commit might fail, and this doesn't necessarily mean that no data was written to your database. The documentation even points out that "you can receive errors in cases where transactions have been committed."
The simple way to detect transaction failures would be to add a try/catch block in your code for when an Exception (failed transactional operation) or DatastoreException (errors related to Datastore - failed commit) are thrown. I believe that you may already have an answer in this Stackoverflow post about this particular question.
A good practice is to make your transactions idempotent whenever possible. In other words, if you're executing a transaction that includes a write operation put() to your database, if this operation were to fail and needed to be retried, the end result should ideally remain the same.
A real world example can be - you're trying to transfer some money to your friend; the transaction consists of withdrawing 20 USD from your bank account and depositing this same amount into your friend's bank account. If the transaction were to fail and had to be retried, the transaction should still operate with the same amount of money (20 USD) as the final result.
Keep in mind that the Datastore API doesn't retry transactions by default, but you can add your own retry logic to your code, as per the documentation.
In summary, if a transaction is interrupted and your logic doesn't handle the failure accordingly, you may eventually see inconsistencies in the data of your database.

How to rollback DB transaction after http connection is lost

Recently at a interview the interviewer asked me a question, below is the question -
Suppose a request is sent to a servlet and the servlet performs several DB transactions(first update and commit, then read and update and again commit) which takes around 3-4 minutes, during that period the user press the cancel button and the connection is lost. How would you rollback the entire transaction.
My answer was - Since Servlet throws IOException we can handle the exception and rollback the transaction.
But again he questioned me what about the DB commits which are already done, how would you rollback that.
I was blank and replied that i never came across that situation. But i would really like to know what could be done in such a situation.
Thanks.
But again he questioned me what about the DB commits which are already
done, how would you rollback that.
I think it was not a servlet related questions.If the transaction was committed in the database you can not rollback it. A database transaction has several properties known as ACID (Atomicity, Consistency, Isolation, Durability). The one that applies in this case is Durability:
"Durability is the ACID property which guarantees that transactions
that have committed will survive permanently"

Recovering from Datastore commit exceptions for transactions that are not idempotent

The Google App Engine documentation at https://developers.google.com/appengine/docs/java/datastore/transactions says this:
Note: In extremely rare cases, the transaction is fully committed even
if a transaction returns a timeout or internal error exception. For
this reason, it's best to make transactions idempotent whenever
possible.
What is the proper way to recover from a commit exception if the transaction is not idempotent?
I think what you do is show the end user an error with a link they can use to view the state of their world. Then the end user can decide whether to resubmit. E.g. if they post a comment to a blog and the post somehow reports an error, they can re-load the blog page and see if their comment is there; if they see it's not, they can (hopefully) recover it from their browser history and resubmit.

Resources