Search in sources :

Example 1 with AsyncTransactionManager

use of com.google.cloud.spanner.AsyncTransactionManager in project java-spanner by googleapis.

the class ITAsyncAPITest method testAsyncTransactionManagerReturnsCommitStats.

@Test
public void testAsyncTransactionManagerReturnsCommitStats() throws InterruptedException {
    assumeFalse("Emulator does not return commit statistics", isUsingEmulator());
    try (AsyncTransactionManager manager = client.transactionManagerAsync(Options.commitStats())) {
        TransactionContextFuture context = manager.beginAsync();
        while (true) {
            try {
                get(context.then((transaction, ignored) -> {
                    transaction.buffer(Mutation.newInsertOrUpdateBuilder(TABLE_NAME).set("Key").to("k_commit_stats").set("StringValue").to("Should return commit stats").build());
                    return ApiFutures.immediateFuture(null);
                }, executor).commitAsync());
                assertNotNull(get(manager.getCommitResponse()).getCommitStats());
                assertEquals(4L, get(manager.getCommitResponse()).getCommitStats().getMutationCount());
                break;
            } catch (AbortedException e) {
                Thread.sleep(e.getRetryDelayInMillis());
                context = manager.resetForRetryAsync();
            }
        }
    }
}
Also used : AsyncTransactionManager(com.google.cloud.spanner.AsyncTransactionManager) AbortedException(com.google.cloud.spanner.AbortedException) TransactionContextFuture(com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture) SerialIntegrationTest(com.google.cloud.spanner.SerialIntegrationTest) Test(org.junit.Test)

Example 2 with AsyncTransactionManager

use of com.google.cloud.spanner.AsyncTransactionManager in project java-spanner by googleapis.

the class ITTransactionManagerAsyncTest method testAbortAndRetry.

