/** * Inserts a new {@link PortabilityJob} keyed by {@code jobId} in Datastore. * * <p>To update an existing {@link PortabilityJob} instead, use {@link JobStore#update}. * * @throws IOException if a job already exists for {@code jobId}, or if there was a different * problem inserting the job. */ @Override public void createJob(UUID jobId, PortabilityJob job) throws IOException { Preconditions.checkNotNull(jobId); Transaction transaction = datastore.newTransaction(); Entity shouldNotExist = transaction.get(getKey(jobId)); if (shouldNotExist != null) { transaction.rollback(); throw new IOException( "Record already exists for jobID: " + jobId + ". Record: " + shouldNotExist); } Entity entity = createEntity(jobId, job.toMap()); try { transaction.put(entity); } catch (DatastoreException e) { transaction.rollback(); throw new IOException( "Could not create initial record for jobID: " + jobId + ". Record: " + entity, e); } transaction.commit(); }
@Override public <T extends DataModel> void create(UUID jobId, String key, T model) throws IOException { Preconditions.checkNotNull(jobId); Transaction transaction = datastore.newTransaction(); Key fullKey = getDataKey(jobId, key); Entity shouldNotExist = transaction.get(fullKey); if (shouldNotExist != null) { transaction.rollback(); throw new IOException( "Record already exists for key: " + fullKey.getName() + ". Record: " + shouldNotExist); } String serialized = objectMapper.writeValueAsString(model); Entity entity = Entity.newBuilder(fullKey) .set(CREATED_FIELD, Timestamp.now()) .set(model.getClass().getName(), serialized) .build(); try { transaction.put(entity); } catch (DatastoreException e) { throw new IOException( "Could not create initial record for jobID: " + jobId + ". Record: " + entity, e); } transaction.commit(); }
@Override public <T extends DataModel> void update(UUID jobId, String key, T model) { Transaction transaction = datastore.newTransaction(); Key entityKey = getDataKey(jobId, key); try { Entity previousEntity = transaction.get(entityKey); if (previousEntity == null) { throw new IOException("Could not find record for data key: " + entityKey.getName()); } String serialized = objectMapper.writeValueAsString(model); Entity entity = Entity.newBuilder(entityKey) .set(CREATED_FIELD, Timestamp.now()) .set(model.getClass().getName(), serialized) .build(); transaction.put(entity); transaction.commit(); } catch (IOException t) { transaction.rollback(); throw new RuntimeException("Failed atomic update of key: " + key, t); } }
} finally { if (tx.isActive()) { tx.rollback();
@Override public T call() throws DatastoreException { transaction = datastore.newTransaction(options); try { T value = callable.run(transaction); transaction.commit(); return value; } catch (Exception ex) { transaction.rollback(); throw DatastoreException.propagateUserException(ex); } finally { if (transaction.isActive()) { transaction.rollback(); } if (options != null && options.getModeCase().equals(TransactionOptions.ModeCase.READ_WRITE)) { setPrevTransactionId(transaction.getTransactionId()); } } } }
transaction.commit(); } catch (Throwable t) { transaction.rollback(); throw new IOException("Failed atomic update of jobId: " + jobId, t);
@Override public void rollback() { this.raw.rollback(); } }
@Override public void rollback() { transaction.rollback(); } }
/** Example of rolling back a transaction. */ // [TARGET rollback()] public Key rollback() { Datastore datastore = transaction.getDatastore(); // [START rollback] // create an entity KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind"); Key key = datastore.allocateId(keyFactory.newKey()); Entity entity = Entity.newBuilder(key).set("description", "rollback()").build(); // add the entity and rollback transaction.put(entity); transaction.rollback(); // calling transaction.commit() now would fail // [END rollback] return key; }
/** Example of verifying if a transaction is active. */ // [TARGET active()] public Key active() { Datastore datastore = transaction.getDatastore(); // [START active] // create an entity KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind"); Key key = datastore.allocateId(keyFactory.newKey()); Entity entity = Entity.newBuilder(key).set("description", "active()").build(); // calling transaction.active() now would return true try { // add the entity and commit transaction.put(entity); transaction.commit(); } finally { // if committing succeeded // then transaction.isActive() will be false if (transaction.isActive()) { // otherwise it's true and we need to rollback transaction.rollback(); } } // [END active] return key; }
/** Example of verifying if a transaction is active. */ // [TARGET isActive()] public Key isActive() { Datastore datastore = transaction.getDatastore(); // [START isActive] // create an entity KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind"); Key key = datastore.allocateId(keyFactory.newKey()); Entity entity = Entity.newBuilder(key).set("description", "active()").build(); // calling transaction.active() now would return true try { // add the entity and commit transaction.put(entity); transaction.commit(); } finally { // if committing succeeded // then transaction.active() will be false if (transaction.isActive()) { // otherwise it's true and we need to rollback transaction.rollback(); } } // [END isActive] return key; } }
@Test public void testNewTransactionRollback() { Transaction transaction = datastore.newTransaction(); transaction.add(ENTITY3); Entity entity2 = Entity.newBuilder(ENTITY2) .clear() .setNull("bla") .set("list3", StringValue.of("bla"), StringValue.newBuilder("bla").build()) .build(); transaction.update(entity2); transaction.delete(KEY1); transaction.rollback(); transaction.rollback(); // should be safe to repeat rollback calls try { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException ex) { // expected to fail } verifyNotUsable(transaction); List<Entity> list = datastore.fetch(KEY1, KEY2, KEY3); assertEquals(ENTITY1, list.get(0)); assertEquals(ENTITY2, list.get(1)); assertNull(list.get(2)); assertEquals(3, list.size()); }
@Test public void testNewTransactionRollback() { Transaction transaction = DATASTORE.newTransaction(); transaction.add(ENTITY3); Entity entity2 = Entity.newBuilder(ENTITY2) .clear() .setNull("bla") .set("list3", StringValue.of("bla"), StringValue.newBuilder("bla").build()) .build(); transaction.update(entity2); transaction.delete(KEY1); transaction.rollback(); transaction.rollback(); // should be safe to repeat rollback calls try { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { assertEquals("FAILED_PRECONDITION", expected.getReason()); } List<Entity> list = DATASTORE.fetch(KEY1, KEY2, KEY3); assertEquals(ENTITY1, list.get(0)); assertEquals(ENTITY2, list.get(1)); assertNull(list.get(2)); assertEquals(3, list.size()); }
@Test public void testNewTransactionCommit() { Transaction transaction = datastore.newTransaction(); transaction.add(ENTITY3); Entity entity2 = Entity.newBuilder(ENTITY2).clear().setNull("bla").build(); transaction.update(entity2); transaction.delete(KEY1); transaction.commit(); List<Entity> list = datastore.fetch(KEY1, KEY2, KEY3); assertNull(list.get(0)); assertEquals(entity2, list.get(1)); assertEquals(ENTITY3, list.get(2)); assertEquals(3, list.size()); try { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException ex) { // expected to fail } try { transaction.rollback(); fail("Expecting a failure"); } catch (DatastoreException ex) { // expected to fail } verifyNotUsable(transaction); }
@Test public void testNewTransactionCommit() { Transaction transaction = DATASTORE.newTransaction(); transaction.add(ENTITY3); Entity entity2 = Entity.newBuilder(ENTITY2).clear().setNull("bla").build(); transaction.update(entity2); transaction.delete(KEY1); transaction.commit(); assertFalse(transaction.isActive()); List<Entity> list = DATASTORE.fetch(KEY1, KEY2, KEY3); assertNull(list.get(0)); assertEquals(entity2, list.get(1)); assertEquals(ENTITY3, list.get(2)); assertEquals(3, list.size()); try { transaction.commit(); fail("Expecting a failure"); } catch (DatastoreException expected) { assertEquals("FAILED_PRECONDITION", expected.getReason()); } try { transaction.rollback(); fail("Expecting a failure"); } catch (DatastoreException expected) { assertEquals("FAILED_PRECONDITION", expected.getReason()); } }
@Override public void rollback() { this.transaction.rollback(); }
/** * Marks a task entity as done. * * @param id The ID of the task entity as given by {@link Key#id()} * @return true if the task was found, false if not * @throws DatastoreException if the transaction fails */ boolean markDone(long id) { Transaction transaction = datastore.newTransaction(); try { Entity task = transaction.get(keyFactory.newKey(id)); if (task != null) { transaction.put(Entity.newBuilder(task).set("done", true).build()); } transaction.commit(); return task != null; } finally { if (transaction.isActive()) { transaction.rollback(); } } } // [END datastore_update_entity]
/** * @see Transaction#rollback() * @throws DatastoreIOException if the underlying client throws {@link DatastoreException} */ void rollback() throws DatastoreIOException { try { tx.rollback(); } catch (DatastoreException e) { throw new DatastoreIOException(e); } }
@Override default void rollback() { transaction().rollback(); }
@Override public void rollback() { try { nativeTransaction.rollback(); } catch (DatastoreException exp) { throw DatastoreUtils.wrap(exp); } catch (Exception exp) { throw new EntityManagerException(exp); } }