@Test public void throwsIfModulusIsNegative() { assertThatThrownBy(() -> TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 3, -8)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Modulus should be positive, but found -8."); assertThatThrownBy(() -> TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 4, -2)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Modulus should be positive, but found -2."); }
@Test public void throwsIfModulusIsZero() { assertThatThrownBy(() -> TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 0, 0)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Modulus should be positive, but found 0."); }
@Test public void throwsIfResidueEqualsOrExceedsModulus() { assertThatThrownBy(() -> TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 2, 2)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("Absolute value of residue 2 equals or exceeds modulus 2 - no solutions"); assertThatThrownBy(() -> TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, -3, 2)) .isInstanceOf(IllegalArgumentException.class) .hasMessageMatching("Absolute value of residue -3 equals or exceeds modulus 2 - no solutions"); }
@Override public TimestampAndPartition getFreshTimestampForClient(UUID clientIdentifier) { while (true) { TimestampRange timestampRange = delegate.getFreshTimestamps(NUM_PARTITIONS); int targetResidue = allocator.getRelevantModuli(clientIdentifier).iterator().next(); OptionalLong relevantTimestamp = TimestampRanges.getTimestampMatchingModulus( timestampRange, targetResidue, NUM_PARTITIONS); if (relevantTimestamp.isPresent()) { return TimestampAndPartition.of(relevantTimestamp.getAsLong(), targetResidue); } // Not a bug - getFreshTimestamps is permitted to return less than the number of timestamps asked for, // so this case is possible. log.info("The timestamp range we received from the underlying timestamp service - {} -" + " did not contain a value with residue {} modulo {}. We will try again." + " This is not a bug; but if it happens excessively frequently, please contact support.", SafeArg.of("timestampRange", timestampRange), SafeArg.of("targetResidue", targetResidue), SafeArg.of("modulus", NUM_PARTITIONS)); } }
@Test public void canHandleNegativeResidues() { assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, -7, 10)) .isPresent() .hasValue(SEVENTY_THREE); assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, -5, 10)) .isPresent() .hasValue(75); }
@Test public void canGetTimestampsFromRangeInTheMiddle() { assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 7, 10)) .isPresent() .hasValue(77L); assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 8, 10)) .isPresent() .hasValue(78L); }
@Test public void returnsAbsentIfTimestampRangeDoesNotContainAnyValuesMatchingModulus() { TimestampRange oneTimestamp = TimestampRange.createInclusiveRange(77, 77); assertThat(TimestampRanges.getTimestampMatchingModulus(oneTimestamp, 6, 10)).isNotPresent(); } }
@Test public void canGetTimestampFromRangeIfItIsTheLowerBound() { assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 3, 10)) .isPresent() .hasValue(SEVENTY_THREE); }
@Test public void canGetTimestampFromRangeIfItIsTheUpperBound() { assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 2, 10)) .isPresent() .hasValue(EIGHTY_TWO); }
@Test public void canHandleMultipleValidMatches() { assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 1, 2)) .isPresent() .satisfies(optionalLong -> { long value = optionalLong.getAsLong(); assertThat(value).isIn(73L, 75L, 77L, 79L, 81L); }); assertThat(TimestampRanges.getTimestampMatchingModulus(SEVENTY_THREE_TO_EIGHTY_TWO, 0, 2)) .isPresent() .satisfies(optionalLong -> { long value = optionalLong.getAsLong(); assertThat(value).isIn(74L, 76L, 78L, 80L, 82L); }); }
@Override public TimestampAndPartition getFreshTimestampForClient(UUID clientIdentifier) { while (true) { TimestampRange timestampRange = delegate.getFreshTimestamps(NUM_PARTITIONS); int targetResidue = allocator.getRelevantModuli(clientIdentifier).iterator().next(); OptionalLong relevantTimestamp = TimestampRanges.getTimestampMatchingModulus( timestampRange, targetResidue, NUM_PARTITIONS); if (relevantTimestamp.isPresent()) { return TimestampAndPartition.of(relevantTimestamp.getAsLong(), targetResidue); } // Not a bug - getFreshTimestamps is permitted to return less than the number of timestamps asked for, // so this case is possible. log.info("The timestamp range we received from the underlying timestamp service - {} -" + " did not contain a value with residue {} modulo {}. We will try again." + " This is not a bug; but if it happens excessively frequently, please contact support.", SafeArg.of("timestampRange", timestampRange), SafeArg.of("targetResidue", targetResidue), SafeArg.of("modulus", NUM_PARTITIONS)); } }