@Ignore("Cloud Spanner now seems to return CANCELLED instead of ABORTED when a transaction is invalidated by a later transaction in the same session")
@Test
public void testAbortAndRetry() throws InterruptedException, ExecutionException {
    assumeFalse("Emulator does not support more than 1 simultaneous transaction. " + "This test would therefore loop indefinitely on the emulator.", isUsingEmulator());
    client.write(Collections.singletonList(Mutation.newInsertBuilder("T").set("K").to("Key3").set("BoolValue").to(true).build()));
    try (AsyncTransactionManager manager1 = client.transactionManagerAsync()) {
        TransactionContextFuture txn1 = manager1.beginAsync();
        AsyncTransactionManager manager2;
        TransactionContextFuture txn2;
        AsyncTransactionStep<Void, Struct> txn2Step1;
        while (true) {
            try {
                AsyncTransactionStep<Void, Struct> txn1Step1 = txn1.then((transaction, ignored) -> transaction.readRowAsync("T", Key.of("Key3"), Arrays.asList("K", "BoolValue")), executor);
                manager2 = client.transactionManagerAsync();
                txn2 = manager2.beginAsync();
                txn2Step1 = txn2.then((transaction, ignored) -> transaction.readRowAsync("T", Key.of("Key3"), Arrays.asList("K", "BoolValue")), executor);
                AsyncTransactionStep<Struct, Void> txn1Step2 = txn1Step1.then((transaction, ignored) -> {
                    transaction.buffer(Mutation.newUpdateBuilder("T").set("K").to("Key3").set("BoolValue").to(false).build());
                    return ApiFutures.immediateFuture(null);
                }, executor);
                txn2Step1.get();
                txn1Step2.commitAsync().get();
                break;
            } catch (AbortedException e) {
                Thread.sleep(e.getRetryDelayInMillis());
                // In that case we should just retry without resetting anything.
                if (manager1.getState() == TransactionState.ABORTED) {
                    txn1 = manager1.resetForRetryAsync();
                }
            }
        }
        // txn2 should have been aborted.
        try {
            txn2Step1.commitAsync().get();
            fail("Expected to abort");
        } catch (AbortedException e) {
            assertThat(manager2.getState()).isEqualTo(TransactionState.ABORTED);
            txn2 = manager2.resetForRetryAsync();
        }
        AsyncTransactionStep<Void, Void> txn2Step2 = txn2.then((transaction, ignored) -> {
            transaction.buffer(Mutation.newUpdateBuilder("T").set("K").to("Key3").set("BoolValue").to(true).build());
            return ApiFutures.immediateFuture(null);
        }, executor);
        txn2Step2.commitAsync().get();
        Struct row = client.singleUse().readRow("T", Key.of("Key3"), Arrays.asList("K", "BoolValue"));
        assertThat(row.getString(0)).isEqualTo("Key3");
        assertThat(row.getBoolean(1)).isTrue();
        manager2.close();
    }
}
Also used : MoreExecutors(com.google.common.util.concurrent.MoreExecutors) Arrays(java.util.Arrays) BeforeClass(org.junit.BeforeClass) Assume.assumeFalse(org.junit.Assume.assumeFalse) RunWith(org.junit.runner.RunWith) Parameters(org.junit.runners.Parameterized.Parameters) TransactionState(com.google.cloud.spanner.TransactionManager.TransactionState) DatabaseClient(com.google.cloud.spanner.DatabaseClient) Spanner(com.google.cloud.spanner.Spanner) ImmutableList(com.google.common.collect.ImmutableList) AsyncTransactionManager(com.google.cloud.spanner.AsyncTransactionManager) Key(com.google.cloud.spanner.Key) Assert.fail(org.junit.Assert.fail) ClassRule(org.junit.ClassRule) Parameterized(org.junit.runners.Parameterized) Before(org.junit.Before) AbortedException(com.google.cloud.spanner.AbortedException) ParallelIntegrationTest(com.google.cloud.spanner.ParallelIntegrationTest) TransactionContextFuture(com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture) ApiFutures(com.google.api.core.ApiFutures) Database(com.google.cloud.spanner.Database) Executor(java.util.concurrent.Executor) Assert.assertNotNull(org.junit.Assert.assertNotNull) Parameter(org.junit.runners.Parameterized.Parameter) Collection(java.util.Collection) EmulatorSpannerHelper.isUsingEmulator(com.google.cloud.spanner.testing.EmulatorSpannerHelper.isUsingEmulator) Test(org.junit.Test) Mutation(com.google.cloud.spanner.Mutation) Truth.assertThat(com.google.common.truth.Truth.assertThat) Category(org.junit.experimental.categories.Category) Executors(java.util.concurrent.Executors) IntegrationTestEnv(com.google.cloud.spanner.IntegrationTestEnv) KeySet(com.google.cloud.spanner.KeySet) ErrorCode(com.google.cloud.spanner.ErrorCode) SpannerException(com.google.cloud.spanner.SpannerException) ExecutionException(java.util.concurrent.ExecutionException) Ignore(org.junit.Ignore) Struct(com.google.cloud.spanner.Struct) AsyncTransactionStep(com.google.cloud.spanner.AsyncTransactionManager.AsyncTransactionStep) Collections(java.util.Collections) AsyncTransactionManager(com.google.cloud.spanner.AsyncTransactionManager) AbortedException(com.google.cloud.spanner.AbortedException) TransactionContextFuture(com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture) Struct(com.google.cloud.spanner.Struct) Ignore(org.junit.Ignore) ParallelIntegrationTest(com.google.cloud.spanner.ParallelIntegrationTest) Test(org.junit.Test)

Example 3 with AsyncTransactionManager

use of com.google.cloud.spanner.AsyncTransactionManager in project java-spanner by googleapis.

the class AsyncTransactionManagerExample method asyncTransactionManager.

