@Override public LockImmutableTimestampResponse lockImmutableTimestamp( IdentifiedTimeLockRequest request) { return executeWithRecord(() -> timelockService.lockImmutableTimestamp(request)); }
@Override public LockImmutableTimestampResponse lockImmutableTimestamp(IdentifiedTimeLockRequest request) { LockImmutableTimestampResponse response = executeOnTimeLock(() -> delegate.lockImmutableTimestamp(request)); lockRefresher.registerLock(response.getLock()); return response; }
@Test public void registersImmutableTimestampLock() { when(delegate.lockImmutableTimestamp(any())).thenReturn(LockImmutableTimestampResponse.of(123L, TOKEN_1)); timelock.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); verify(refresher).registerLock(TOKEN_1); }
@Test public void methodsNotOnTimestampServiceRoutedToDelegateService() { decoratingService.currentTimeMillis(); verify(delegate).currentTimeMillis(); IdentifiedTimeLockRequest immutableTimestampRequest = IdentifiedTimeLockRequest.create(); decoratingService.lockImmutableTimestamp(immutableTimestampRequest); verify(delegate).lockImmutableTimestamp(eq(immutableTimestampRequest)); } }
@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())); }
when(timelock.lockImmutableTimestamp(any())).thenReturn( LockImmutableTimestampResponse.of(2L, LockToken.of(UUID.randomUUID()))); when(timelock.startIdentifiedAtlasDbTransaction(any())).thenReturn(
@Test public void checkImmutableTsLockOnceIfThoroughlySwept_WithoutValidationOnReads() { 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, false); 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 commitDoesNotThrowIfAlreadySuccessfullyCommitted() { final Cell cell = Cell.create(PtBytes.toBytes("row1"), PtBytes.toBytes("column1")); TimestampService timestampServiceSpy = spy(timestampService); TimelockService timelockService = new LegacyTimelockService(timestampServiceSpy, lockService, lockClient); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction snapshot = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP); when(timestampServiceSpy.getFreshTimestamp()).thenReturn(10000000L); //forcing to try to commit a transaction that is already committed transactionService.putUnlessExists(transactionTs, timelockService.getFreshTimestamp()); snapshot.put(TABLE, ImmutableMap.of(cell, PtBytes.toBytes("value"))); snapshot.commit(); timelockService.unlock(Collections.singleton(res.getLock())); }
@Test public void commitThrowsIfRolledBackAtCommitTime_expiredLocks() { final Cell cell = Cell.create(PtBytes.toBytes("row1"), PtBytes.toBytes("column1")); TimelockService timelockService = spy(new LegacyTimelockService(timestampService, lockService, lockClient)); // expire the locks when the pre-commit check happens - this is guaranteed to be after we've written the data PreCommitCondition condition = unused -> doReturn(ImmutableSet.of()).when(timelockService).refreshLockLeases(any()); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); long transactionTs = timelockService.getFreshTimestamp(); SnapshotTransaction snapshot = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, condition); //simulate roll back at commit time transactionService.putUnlessExists(snapshot.getTimestamp(), TransactionConstants.FAILED_COMMIT_TS); snapshot.put(TABLE, ImmutableMap.of(cell, PtBytes.toBytes("value"))); assertThatExceptionOfType(TransactionLockTimeoutException.class).isThrownBy(snapshot::commit); timelockService.unlock(ImmutableSet.of(res.getLock())); TransactionOutcomeMetricsAssert.assertThat(transactionOutcomeMetrics) .hasFailedCommits(1) .hasLocksExpired(1); }
@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()); }
@Override public LockImmutableTimestampResponse lockImmutableTimestamp( IdentifiedTimeLockRequest request) { return executeWithRecord(() -> timelockService.lockImmutableTimestamp(request)); }
@Test public void commitThrowsIfRolledBackAtCommitTime_alreadyAborted() { final Cell cell = Cell.create(PtBytes.toBytes("row1"), PtBytes.toBytes("column1")); TimelockService timelockService = new LegacyTimelockService(timestampService, lockService, lockClient); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); long transactionTs = timelockService.getFreshTimestamp(); SnapshotTransaction snapshot = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP); //forcing to try to commit a transaction that is already committed transactionService.putUnlessExists(transactionTs, TransactionConstants.FAILED_COMMIT_TS); snapshot.put(TABLE, ImmutableMap.of(cell, PtBytes.toBytes("value"))); assertThatExceptionOfType(TransactionCommitFailedException.class).isThrownBy(snapshot::commit); timelockService.unlock(Collections.singleton(res.getLock())); }
@Override public LockImmutableTimestampResponse lockImmutableTimestamp(IdentifiedTimeLockRequest request) { LockImmutableTimestampResponse response = executeOnTimeLock(() -> delegate.lockImmutableTimestamp(request)); lockRefresher.registerLock(response.getLock()); return response; }