0

I'm using the gcloud-java-datastore API (v0.2.3) to work with Google Cloud Datastore. Trying to use transactions to prevent simultaneous updates to a root entity I just can't seem to get the transactions work the way I think they should. Perhaps my understanding is not right, but could definitely use some help.

Below is a test case where two threads load the same entity in their own transactions, update the entity and commit. I was hoping that the commit from one thread would succeed while the other fails. But, every time, both threads are succeeding by overwriting the first thread's change. Is this expected? Based on the official documentation at https://cloud.google.com/datastore/docs/concepts/transactions, I interpreted that only one transaction would be successful.

@Test
public void test2() {

    Datastore datastore = DatastoreOptions.defaultInstance().service();
    KeyFactory keyFactory = datastore.newKeyFactory();
    com.google.cloud.datastore.Key key = keyFactory.kind("Account").newKey(5642398931615744L);
    Runnable r = new Runnable() {
        @Override
        public void run() {
            Transaction transaction = datastore.newTransaction();
            try {
                Entity entity = transaction.get(key);
                System.out.println(entity);
                Entity modifiedEntity = Entity.builder(entity).set("name", Thread.currentThread().getName())
                        .build();
                transaction.put(modifiedEntity);
                transaction.commit();
                System.out.println(String.format("%1s: Commit successful", Thread.currentThread().getName()));
            } catch (Exception exp) {
                exp.printStackTrace();
            } finally {
                if (transaction.active()) {
                    transaction.rollback();
                }
            }
        }
    };

    Thread t1 = new Thread(r);
    Thread t2 = new Thread(r);
    t1.start();
    t2.start();
    try {
        t1.join();
        t2.join();
    } catch (InterruptedException exp) {
        exp.printStackTrace();
    }

}

When I run this test case, I see the below output on the console:

Thread-2: Commit successful
Thread-1: Commit successful

Thanks.

Sai Pullabhotla
  • 2,207
  • 17
  • 17
  • How do you know there are not executing sequentially? I don't see any output that tells you one thread is committing a transaction while the other one has it open. – Dan McGrath Jun 22 '16 at 12:10
  • Well, the very first test I did was without any Threads. I had a breakpoint on transaction.commit line. While the code is on the breakpoint, I went into Google Cloud Console and updated the same entity. Let my program resume and was expecting that my commit would fail. However, it just succeeded. Is that expected? I will add some console logs to this test program and confirm the sequence. – Sai Pullabhotla Jun 22 '16 at 13:36
  • Dan's right. It just happened that the timing of threads made it look like it was not working properly. I ran more tests now and I can see that some commits are failing with the error - too much contention on these datastore entities. please try again. – Sai Pullabhotla Jun 23 '16 at 03:23

0 Answers0