I am trying to catch a concurrent modification exception in Firestore in Datastore mode with Objectify. I created a method and ran it 50 times in 1 second to try and catch the exception. I found that I can only catch the exception if I use a transaction.
Is there a way to catch the CME without a transaction?
This does not catch the exception when ran 50 times in 1 second (even though I can see in the logs the entity is not always updated due to the 1/sec write limit):
try {
Entity entity = ofy().load().type(Entity.class)
.filter("username", "username1")
.first()
.now();
entity.setName("username2")
ofy().save().entity(newEntity).now();
} catch (com.google.cloud.datastore.DatastoreException datastoreException) {
// Never catches anything
} catch (Exception e) {
// Never catches anything
}
This catches the exception when ran 50 times in 1 second:
try {
ofy().transact(new VoidWork() {
public void vrun() {
Entity entity = ofy().load().type(Entity.class)
.filter("username", "username1")
.first()
.now();
entity.setName("username2")
ofy().save().entity(newEntity).now();
}
}
});
} catch (com.google.cloud.datastore.DatastoreException datastoreException) {
// Catches this error: Aborted due to cross-transaction contention. This occurs when multiple transactions attempt to access the same data, requiring Firestore to abort at least one in order to enforce serializability.
} catch (Exception e) {
}
Without a transaction the write is concerned a blind write. A blind write writes the content of the write even if another write has happened between your read & your write.
You should not expect a concurrent modification exception without a transaction.