Search in sources :

Example 1 with ReadyCallback

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

the class ConnectionAsyncApiAbortedTest method testUpdateAndQueryAbortedMidway.

@Test
public void testUpdateAndQueryAbortedMidway() throws InterruptedException {
    mockSpanner.setExecuteStreamingSqlExecutionTime(SimulatedExecutionTime.ofStreamException(mockSpanner.createAbortedException(ByteString.copyFromUtf8("test")), RANDOM_RESULT_SET_ROW_COUNT / 2));
    final RetryCounter counter = new RetryCounter();
    try (Connection connection = createConnection(counter)) {
        assertThat(counter.retryCount).isEqualTo(0);
        final SettableApiFuture<Long> rowCount = SettableApiFuture.create();
        final CountDownLatch updateLatch = new CountDownLatch(1);
        final CountDownLatch queryLatch = new CountDownLatch(1);
        ApiFuture<Void> finished;
        try (AsyncResultSet rs = connection.executeQueryAsync(SELECT_RANDOM_STATEMENT, Options.bufferRows(RANDOM_RESULT_SET_ROW_COUNT / 2 - 1))) {
            finished = rs.setCallback(singleThreadedExecutor, new ReadyCallback() {

                long count;

                @Override
                public CallbackResponse cursorReady(AsyncResultSet resultSet) {
                    // Indicate that the query has been executed.
                    queryLatch.countDown();
                    try {
                        // Wait until the update is on its way.
                        updateLatch.await(10L, TimeUnit.SECONDS);
                        while (true) {
                            switch(resultSet.tryNext()) {
                                case OK:
                                    count++;
                                    break;
                                case DONE:
                                    rowCount.set(count);
                                    return CallbackResponse.DONE;
                                case NOT_READY:
                                    return CallbackResponse.CONTINUE;
                            }
                        }
                    } catch (InterruptedException e) {
                        throw SpannerExceptionFactory.propagateInterrupt(e);
                    }
                }
            });
        }
        // Wait until the query has actually executed.
        queryLatch.await(10L, TimeUnit.SECONDS);
        ApiFuture<Long> updateCount = connection.executeUpdateAsync(INSERT_STATEMENT);
        updateCount.addListener(updateLatch::countDown, MoreExecutors.directExecutor());
        // We should not commit before the AsyncResultSet has finished.
        assertThat(get(finished)).isNull();
        ApiFuture<Void> commit = connection.commitAsync();
        assertThat(get(rowCount)).isEqualTo(RANDOM_RESULT_SET_ROW_COUNT);
        assertThat(get(updateCount)).isEqualTo(UPDATE_COUNT);
        assertThat(get(commit)).isNull();
        assertThat(counter.retryCount).isEqualTo(1);
        // Verify the order of the statements on the server.
        List<? extends AbstractMessage> requests = Lists.newArrayList(Collections2.filter(mockSpanner.getRequests(), input -> input instanceof ExecuteSqlRequest));
        // The entire transaction should be retried.
        assertThat(requests).hasSize(4);
        assertThat(((ExecuteSqlRequest) requests.get(0)).getSeqno()).isEqualTo(1L);
        assertThat(((ExecuteSqlRequest) requests.get(0)).getSql()).isEqualTo(SELECT_RANDOM_STATEMENT.getSql());
        assertThat(((ExecuteSqlRequest) requests.get(1)).getSeqno()).isEqualTo(2L);
        assertThat(((ExecuteSqlRequest) requests.get(1)).getSql()).isEqualTo(INSERT_STATEMENT.getSql());
        assertThat(((ExecuteSqlRequest) requests.get(2)).getSeqno()).isEqualTo(1L);
        assertThat(((ExecuteSqlRequest) requests.get(2)).getSql()).isEqualTo(SELECT_RANDOM_STATEMENT.getSql());
        assertThat(((ExecuteSqlRequest) requests.get(3)).getSeqno()).isEqualTo(2L);
        assertThat(((ExecuteSqlRequest) requests.get(3)).getSql()).isEqualTo(INSERT_STATEMENT.getSql());
    }
}
Also used : MoreExecutors(com.google.common.util.concurrent.MoreExecutors) BeforeClass(org.junit.BeforeClass) SpannerExceptionFactory(com.google.cloud.spanner.SpannerExceptionFactory) Timestamp(com.google.cloud.Timestamp) Collections2(com.google.common.collect.Collections2) StatementResult(com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult) ArrayList(java.util.ArrayList) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) After(org.junit.After) Assert.fail(org.junit.Assert.fail) AbortedDueToConcurrentModificationException(com.google.cloud.spanner.AbortedDueToConcurrentModificationException) SimulatedExecutionTime(com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) AfterClass(org.junit.AfterClass) CallbackResponse(com.google.cloud.spanner.AsyncResultSet.CallbackResponse) AbstractMessage(com.google.protobuf.AbstractMessage) Executor(java.util.concurrent.Executor) SpannerApiFutures.get(com.google.cloud.spanner.SpannerApiFutures.get) ITConnection(com.google.cloud.spanner.connection.ITAbstractSpannerTest.ITConnection) Test(org.junit.Test) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback) Truth.assertThat(com.google.common.truth.Truth.assertThat) Options(com.google.cloud.spanner.Options) Executors(java.util.concurrent.Executors) ApiFuture(com.google.api.core.ApiFuture) SettableApiFuture(com.google.api.core.SettableApiFuture) Statement(com.google.cloud.spanner.Statement) ByteString(com.google.protobuf.ByteString) TimeUnit(java.util.concurrent.TimeUnit) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) ExecuteSqlRequest(com.google.spanner.v1.ExecuteSqlRequest) AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) ITConnection(com.google.cloud.spanner.connection.ITAbstractSpannerTest.ITConnection) CountDownLatch(java.util.concurrent.CountDownLatch) ExecuteSqlRequest(com.google.spanner.v1.ExecuteSqlRequest) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback) Test(org.junit.Test)

