@Override public long getFreshTimestamp() { return timelockService.getFreshTimestamp(); }
private static void tryGetFreshTimestamp(TimelockService service, int repetition) { for (int i = 0; i < repetition; i++) { try { service.getFreshTimestamp(); } catch (RuntimeException e) { // ignored - TODO(gsheasby): should assert exception message } } }
private Supplier<Long> getStartTimestampSupplier() { return Suppliers.memoize(() -> { long freshTimestamp = timelockService.getFreshTimestamp(); cleaner.punch(freshTimestamp); return freshTimestamp; }); }
@Override public long getFreshTimestamp() { return executeWithRecord(() -> timelockService.getFreshTimestamp()); }
@Test public void freshTimestampTrackerDelegatesToTimeLock() { createDefaultTracker(); when(timelockService.getFreshTimestamp()).thenReturn(TEN); assertThat(getGauge(FRESH_TIMESTAMP_NAME).getValue()).isEqualTo(TEN); verify(timelockService).getFreshTimestamp(); verifyNoMoreInteractions(timelockService, cleaner); }
@Test public void getTimestampDelegates() { long timestamp = 123L; when(timestampService.getFreshTimestamp()).thenReturn(timestamp); assertThat(timelock.getFreshTimestamp()).isEqualTo(timestamp); }
@Test public void getFreshTimestampShouldFail() { when(rawTimelockService.getFreshTimestamp()).thenReturn(1L); assertThrowsOnSecondCall(timelockService::getFreshTimestamp); }
@Test public void singleFreshTimestampRoutedToDecoratedService() { decoratingService.getFreshTimestamp(); verify(decoratedTimestamps).getFreshTimestamp(); }
@Test public void timelockIsHealthyAfterOneFailureMultipleSuccesses() { TimelockService instrumentedTimelockService = getFreshInstrumentedTimelockService(); when(timelockService.getFreshTimestamp()).thenThrow(new RuntimeException()).thenReturn(0L); tryGetFreshTimestamp(instrumentedTimelockService, 10); waitForClockTick(); assertThat(timelockHealthCheck.getStatus().isHealthy()).isTrue(); }
@Test public void timelockIsUnhealthyAfterOneSuccessMultipleFailures() { TimelockService instrumentedTimelockService = getFreshInstrumentedTimelockService(); when(timelockService.getFreshTimestamp()).thenReturn(0L).thenThrow(new RuntimeException()); tryGetFreshTimestamp(instrumentedTimelockService, 10); waitForClockTick(); assertThat(timelockHealthCheck.getStatus().isHealthy()).isFalse(); }
@Test public void resilientUnderMultipleThreads() throws InterruptedException { BlockingTimestamp blockingTimestampReturning1 = new BlockingTimestamp(1); when(rawTimelockService.getFreshTimestamp()) .thenAnswer(blockingTimestampReturning1) .thenReturn(2L); Future<Void> blockingGetFreshTimestampCall = CompletableFuture.runAsync(timelockService::getFreshTimestamp); blockingTimestampReturning1.waitForFirstCallToBlock(); assertThat(timelockService.getFreshTimestamp()) .as("This should have updated the lower bound to 2") .isEqualTo(2L); // we want to now resume the blocked call, which will return timestamp of 1 and not throw blockingTimestampReturning1.countdown(); assertThatCode(blockingGetFreshTimestampCall::get) .doesNotThrowAnyException(); }
@Test public void timelockIsUnhealthyAfterFailedRequests() { TimelockService instrumentedTimelockService = getFreshInstrumentedTimelockService(); when(timelockService.getFreshTimestamp()).thenThrow(new RuntimeException()); tryGetFreshTimestamp(instrumentedTimelockService, 10); waitForClockTick(); assertThat(timelockHealthCheck.getStatus().isHealthy()).isFalse(); }
@Test public void timelockIsHealthyAfterSuccessfulRequests() { TimelockService instrumentedTimelockService = getFreshInstrumentedTimelockService(); when(timelockService.getFreshTimestamp()).thenReturn(0L); tryGetFreshTimestamp(instrumentedTimelockService, 10); waitForClockTick(); assertThat(timelockHealthCheck.getStatus().isHealthy()).isTrue(); }
private void assertThatTimeAndLockMetricsAreRecorded(String timestampMetric, String lockMetric) { assertThat(metricsManager.getRegistry().timer(timestampMetric).getCount(), is(equalTo(0L))); assertThat(metricsManager.getRegistry().timer(lockMetric).getCount(), is(equalTo(0L))); TransactionManagers.LockAndTimestampServices lockAndTimestamp = getLockAndTimestampServices(); lockAndTimestamp.timelock().getFreshTimestamp(); lockAndTimestamp.timelock().currentTimeMillis(); assertThat(metricsManager.getRegistry().timer(timestampMetric).getCount(), is(equalTo(1L))); assertThat(metricsManager.getRegistry().timer(lockMetric).getCount(), is(equalTo(1L))); }
private void verifyUsingTimeLockByGettingAFreshTimestamp() { when(config.namespace()).thenReturn(Optional.of(CLIENT)); getLockAndTimestampServices().timelock().getFreshTimestamp(); availableServer.verify(1, postRequestedFor(urlMatching(TIMELOCK_TIMESTAMP_PATH))); }
@Test public void checkImmutableTsLockOnceIfThoroughlySwept_WithValidationOnReads() { TimelockService timelockService = spy(new LegacyTimelockService(timestampService, lockService, lockClient)); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction transaction = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP, true); transaction.get(TABLE_SWEPT_THOROUGH, ImmutableSet.of(TEST_CELL)); transaction.commit(); timelockService.unlock(ImmutableSet.of(res.getLock())); verify(timelockService).refreshLockLeases(ImmutableSet.of(res.getLock())); }
@Test public void validateLocksOnReadsIfThoroughlySwept() { TimelockService timelockService = new LegacyTimelockService(timestampService, lockService, lockClient); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction transaction = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP, true); timelockService.unlock(ImmutableSet.of(res.getLock())); assertThatExceptionOfType(TransactionLockTimeoutException.class).isThrownBy(() -> transaction.get(TABLE_SWEPT_THOROUGH, ImmutableSet.of(TEST_CELL))); }
@Test public void validateLocksOnlyOnCommitIfValidationFlagIsFalse() { TimelockService timelockService = new LegacyTimelockService(timestampService, lockService, lockClient); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction transaction = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP, false); timelockService.unlock(ImmutableSet.of(res.getLock())); transaction.get(TABLE_SWEPT_THOROUGH, ImmutableSet.of(TEST_CELL)); assertThatExceptionOfType(TransactionLockTimeoutException.class).isThrownBy(() -> transaction.commit()); }
@Test public void remoteCallsStillMadeIfPingableLeader404s() throws IOException, InterruptedException { setUpForRemoteServices(); setUpLeaderBlockInConfig(); TransactionManagers.LockAndTimestampServices lockAndTimestamp = getLockAndTimestampServices(); availableServer.verify(getRequestedFor(urlMatching(LEADER_UUID_PATH))); lockAndTimestamp.timelock().getFreshTimestamp(); lockAndTimestamp.lock().currentTimeMillis(); availableServer.verify(postRequestedFor(urlMatching(TIMESTAMP_PATH)) .withHeader(USER_AGENT_HEADER, WireMock.equalTo(USER_AGENT))); availableServer.verify(postRequestedFor(urlMatching(LOCK_PATH)) .withHeader(USER_AGENT_HEADER, WireMock.equalTo(USER_AGENT))); }
@Test public void remoteCallsElidedIfTalkingToLocalServer() throws IOException, InterruptedException { setUpForLocalServices(); setUpLeaderBlockInConfig(); TransactionManagers.LockAndTimestampServices lockAndTimestamp = getLockAndTimestampServices(); availableServer.verify(getRequestedFor(urlMatching(LEADER_UUID_PATH))); lockAndTimestamp.timelock().getFreshTimestamp(); lockAndTimestamp.lock().currentTimeMillis(); availableServer.verify(0, postRequestedFor(urlMatching(TIMESTAMP_PATH)) .withHeader(USER_AGENT_HEADER, WireMock.equalTo(USER_AGENT))); availableServer.verify(0, postRequestedFor(urlMatching(LOCK_PATH)) .withHeader(USER_AGENT_HEADER, WireMock.equalTo(USER_AGENT))); }