static void asyncTransactionManager(DatabaseClient client) throws InterruptedException, ExecutionException, TimeoutException {
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncTransactionStep<List<Struct>, long[]> updateCounts;
    try (AsyncTransactionManager mgr = client.transactionManagerAsync()) {
        TransactionContextFuture txn = mgr.beginAsync();
        // Loop to retry aborted errors.
        while (true) {
            try {
                updateCounts = txn.then((transaction, v) -> {
                    // Execute two reads in parallel and return the result of these as the input
                    // for the next step of the transaction.
                    ApiFuture<Struct> album1BudgetFut = transaction.readRowAsync("Albums", Key.of(1, 1), ImmutableList.of("MarketingBudget"));
                    ApiFuture<Struct> album2BudgetFut = transaction.readRowAsync("Albums", Key.of(2, 2), ImmutableList.of("MarketingBudget"));
                    return ApiFutures.allAsList(Arrays.asList(album1BudgetFut, album2BudgetFut));
                }, executor).then((transaction, budgets) -> {
                    long album1Budget = budgets.get(0).getLong(0);
                    long album2Budget = budgets.get(1).getLong(0);
                    long transfer = 200_000;
                    if (album2Budget >= transfer) {
                        album1Budget += transfer;
                        album2Budget -= transfer;
                        Statement updateStatement1 = Statement.newBuilder("UPDATE Albums " + "SET MarketingBudget = @AlbumBudget " + "WHERE SingerId = 1 and AlbumId = 1").bind("AlbumBudget").to(album1Budget).build();
                        Statement updateStatement2 = Statement.newBuilder("UPDATE Albums " + "SET MarketingBudget = @AlbumBudget " + "WHERE SingerId = 2 and AlbumId = 2").bind("AlbumBudget").to(album2Budget).build();
                        return transaction.batchUpdateAsync(ImmutableList.of(updateStatement1, updateStatement2));
                    } else {
                        return ApiFutures.immediateFuture(new long[] { 0L, 0L });
                    }
                }, executor);
                // Commit after the updates.
                CommitTimestampFuture commitTsFut = updateCounts.commitAsync();
                // Wait for the transaction to finish and execute a retry if necessary.
                commitTsFut.get();
                break;
            } catch (AbortedException e) {
                txn = mgr.resetForRetryAsync();
            }
        }
    }
    // Calculate the total update count.
    ApiFuture<Long> totalUpdateCount = ApiFutures.transform(updateCounts, new ApiFunction<long[], Long>() {

        @SuppressFBWarnings("UVA_USE_VAR_ARGS")
        @Override
        public Long apply(long[] input) {
            return Arrays.stream(input).sum();
        }
    }, MoreExecutors.directExecutor());
    System.out.printf("%d records updated.%n", totalUpdateCount.get(30L, TimeUnit.SECONDS));
    executor.shutdown();
}
Also used : MoreExecutors(com.google.common.util.concurrent.MoreExecutors) Arrays(java.util.Arrays) DatabaseId(com.google.cloud.spanner.DatabaseId) TimeoutException(java.util.concurrent.TimeoutException) DatabaseClient(com.google.cloud.spanner.DatabaseClient) Spanner(com.google.cloud.spanner.Spanner) ImmutableList(com.google.common.collect.ImmutableList) AsyncTransactionManager(com.google.cloud.spanner.AsyncTransactionManager) SpannerOptions(com.google.cloud.spanner.SpannerOptions) Key(com.google.cloud.spanner.Key) ExecutorService(java.util.concurrent.ExecutorService) CommitTimestampFuture(com.google.cloud.spanner.AsyncTransactionManager.CommitTimestampFuture) AbortedException(com.google.cloud.spanner.AbortedException) TransactionContextFuture(com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture) ApiFutures(com.google.api.core.ApiFutures) Executors(java.util.concurrent.Executors) ApiFuture(com.google.api.core.ApiFuture) Statement(com.google.cloud.spanner.Statement) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) Struct(com.google.cloud.spanner.Struct) AsyncTransactionStep(com.google.cloud.spanner.AsyncTransactionManager.AsyncTransactionStep) ApiFunction(com.google.api.core.ApiFunction) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings) Statement(com.google.cloud.spanner.Statement) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings) TransactionContextFuture(com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture) Struct(com.google.cloud.spanner.Struct) AsyncTransactionManager(com.google.cloud.spanner.AsyncTransactionManager) AbortedException(com.google.cloud.spanner.AbortedException) ExecutorService(java.util.concurrent.ExecutorService) ImmutableList(com.google.common.collect.ImmutableList) List(java.util.List) CommitTimestampFuture(com.google.cloud.spanner.AsyncTransactionManager.CommitTimestampFuture)

Example 4 with AsyncTransactionManager

use of com.google.cloud.spanner.AsyncTransactionManager in project java-spanner by googleapis.

the class ITTransactionManagerAsyncTest method testInvalidInsert.

