@Override protected Optional<SweepResults> completeSweep(TableReference ignored, long ts) { when(timestampsSupplier.getUnreadableTimestamp()).thenReturn(ts); when(timestampsSupplier.getImmutableTimestamp()).thenReturn(ts); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(0)); sweepQueue.sweepNextBatch(ShardAndStrategy.thorough(0)); return Optional.empty(); }
@Test public void sweepCellOnlyOnceWhenInLastPartitionBeforeSweepTs() { immutableTs = 2 * TS_COARSE_GRANULARITY - TS_FINE_GRANULARITY; verify(spiedKvs, never()).deleteAllTimestamps(any(TableReference.class), anyMap(), eq(false)); enqueueWriteCommitted(TABLE_CONS, immutableTs - 1); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); verify(spiedKvs, times(1)).deleteAllTimestamps(any(TableReference.class), anyMap(), eq(false)); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); verify(spiedKvs, times(1)).deleteAllTimestamps(any(TableReference.class), anyMap(), eq(false)); }
@Test public void conservativeSweepCallsFollower() { enqueueWriteCommitted(TABLE_CONS, LOW_TS); enqueueWriteCommitted(TABLE_CONS, LOW_TS2); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); ArgumentCaptor<Set> captor = ArgumentCaptor.forClass(Set.class); verify(mockFollower, times(1)).run(eq(TABLE_CONS), captor.capture()); assertThat(Iterables.getOnlyElement(captor.getAllValues())).containsExactly(DEFAULT_CELL); }
@Test public void callingEnqueueAndSweepOnUninitializedSweeperThrows() { TargetedSweeper uninitializedSweeper = TargetedSweeper.createUninitializedForTest(null); assertThatThrownBy(() -> uninitializedSweeper.enqueue(ImmutableList.of())) .isInstanceOf(NotInitializedException.class) .hasMessageContaining("Targeted Sweeper"); assertThatThrownBy(() -> uninitializedSweeper.sweepNextBatch(ShardAndStrategy.conservative(0))) .isInstanceOf(NotInitializedException.class) .hasMessageContaining("Targeted Sweeper"); }
@Test public void thoroughSweepDeletesAllButLatestWithSingleDeleteAllTimestampsIncludingSentinels() { long lastWriteTs = TS_FINE_GRANULARITY - 1; for (long i = 1; i <= lastWriteTs; i++) { enqueueWriteCommitted(TABLE_THOR, i); } sweepQueue.sweepNextBatch(ShardAndStrategy.thorough(THOR_SHARD)); assertReadAtTimestampReturnsNothing(TABLE_THOR, lastWriteTs); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_THOR, lastWriteTs); verify(spiedKvs, times(1)).deleteAllTimestamps(any(TableReference.class), anyMap(), eq(true)); }
@Test public void sweepDisabledIsReportedInOutcome() { sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertThat(metricsManager).hasTargetedOutcomeEqualTo(SweepOutcome.NOTHING_TO_SWEEP, 1L); enabled = false; sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertThat(metricsManager).hasTargetedOutcomeEqualTo(SweepOutcome.DISABLED, 1L); }
private void writeValuesAroundSweepTimestampAndSweepAndCheck(long sweepTimestamp, int sweepIterations) { enqueueWriteCommitted(TABLE_CONS, sweepTimestamp - 10); enqueueWriteCommitted(TABLE_CONS, sweepTimestamp - 5); enqueueWriteCommitted(TABLE_CONS, sweepTimestamp + 5); IntStream.range(0, sweepIterations) .forEach(unused -> sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD))); assertReadAtTimestampReturnsSentinel(TABLE_CONS, sweepTimestamp - 5); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_CONS, sweepTimestamp - 5); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_CONS, sweepTimestamp + 5); }
@Test public void sweepProgressesToJustBeforeSweepTsWhenNothingToSweep() { sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertProgressUpdatedToTimestamp(getSweepTsCons() - 1L); }
@Test public void thoroughSweepDeletesExistingSentinel() { spiedKvs.addGarbageCollectionSentinelValues(TABLE_THOR, ImmutableList.of(DEFAULT_CELL)); assertReadAtTimestampReturnsSentinel(TABLE_THOR, 0L); enqueueWriteCommitted(TABLE_THOR, 10L); sweepQueue.sweepNextBatch(ShardAndStrategy.thorough(THOR_SHARD)); assertReadAtTimestampReturnsNothing(TABLE_THOR, 0L); }
@Test public void doesNotLeaveSentinelsIfTableDestroyed() { enqueueWriteCommitted(TABLE_CONS, 10); immutableTs = 11; unreadableTs = 11; spiedKvs.truncateTable(TABLE_CONS); assertThat(spiedKvs.getRange(TABLE_CONS, RangeRequest.all(), Long.MAX_VALUE)).isEmpty(); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertThat(spiedKvs.getRange(TABLE_CONS, RangeRequest.all(), Long.MAX_VALUE)).isEmpty(); }
@Test public void sweepProgressesToEndOfPartitionWhenFewValuesAndSweepTsLarge() { long writeTs = getSweepTsCons() - 3 * TS_FINE_GRANULARITY; enqueueWriteCommitted(TABLE_CONS, writeTs); enqueueWriteCommitted(TABLE_CONS, writeTs + 5); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertProgressUpdatedToTimestamp(maxTsForFinePartition(tsPartitionFine(writeTs))); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertProgressUpdatedToTimestamp(getSweepTsCons() - 1L); }
@Test public void conservativeSweepAddsSentinelAndLeavesSingleValue() { enqueueWriteCommitted(TABLE_CONS, LOW_TS); assertReadAtTimestampReturnsNothing(TABLE_CONS, LOW_TS); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertReadAtTimestampReturnsSentinel(TABLE_CONS, LOW_TS); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_CONS, LOW_TS); }
@Test public void sweepDeletesValuesWrittenOnPreCommitConditionFailure() { useOneSweepQueueShard(); long startTs = putWriteAndFailOnPreCommitConditionReturningStartTimestamp(SINGLE_WRITE); serializableTxManager.setUnreadableTimestamp(startTs + 1); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(0)); assertNoEntryForCellInKvs(TABLE_CONS, TEST_CELL); }
@Test public void sweepWithNoCandidatesBeforeSweepTimestampReportsNothingToSweep() { enqueueWriteCommitted(TABLE_CONS, getSweepTsCons()); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertThat(metricsManager).hasTargetedOutcomeEqualTo(SweepOutcome.NOTHING_TO_SWEEP, 1L); }
@Test public void thoroughSweepDoesNotAddSentinelAndLeavesSingleValue() { enqueueWriteCommitted(TABLE_THOR, LOW_TS); assertReadAtTimestampReturnsNothing(TABLE_THOR, LOW_TS); sweepQueue.sweepNextBatch(ShardAndStrategy.thorough(THOR_SHARD)); assertReadAtTimestampReturnsNothing(TABLE_THOR, LOW_TS); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_THOR, LOW_TS); }
@Test public void sweepThrowsAwayWritesForDroppedTables() { useOneSweepQueueShard(); writeInTransactionAndGetStartTimestamp(SINGLE_WRITE); Long startTimestamp = writeInTransactionAndGetStartTimestamp(SINGLE_WRITE); keyValueService.dropTable(TABLE_CONS); serializableTxManager.setUnreadableTimestamp(startTimestamp + 1); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(0)); }
@Test public void thoroughSweepDeletesLowerValue() { enqueueWriteCommitted(TABLE_THOR, LOW_TS); enqueueWriteCommitted(TABLE_THOR, LOW_TS2); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_THOR, LOW_TS); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_THOR, LOW_TS2); sweepQueue.sweepNextBatch(ShardAndStrategy.thorough(THOR_SHARD)); assertReadAtTimestampReturnsNothing(TABLE_THOR, LOW_TS + 1); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_THOR, LOW_TS2); }
@Test public void conservativeSweepDeletesLowerValue() { enqueueWriteCommitted(TABLE_CONS, LOW_TS); enqueueWriteCommitted(TABLE_CONS, LOW_TS2); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_CONS, LOW_TS); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_CONS, LOW_TS2); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertReadAtTimestampReturnsSentinel(TABLE_CONS, LOW_TS + 1); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_CONS, LOW_TS2); }
@Test public void sweepDeletesWritesWhenTombstoneHasHigherTimestamp() { enqueueWriteCommitted(TABLE_CONS, LOW_TS); enqueueTombstone(TABLE_CONS, LOW_TS2); assertTestValueEnqueuedAtGivenTimestampStillPresent(TABLE_CONS, LOW_TS); assertReadAtTimestampReturnsTombstoneAtTimestamp(TABLE_CONS, LOW_TS2 + 1, LOW_TS2); sweepQueue.sweepNextBatch(ShardAndStrategy.conservative(CONS_SHARD)); assertReadAtTimestampReturnsSentinel(TABLE_CONS, LOW_TS + 1); assertReadAtTimestampReturnsTombstoneAtTimestamp(TABLE_CONS, LOW_TS2 + 1, LOW_TS2); }
@Test public void thoroughSweepDeletesTombstoneIfLatestWrite() { enqueueTombstone(TABLE_THOR, LOW_TS); enqueueTombstone(TABLE_THOR, LOW_TS2); assertReadAtTimestampReturnsTombstoneAtTimestamp(TABLE_THOR, LOW_TS + 1, LOW_TS); assertReadAtTimestampReturnsTombstoneAtTimestamp(TABLE_THOR, LOW_TS2 + 1, LOW_TS2); sweepQueue.sweepNextBatch(ShardAndStrategy.thorough(THOR_SHARD)); assertReadAtTimestampReturnsNothing(TABLE_THOR, LOW_TS + 1); assertReadAtTimestampReturnsNothing(TABLE_THOR, LOW_TS2 + 1); }