@Override public void run() { try (Session session = pool.getReadWriteSession()) { failed.compareAndSet(false, session == null); Uninterruptibles.sleepUninterruptibly(2, TimeUnit.MILLISECONDS); } catch (SpannerException e) { failed.compareAndSet(false, true); } finally { latch.countDown(); } } })
@Override public TransactionManager transactionManager() { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().transactionManager(); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public long executePartitionedUpdate(Statement stmt) { Span span = tracer.spanBuilder(PARTITION_DML_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().executePartitionedUpdate(stmt); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public TransactionRunner readWriteTransaction() { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().readWriteTransaction(); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public Timestamp write(Iterable<Mutation> mutations) throws SpannerException { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().write(mutations); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } finally { span.end(); } }
@Override public Timestamp writeAtLeastOnce(Iterable<Mutation> mutations) throws SpannerException { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().writeAtLeastOnce(mutations); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } finally { span.end(); } }
@Test public void getReadWriteSession() { Session mockSession = mockSession(); when(client.createSession(db)).thenReturn(mockSession); pool = createPool(); try (Session session = pool.getReadWriteSession()) { assertThat(session).isNotNull(); verify(mockSession).prepareReadWriteTransaction(); } }
@Test public void getMultipleReadWriteSessions() { Session mockSession1 = mockSession(); Session mockSession2 = mockSession(); when(client.createSession(db)).thenReturn(mockSession1).thenReturn(mockSession2); pool = createPool(); Session session1 = pool.getReadWriteSession(); Session session2 = pool.getReadWriteSession(); verify(mockSession1).prepareReadWriteTransaction(); verify(mockSession2).prepareReadWriteTransaction(); session1.close(); session2.close(); }
@Test public void poolWorksWhenSessionNotFound() { Session mockSession1 = mockSession(); Session mockSession2 = mockSession(); doThrow(SpannerExceptionFactory.newSpannerException(ErrorCode.NOT_FOUND, "Session not found")) .when(mockSession1) .prepareReadWriteTransaction(); when(client.createSession(db)).thenReturn(mockSession1).thenReturn(mockSession2); pool = createPool(); assertThat(((PooledSession) pool.getReadWriteSession()).delegate).isEqualTo(mockSession2); }
@Override public void run() { Uninterruptibles.awaitUninterruptibly(releaseThreads); for (int j = 0; j < numOperationsPerThread; j++) { try { Session session = null; if (random.nextInt(10) < writeOperationFraction) { session = pool.getReadWriteSession(); assertWritePrepared(session); } else { session = pool.getReadSession(); } Uninterruptibles.sleepUninterruptibly( random.nextInt(5), TimeUnit.MILLISECONDS); resetTransaction(session); session.close(); } catch (SpannerException e) { if (e.getErrorCode() != ErrorCode.RESOURCE_EXHAUSTED || shouldBlock) { setFailed(e); } } catch (Exception e) { setFailed(e); } } threadsDone.countDown(); } })
@Test public void creationExceptionPropagatesToReadWriteSession() { when(client.createSession(db)) .thenThrow(SpannerExceptionFactory.newSpannerException(ErrorCode.INTERNAL, "")); pool = createPool(); expectedException.expect(isSpannerException(ErrorCode.INTERNAL)); pool.getReadWriteSession(); }
@Test public void prepareExceptionPropagatesToReadWriteSession() { Session session = mockSession(); when(client.createSession(db)).thenReturn(session); doThrow(SpannerExceptionFactory.newSpannerException(ErrorCode.INTERNAL, "")) .when(session) .prepareReadWriteTransaction(); pool = createPool(); expectedException.expect(isSpannerException(ErrorCode.INTERNAL)); pool.getReadWriteSession(); }
@Test public void getReadSessionFallsBackToWritePreparedSession() throws Exception { Session mockSession1 = mockSession(); final CountDownLatch prepareLatch = new CountDownLatch(2); doAnswer( new Answer<Void>() { @Override public Void answer(InvocationOnMock arg0) throws Throwable { prepareLatch.countDown(); return null; } }) .when(mockSession1) .prepareReadWriteTransaction(); when(client.createSession(db)).thenReturn(mockSession1); options = SessionPoolOptions.newBuilder() .setMinSessions(minSessions) .setMaxSessions(1) .setWriteSessionsFraction(1.0f) .build(); pool = createPool(); pool.getReadWriteSession().close(); prepareLatch.await(); // This session should also be write prepared. PooledSession readSession = (PooledSession) pool.getReadSession(); verify(readSession.delegate, times(2)).prepareReadWriteTransaction(); }
PooledSession writeSession = (PooledSession) pool.getReadWriteSession(); verify(writeSession.delegate, times(1)).prepareReadWriteTransaction(); verify(readSession.delegate, never()).prepareReadWriteTransaction();
@Override public long executePartitionedUpdate(Statement stmt) { Span span = tracer.spanBuilder(PARTITION_DML_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().executePartitionedUpdate(stmt); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public TransactionRunner readWriteTransaction() { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().readWriteTransaction(); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public TransactionManager transactionManager() { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().transactionManager(); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } }
@Override public Timestamp writeAtLeastOnce(Iterable<Mutation> mutations) throws SpannerException { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().writeAtLeastOnce(mutations); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } finally { span.end(); } }
@Override public Timestamp write(Iterable<Mutation> mutations) throws SpannerException { Span span = tracer.spanBuilder(READ_WRITE_TRANSACTION).startSpan(); try (Scope s = tracer.withSpan(span)) { return pool.getReadWriteSession().write(mutations); } catch (RuntimeException e) { TraceUtil.endSpanWithFailure(span, e); throw e; } finally { span.end(); } }