Example 2 with ReadyCallback

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

the class ConnectionAsyncApiAbortedTest method testQueriesAbortedMidway_ResultsChanged.

@Test
public void testQueriesAbortedMidway_ResultsChanged() {
    mockSpanner.setExecuteStreamingSqlExecutionTime(SimulatedExecutionTime.ofStreamException(mockSpanner.createAbortedException(ByteString.copyFromUtf8("test")), RANDOM_RESULT_SET_ROW_COUNT - 1));
    final Statement statement = Statement.of("SELECT * FROM TEST_TABLE");
    final RandomResultSetGenerator generator = new RandomResultSetGenerator(RANDOM_RESULT_SET_ROW_COUNT - 10);
    mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate()));
    final CountDownLatch latch = new CountDownLatch(1);
    final RetryCounter counter = new RetryCounter();
    try (Connection connection = createConnection(counter)) {
        ApiFuture<Void> res1;
        try (AsyncResultSet rs = connection.executeQueryAsync(SELECT_RANDOM_STATEMENT, Options.bufferRows(5))) {
            res1 = rs.setCallback(multiThreadedExecutor, resultSet -> {
                try {
                    latch.await(10L, TimeUnit.SECONDS);
                    while (true) {
                        switch(resultSet.tryNext()) {
                            case OK:
                                break;
                            case DONE:
                                return CallbackResponse.DONE;
                            case NOT_READY:
                                return CallbackResponse.CONTINUE;
                        }
                    }
                } catch (Throwable t) {
                    throw SpannerExceptionFactory.asSpannerException(t);
                }
            });
        }
        try (AsyncResultSet rs = connection.executeQueryAsync(statement, Options.bufferRows(5))) {
            rs.setCallback(multiThreadedExecutor, new ReadyCallback() {

                boolean replaced;

                @Override
                public CallbackResponse cursorReady(AsyncResultSet resultSet) {
                    if (!replaced) {
                        // Replace the result of the query on the server after the first execution.
                        mockSpanner.putStatementResult(StatementResult.query(statement, generator.generate()));
                        replaced = true;
                    }
                    while (true) {
                        switch(resultSet.tryNext()) {
                            case OK:
                                break;
                            case DONE:
                                latch.countDown();
                                return CallbackResponse.DONE;
                            case NOT_READY:
                                return CallbackResponse.CONTINUE;
                        }
                    }
                }
            });
        }
        try {
            get(res1);
            fail("Missing expected exception");
        } catch (AbortedDueToConcurrentModificationException e) {
            assertThat(counter.retryCount).isEqualTo(1);
        }
    }
}
Also used : MoreExecutors(com.google.common.util.concurrent.MoreExecutors) BeforeClass(org.junit.BeforeClass) SpannerExceptionFactory(com.google.cloud.spanner.SpannerExceptionFactory) Timestamp(com.google.cloud.Timestamp) Collections2(com.google.common.collect.Collections2) StatementResult(com.google.cloud.spanner.MockSpannerServiceImpl.StatementResult) ArrayList(java.util.ArrayList) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) After(org.junit.After) Assert.fail(org.junit.Assert.fail) AbortedDueToConcurrentModificationException(com.google.cloud.spanner.AbortedDueToConcurrentModificationException) SimulatedExecutionTime(com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) AfterClass(org.junit.AfterClass) CallbackResponse(com.google.cloud.spanner.AsyncResultSet.CallbackResponse) AbstractMessage(com.google.protobuf.AbstractMessage) Executor(java.util.concurrent.Executor) SpannerApiFutures.get(com.google.cloud.spanner.SpannerApiFutures.get) ITConnection(com.google.cloud.spanner.connection.ITAbstractSpannerTest.ITConnection) Test(org.junit.Test) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback) Truth.assertThat(com.google.common.truth.Truth.assertThat) Options(com.google.cloud.spanner.Options) Executors(java.util.concurrent.Executors) ApiFuture(com.google.api.core.ApiFuture) SettableApiFuture(com.google.api.core.SettableApiFuture) Statement(com.google.cloud.spanner.Statement) ByteString(com.google.protobuf.ByteString) TimeUnit(java.util.concurrent.TimeUnit) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) ExecuteSqlRequest(com.google.spanner.v1.ExecuteSqlRequest) AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) CallbackResponse(com.google.cloud.spanner.AsyncResultSet.CallbackResponse) Statement(com.google.cloud.spanner.Statement) ITConnection(com.google.cloud.spanner.connection.ITAbstractSpannerTest.ITConnection) CountDownLatch(java.util.concurrent.CountDownLatch) AbortedDueToConcurrentModificationException(com.google.cloud.spanner.AbortedDueToConcurrentModificationException) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback) Test(org.junit.Test)

