private TimestampCorroborationConsistencyCheck createForTimestamps(long conservativeBound, long freshTimestamp) { return ImmutableTimestampCorroborationConsistencyCheck.builder() .conservativeBound(unused -> conservativeBound) .freshTimestampSource(unused -> freshTimestamp) .build(); } }
private TransactionManagerConsistencyResult checkAndAggregateResults(TransactionManager resource) { return consistencyChecks.stream() .map(check -> check.apply(resource)) .max(Comparator.comparingLong(result -> result.consistencyState().severity())) .orElse(TransactionManagerConsistencyResult.CONSISTENT_RESULT); }
@Test public void returnsConsistentIfBoundIsBelowFreshTimestamp() { TimestampCorroborationConsistencyCheck check = createForTimestamps(10, 20); assertThat(check.apply(mock(TransactionManager.class))) .isEqualTo(ImmutableTransactionManagerConsistencyResult.builder() .consistencyState(TransactionManagerConsistencyResult.ConsistencyState.CONSISTENT) .build()); }
lowerBound = conservativeBound().applyAsLong(transactionManager); } catch (Exception e) { log.warn("Could not obtain a lower bound on timestamps, so we don't know if our transaction manager" + " is consistent"); return indeterminateResultForException(e); freshTimestamp = freshTimestampSource().applyAsLong(transactionManager); } catch (Exception e) { log.warn("Could not obtain a fresh timestamp, so we don't know if our transaction manager is" + " consistent."); return indeterminateResultForException(e); return ImmutableTransactionManagerConsistencyResult.builder() .consistencyState(TransactionManagerConsistencyResult.ConsistencyState.TERMINAL) .reasonForInconsistency(clocksWentBackwards(lowerBound, freshTimestamp)) .build();
private static Callback<TransactionManager> timelockConsistencyCheckCallback( AtlasDbConfig atlasDbConfig, AtlasDbRuntimeConfig initialRuntimeConfig, LockAndTimestampServices lockAndTimestampServices) { if (isUsingTimeLock(atlasDbConfig, initialRuntimeConfig)) { // Only do the consistency check if we're using TimeLock. // This avoids a bootstrapping problem with leader-block services without async initialisation, // where you need a working timestamp service to check consistency, you need to check consistency // before you can return a TM, you need to return a TM to listen on ports, and you need to listen on // ports in order to get a working timestamp service. return ConsistencyCheckRunner.create( ImmutableTimestampCorroborationConsistencyCheck.builder() .conservativeBound(TransactionManager::getUnreadableTimestamp) .freshTimestampSource(unused -> lockAndTimestampServices.timelock().getFreshTimestamp()) .build()); } return Callback.noOp(); }
lowerBound = conservativeBound().applyAsLong(transactionManager); } catch (Exception e) { log.warn("Could not obtain a lower bound on timestamps, so we don't know if our transaction manager" + " is consistent"); return indeterminateResultForException(e); freshTimestamp = freshTimestampSource().applyAsLong(transactionManager); } catch (Exception e) { log.warn("Could not obtain a fresh timestamp, so we don't know if our transaction manager is" + " consistent."); return indeterminateResultForException(e); return ImmutableTransactionManagerConsistencyResult.builder() .consistencyState(TransactionManagerConsistencyResult.ConsistencyState.TERMINAL) .reasonForInconsistency(clocksWentBackwards(lowerBound, freshTimestamp)) .build();
@Test public void returnsTerminalIfBoundIsAboveFreshTimestamp() { TimestampCorroborationConsistencyCheck check = createForTimestamps(111, 42); assertThat(check.apply(mock(TransactionManager.class))).satisfies( result -> { assertThat(result.consistencyState()).isEqualTo( TransactionManagerConsistencyResult.ConsistencyState.TERMINAL); assertThat(result.reasonForInconsistency()).isPresent(); }); }
private TransactionManagerConsistencyResult checkAndAggregateResults(TransactionManager resource) { return consistencyChecks.stream() .map(check -> check.apply(resource)) .max(Comparator.comparingLong(result -> result.consistencyState().severity())) .orElse(TransactionManagerConsistencyResult.CONSISTENT_RESULT); }
@Test public void returnsIndeterminateIfCannotGetFreshTimestamp() { TimestampCorroborationConsistencyCheck checkFailingToGetFresh = ImmutableTimestampCorroborationConsistencyCheck.builder() .conservativeBound(txMgr -> 10L) .freshTimestampSource(EXCEPTION_THROWER) .build(); assertThat(checkFailingToGetFresh.apply(mock(TransactionManager.class))) .isEqualTo(ImmutableTransactionManagerConsistencyResult.builder() .consistencyState(TransactionManagerConsistencyResult.ConsistencyState.INDETERMINATE) .reasonForInconsistency(EXCEPTION) .build()); }
@Test public void returnsTerminalIfBoundEqualsFreshTimestamp() { TimestampCorroborationConsistencyCheck check = createForTimestamps(42, 42); assertThat(check.apply(mock(TransactionManager.class))).satisfies( result -> { assertThat(result.consistencyState()).isEqualTo( TransactionManagerConsistencyResult.ConsistencyState.TERMINAL); assertThat(result.reasonForInconsistency()).isPresent(); }); }
@Test public void returnsIndeterminateIfCannotGetConservativeBound() { TimestampCorroborationConsistencyCheck checkFailingToGetBound = ImmutableTimestampCorroborationConsistencyCheck.builder() .conservativeBound(EXCEPTION_THROWER) .freshTimestampSource(txMgr -> 7L) .build(); assertThat(checkFailingToGetBound.apply(mock(TransactionManager.class))) .isEqualTo(ImmutableTransactionManagerConsistencyResult.builder() .consistencyState(TransactionManagerConsistencyResult.ConsistencyState.INDETERMINATE) .reasonForInconsistency(EXCEPTION) .build()); }
private static Callback<TransactionManager> timelockConsistencyCheckCallback( AtlasDbConfig atlasDbConfig, AtlasDbRuntimeConfig initialRuntimeConfig, LockAndTimestampServices lockAndTimestampServices) { if (isUsingTimeLock(atlasDbConfig, initialRuntimeConfig)) { // Only do the consistency check if we're using TimeLock. // This avoids a bootstrapping problem with leader-block services without async initialisation, // where you need a working timestamp service to check consistency, you need to check consistency // before you can return a TM, you need to return a TM to listen on ports, and you need to listen on // ports in order to get a working timestamp service. return ConsistencyCheckRunner.create( ImmutableTimestampCorroborationConsistencyCheck.builder() .conservativeBound(TransactionManager::getUnreadableTimestamp) .freshTimestampSource(unused -> lockAndTimestampServices.timelock().getFreshTimestamp()) .build()); } return Callback.noOp(); }