@Test
public void testInvalidInsert() throws InterruptedException {
    try (AsyncTransactionManager manager = client.transactionManagerAsync()) {
        TransactionContextFuture txn = manager.beginAsync();
        while (true) {
            try {
                txn.then((transaction, ignored) -> {
                    transaction.buffer(Mutation.newInsertBuilder("InvalidTable").set("K").to("Key1").set("BoolValue").to(true).build());
                    return ApiFutures.immediateFuture(null);
                }, executor).commitAsync().get();
                fail("Expected exception");
            } catch (AbortedException e) {
                Thread.sleep(e.getRetryDelayInMillis());
                txn = manager.resetForRetryAsync();
            } catch (ExecutionException e) {
                assertThat(e.getCause()).isInstanceOf(SpannerException.class);
                SpannerException se = (SpannerException) e.getCause();
                assertThat(se.getErrorCode()).isEqualTo(ErrorCode.NOT_FOUND);
                // expected
                break;
            }
        }
        assertThat(manager.getState()).isEqualTo(TransactionState.COMMIT_FAILED);
        // We cannot retry for non aborted errors.
        try {
            manager.resetForRetryAsync();
            fail("Expected exception");
        } catch (IllegalStateException ex) {
            assertNotNull(ex.getMessage());
        }
    }
}
Also used : AsyncTransactionManager(com.google.cloud.spanner.AsyncTransactionManager) AbortedException(com.google.cloud.spanner.AbortedException) TransactionContextFuture(com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture) SpannerException(com.google.cloud.spanner.SpannerException) ExecutionException(java.util.concurrent.ExecutionException) ParallelIntegrationTest(com.google.cloud.spanner.ParallelIntegrationTest) Test(org.junit.Test)

Example 5 with AsyncTransactionManager

use of com.google.cloud.spanner.AsyncTransactionManager in project java-spanner by googleapis.

the class ITTransactionManagerAsyncTest method testRollback.

@Test
public void testRollback() throws InterruptedException {
    try (AsyncTransactionManager manager = client.transactionManagerAsync()) {
        TransactionContextFuture txn = manager.beginAsync();
        while (true) {
            txn.then((transaction, ignored) -> {
                transaction.buffer(Mutation.newInsertBuilder("T").set("K").to("Key2").set("BoolValue").to(true).build());
                return ApiFutures.immediateFuture(null);
            }, executor);
            try {
                manager.rollbackAsync();
                break;
            } catch (AbortedException e) {
                Thread.sleep(e.getRetryDelayInMillis());
                txn = manager.resetForRetryAsync();
            }
        }
        assertThat(manager.getState()).isEqualTo(TransactionState.ROLLED_BACK);
        // Row should not have been inserted.
        assertThat(client.singleUse().readRow("T", Key.of("Key2"), Arrays.asList("K", "BoolValue"))).isNull();
    }
}
Also used : AsyncTransactionManager(com.google.cloud.spanner.AsyncTransactionManager) AbortedException(com.google.cloud.spanner.AbortedException) TransactionContextFuture(com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture) ParallelIntegrationTest(com.google.cloud.spanner.ParallelIntegrationTest) Test(org.junit.Test)

Aggregations

AbortedException (com.google.cloud.spanner.AbortedException)6 AsyncTransactionManager (com.google.cloud.spanner.AsyncTransactionManager)6 TransactionContextFuture (com.google.cloud.spanner.AsyncTransactionManager.TransactionContextFuture)6 Test (org.junit.Test)5 ParallelIntegrationTest (com.google.cloud.spanner.ParallelIntegrationTest)4 Struct (com.google.cloud.spanner.Struct)3 ExecutionException (java.util.concurrent.ExecutionException)3 ApiFutures (com.google.api.core.ApiFutures)2 AsyncTransactionStep (com.google.cloud.spanner.AsyncTransactionManager.AsyncTransactionStep)2 DatabaseClient (com.google.cloud.spanner.DatabaseClient)2 Key (com.google.cloud.spanner.Key)2 Spanner (com.google.cloud.spanner.Spanner)2 SpannerException (com.google.cloud.spanner.SpannerException)2 ImmutableList (com.google.common.collect.ImmutableList)2 MoreExecutors (com.google.common.util.concurrent.MoreExecutors)2 Arrays (java.util.Arrays)2 Executors (java.util.concurrent.Executors)2 ApiFunction (com.google.api.core.ApiFunction)1 ApiFuture (com.google.api.core.ApiFuture)1 CommitTimestampFuture (com.google.cloud.spanner.AsyncTransactionManager.CommitTimestampFuture)1