Example 3 with ReadyCallback

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

the class ConnectionAsyncApiTest method testReadWriteMultipleAsyncStatements.

@Test
public void testReadWriteMultipleAsyncStatements() {
    try (Connection connection = createConnection()) {
        assertThat(connection.isAutocommit()).isFalse();
        ApiFuture<Long> update1 = connection.executeUpdateAsync(INSERT_STATEMENT);
        ApiFuture<Long> update2 = connection.executeUpdateAsync(INSERT_STATEMENT);
        ApiFuture<long[]> batch = connection.executeBatchUpdateAsync(ImmutableList.of(INSERT_STATEMENT, INSERT_STATEMENT));
        final SettableApiFuture<Integer> rowCount = SettableApiFuture.create();
        try (AsyncResultSet rs = connection.executeQueryAsync(SELECT_RANDOM_STATEMENT)) {
            rs.setCallback(executor, new ReadyCallback() {

                int count = 0;

                @Override
                public CallbackResponse cursorReady(AsyncResultSet resultSet) {
                    try {
                        while (true) {
                            switch(resultSet.tryNext()) {
                                case DONE:
                                    rowCount.set(count);
                                    return CallbackResponse.DONE;
                                case NOT_READY:
                                    return CallbackResponse.CONTINUE;
                                case OK:
                                    count++;
                            }
                        }
                    } catch (SpannerException e) {
                        rowCount.setException(e);
                        return CallbackResponse.DONE;
                    }
                }
            });
        }
        ApiFuture<Void> commit = connection.commitAsync();
        assertThat(get(update1)).isEqualTo(UPDATE_COUNT);
        assertThat(get(update2)).isEqualTo(UPDATE_COUNT);
        assertThat(get(batch)).asList().containsExactly(1L, 1L);
        assertThat(get(rowCount)).isEqualTo(RANDOM_RESULT_SET_ROW_COUNT);
        assertNull(get(commit));
        // Get the last commit request.
        CommitRequest commitRequest = mockSpanner.getRequestsOfType(CommitRequest.class).stream().reduce((first, second) -> second).get();
        // Verify the order of the statements on the server.
        List<? extends AbstractMessage> requests = Lists.newArrayList(Collections2.filter(mockSpanner.getRequests(), input -> (input instanceof ExecuteSqlRequest && ((ExecuteSqlRequest) input).getSession().equals(commitRequest.getSession())) || (input instanceof ExecuteBatchDmlRequest && ((ExecuteBatchDmlRequest) input).getSession().equals(commitRequest.getSession()))));
        assertThat(requests).hasSize(4);
        assertThat(requests.get(0)).isInstanceOf(ExecuteSqlRequest.class);
        assertThat(((ExecuteSqlRequest) requests.get(0)).getSeqno()).isEqualTo(1L);
        assertThat(requests.get(1)).isInstanceOf(ExecuteSqlRequest.class);
        assertThat(((ExecuteSqlRequest) requests.get(1)).getSeqno()).isEqualTo(2L);
        assertThat(requests.get(2)).isInstanceOf(ExecuteBatchDmlRequest.class);
        assertThat(((ExecuteBatchDmlRequest) requests.get(2)).getSeqno()).isEqualTo(3L);
        assertThat(requests.get(3)).isInstanceOf(ExecuteSqlRequest.class);
        assertThat(((ExecuteSqlRequest) requests.get(3)).getSeqno()).isEqualTo(4L);
    }
}
Also used : CommitRequest(com.google.spanner.v1.CommitRequest) CheckAndCloseSpannersMode(com.google.cloud.spanner.connection.SpannerPool.CheckAndCloseSpannersMode) Assert.assertThrows(org.junit.Assert.assertThrows) RunWith(org.junit.runner.RunWith) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Collections2(com.google.common.collect.Collections2) ResultSet(com.google.cloud.spanner.ResultSet) CommitRequest(com.google.spanner.v1.CommitRequest) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) After(org.junit.After) Assert.fail(org.junit.Assert.fail) SimulatedExecutionTime(com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) AfterClass(org.junit.AfterClass) Function(com.google.common.base.Function) CallbackResponse(com.google.cloud.spanner.AsyncResultSet.CallbackResponse) AbstractMessage(com.google.protobuf.AbstractMessage) SpannerApiFutures.get(com.google.cloud.spanner.SpannerApiFutures.get) Test(org.junit.Test) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback) Mutation(com.google.cloud.spanner.Mutation) JUnit4(org.junit.runners.JUnit4) Truth.assertThat(com.google.common.truth.Truth.assertThat) ForceCloseSpannerFunction(com.google.cloud.spanner.ForceCloseSpannerFunction) Executors(java.util.concurrent.Executors) ApiFuture(com.google.api.core.ApiFuture) SettableApiFuture(com.google.api.core.SettableApiFuture) ErrorCode(com.google.cloud.spanner.ErrorCode) SpannerException(com.google.cloud.spanner.SpannerException) Statement(com.google.cloud.spanner.Statement) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) Assert.assertNull(org.junit.Assert.assertNull) ResultType(com.google.cloud.spanner.connection.StatementResult.ResultType) ExecuteSqlRequest(com.google.spanner.v1.ExecuteSqlRequest) ExecuteBatchDmlRequest(com.google.spanner.v1.ExecuteBatchDmlRequest) SpannerApiFutures(com.google.cloud.spanner.SpannerApiFutures) Assert.assertEquals(org.junit.Assert.assertEquals) AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) CallbackResponse(com.google.cloud.spanner.AsyncResultSet.CallbackResponse) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ExecuteSqlRequest(com.google.spanner.v1.ExecuteSqlRequest) SpannerException(com.google.cloud.spanner.SpannerException) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback) ExecuteBatchDmlRequest(com.google.spanner.v1.ExecuteBatchDmlRequest) Test(org.junit.Test)

Example 4 with ReadyCallback

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

the class ITAsyncExamplesTest method readAsync.

@Test
public void readAsync() throws Exception {
    final SettableApiFuture<List<String>> future = SettableApiFuture.create();
    try (AsyncResultSet rs = client.singleUse().readAsync(TABLE_NAME, KeySet.all(), ALL_COLUMNS)) {
        rs.setCallback(executor, new ReadyCallback() {

            final List<String> values = new LinkedList<>();

            @Override
            public CallbackResponse cursorReady(AsyncResultSet resultSet) {
                try {
                    while (true) {
                        switch(resultSet.tryNext()) {
                            case DONE:
                                future.set(values);
                                return CallbackResponse.DONE;
                            case NOT_READY:
                                return CallbackResponse.CONTINUE;
                            case OK:
                                values.add(resultSet.getString("StringValue"));
                                break;
                        }
                    }
                } catch (Throwable t) {
                    future.setException(t);
                    return CallbackResponse.DONE;
                }
            }
        });
    }
    assertThat(future.get()).containsExactlyElementsIn(ALL_VALUES_IN_PK_ORDER);
}
Also used : AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) CallbackResponse(com.google.cloud.spanner.AsyncResultSet.CallbackResponse) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) LinkedList(java.util.LinkedList) List(java.util.List) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback) LinkedList(java.util.LinkedList) Test(org.junit.Test) SerialIntegrationTest(com.google.cloud.spanner.SerialIntegrationTest)

Example 5 with ReadyCallback

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

the class AsyncQueryExample method asyncQuery.

// Execute a query asynchronously and process the results in a callback.
static void asyncQuery(DatabaseClient client) throws InterruptedException, ExecutionException, TimeoutException {
    ApiFuture<Void> finished;
    ExecutorService executor = Executors.newSingleThreadExecutor();
    try (AsyncResultSet resultSet = client.singleUse().executeQueryAsync(Statement.of("SELECT SingerId, AlbumId, AlbumTitle FROM Albums"))) {
        // Setting a callback will automatically start the iteration over the results of the query
        // using the specified executor. The callback will be called at least once. The returned
        // ApiFuture is done when the callback has returned DONE and all resources used by the
        // AsyncResultSet have been released.
        finished = resultSet.setCallback(executor, new ReadyCallback() {

            @Override
            public CallbackResponse cursorReady(AsyncResultSet resultSet) {
                try {
                    while (true) {
                        switch(resultSet.tryNext()) {
                            // OK: There is a row ready.
                            case OK:
                                System.out.printf("%d %d %s%n", resultSet.getLong(0), resultSet.getLong(1), resultSet.getString(2));
                                break;
                            // DONE: There are no more rows in the result set.
                            case DONE:
                                return CallbackResponse.DONE;
                            // NOT_READY: There are currently no more rows in the buffer.
                            case NOT_READY:
                                return CallbackResponse.CONTINUE;
                            default:
                                throw new IllegalStateException();
                        }
                    }
                } catch (SpannerException e) {
                    System.out.printf("Error in callback: %s%n", e.getMessage());
                    return CallbackResponse.DONE;
                }
            }
        });
    }
    // This ApiFuture is done when the callback has returned DONE and all resources of the
    // asynchronous result set have been released.
    finished.get(30L, TimeUnit.SECONDS);
    executor.shutdown();
}
Also used : AsyncResultSet(com.google.cloud.spanner.AsyncResultSet) ExecutorService(java.util.concurrent.ExecutorService) SpannerException(com.google.cloud.spanner.SpannerException) ReadyCallback(com.google.cloud.spanner.AsyncResultSet.ReadyCallback)

Aggregations

AsyncResultSet (com.google.cloud.spanner.AsyncResultSet)12 ReadyCallback (com.google.cloud.spanner.AsyncResultSet.ReadyCallback)12 CallbackResponse (com.google.cloud.spanner.AsyncResultSet.CallbackResponse)8 ExecutorService (java.util.concurrent.ExecutorService)7 ImmutableList (com.google.common.collect.ImmutableList)6 List (java.util.List)6 Test (org.junit.Test)6 SpannerException (com.google.cloud.spanner.SpannerException)5 ArrayList (java.util.ArrayList)5 ApiFuture (com.google.api.core.ApiFuture)3 SettableApiFuture (com.google.api.core.SettableApiFuture)3 SimulatedExecutionTime (com.google.cloud.spanner.MockSpannerServiceImpl.SimulatedExecutionTime)3 SpannerApiFutures.get (com.google.cloud.spanner.SpannerApiFutures.get)3 Statement (com.google.cloud.spanner.Statement)3 Collections2 (com.google.common.collect.Collections2)3 Lists (com.google.common.collect.Lists)3 Truth.assertThat (com.google.common.truth.Truth.assertThat)3 AbstractMessage (com.google.protobuf.AbstractMessage)3 ExecuteSqlRequest (com.google.spanner.v1.ExecuteSqlRequest)3 Executors (java.util.concurrent.Executors)3