regular maintenance
This commit is contained in:
parent
6641297be8
commit
d7a8333053
|
@ -170,7 +170,7 @@ public final class UlidFactory {
|
||||||
* @return {@link UlidFactory}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
static UlidFactory newMonotonicInstance(LongSupplier randomFunction, Clock clock) {
|
static UlidFactory newMonotonicInstance(LongSupplier randomFunction, Clock clock) {
|
||||||
return new UlidFactory(new MonotonicFunction(IRandom.newInstance(randomFunction)), clock);
|
return new UlidFactory(new MonotonicFunction(IRandom.newInstance(randomFunction), clock), clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -183,7 +183,7 @@ public final class UlidFactory {
|
||||||
* @return {@link UlidFactory}
|
* @return {@link UlidFactory}
|
||||||
*/
|
*/
|
||||||
static UlidFactory newMonotonicInstance(IntFunction<byte[]> randomFunction, Clock clock) {
|
static UlidFactory newMonotonicInstance(IntFunction<byte[]> randomFunction, Clock clock) {
|
||||||
return new UlidFactory(new MonotonicFunction(IRandom.newInstance(randomFunction)), clock);
|
return new UlidFactory(new MonotonicFunction(IRandom.newInstance(randomFunction), clock), clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******************************
|
// ******************************
|
||||||
|
@ -251,9 +251,13 @@ public final class UlidFactory {
|
||||||
protected static final int CLOCK_DRIFT_TOLERANCE = 10_000;
|
protected static final int CLOCK_DRIFT_TOLERANCE = 10_000;
|
||||||
|
|
||||||
public MonotonicFunction(IRandom random) {
|
public MonotonicFunction(IRandom random) {
|
||||||
|
this(random, Clock.systemUTC());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MonotonicFunction(IRandom random, Clock clock) {
|
||||||
this.random = random;
|
this.random = random;
|
||||||
// initialize internal state
|
// initialize internal state
|
||||||
this.lastUlid = new Ulid(0L, this.random.nextBytes(Ulid.RANDOM_BYTES));
|
this.lastUlid = new Ulid(clock.millis(), this.random.nextBytes(Ulid.RANDOM_BYTES));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -39,7 +39,8 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
|
|
||||||
long diff = UlidFactory.MonotonicFunction.CLOCK_DRIFT_TOLERANCE;
|
long diff = UlidFactory.MonotonicFunction.CLOCK_DRIFT_TOLERANCE;
|
||||||
long time = Instant.parse("2021-12-31T23:59:59.000Z").toEpochMilli();
|
long time = Instant.parse("2021-12-31T23:59:59.000Z").toEpochMilli();
|
||||||
long times[] = { time, time + 0, time + 1, time + 2, time + 3 - diff, time + 4 - diff, time + 5 };
|
long times[] = { /* init */ 0L, time + 0, time + 1, time + 2, time + 3, time + 4 - diff, time + 5 - diff,
|
||||||
|
time + 6 - diff };
|
||||||
|
|
||||||
Clock clock = new Clock() {
|
Clock clock = new Clock() {
|
||||||
private int i;
|
private int i;
|
||||||
|
@ -65,37 +66,63 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IntFunction<byte[]> randomSupplier = UlidFactory.ByteRandom.newRandomFunction(new Random());
|
LongSupplier randomFunction = () -> 0;
|
||||||
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
UlidFactory factory = UlidFactory.newMonotonicInstance(randomFunction, clock);
|
||||||
|
|
||||||
long ms1 = factory.create().getTime(); // time
|
Ulid ulid1 = factory.create();
|
||||||
long ms2 = factory.create().getTime(); // time + 0
|
Ulid ulid2 = factory.create();
|
||||||
long ms3 = factory.create().getTime(); // time + 1
|
Ulid ulid3 = factory.create();
|
||||||
long ms4 = factory.create().getTime(); // time + 2
|
Ulid ulid4 = factory.create();
|
||||||
long ms5 = factory.create().getTime(); // time + 3 - 10000 (CLOCK DRIFT)
|
Ulid ulid5 = factory.create();
|
||||||
long ms6 = factory.create().getTime(); // time + 4 - 10000 (CLOCK DRIFT)
|
Ulid ulid6 = factory.create();
|
||||||
long ms7 = factory.create().getTime(); // time + 5
|
Ulid ulid7 = factory.create();
|
||||||
assertEquals(ms1 + 0, ms2); // clock repeats.
|
|
||||||
assertEquals(ms1 + 1, ms3); // clock advanced.
|
long t1 = ulid1.getTime(); // time + 0
|
||||||
assertEquals(ms1 + 2, ms4); // clock advanced.
|
long t2 = ulid2.getTime(); // time + 1
|
||||||
assertEquals(ms1 + 2, ms5); // CLOCK DRIFT! DON'T MOVE BACKWARDS!
|
long t3 = ulid3.getTime(); // time + 2
|
||||||
assertEquals(ms1 + 2, ms6); // CLOCK DRIFT! DON'T MOVE BACKWARDS!
|
long t4 = ulid4.getTime(); // time + 3
|
||||||
assertEquals(ms1 + 5, ms7); // clock advanced.
|
long t5 = ulid5.getTime(); // time + 4 - 10000 (CLOCK DRIFT)
|
||||||
|
long t6 = ulid6.getTime(); // time + 5 - 10000
|
||||||
|
long t7 = ulid7.getTime(); // time + 6 - 10000
|
||||||
|
|
||||||
|
long r1 = ulid1.getLeastSignificantBits(); // time + 0
|
||||||
|
long r2 = ulid2.getLeastSignificantBits(); // time + 1
|
||||||
|
long r3 = ulid3.getLeastSignificantBits(); // time + 2
|
||||||
|
long r4 = ulid4.getLeastSignificantBits(); // time + 3
|
||||||
|
long r5 = ulid5.getLeastSignificantBits(); // time + 4 - 10000 (CLOCK REGRESSION)
|
||||||
|
long r6 = ulid6.getLeastSignificantBits(); // time + 5 - 10000
|
||||||
|
long r7 = ulid7.getLeastSignificantBits(); // time + 6 - 10000
|
||||||
|
|
||||||
|
assertEquals(time + 0, t1); // time + 0
|
||||||
|
assertEquals(time + 1, t2); // time + 1
|
||||||
|
assertEquals(time + 2, t3); // time + 2
|
||||||
|
assertEquals(time + 3, t4); // time + 3
|
||||||
|
assertEquals(time + 3, t5); // time + 4 - 10000 (CLOCK REGRESSION)
|
||||||
|
assertEquals(time + 3, t6); // time + 5 - 10000
|
||||||
|
assertEquals(time + 3, t7); // time + 5 - 10000
|
||||||
|
|
||||||
|
assertEquals(0, r1); // time + 0
|
||||||
|
assertEquals(0, r2); // time + 1
|
||||||
|
assertEquals(0, r3); // time + 2
|
||||||
|
assertEquals(0, r4); // time + 3
|
||||||
|
assertEquals(1, r5); // time + 4 - 10000 (CLOCK REGRESSION)
|
||||||
|
assertEquals(2, r6); // time + 5 - 10000
|
||||||
|
assertEquals(3, r7); // time + 5 - 10000
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMonotonicUlidAfterLeapSecond() {
|
public void testGetMonotonicUlidAfterLeapSecond() {
|
||||||
|
|
||||||
long second = Instant.parse("2021-12-31T23:59:59.000Z").getEpochSecond();
|
long time = Instant.parse("2021-12-31T23:59:59.000Z").toEpochMilli();
|
||||||
long leapSecond = second - 1; // simulate a leap second
|
long leap = time - 1000; // simulate a leap second
|
||||||
long times[] = { second, leapSecond };
|
long times[] = { time, leap };
|
||||||
|
|
||||||
Clock clock = new Clock() {
|
Clock clock = new Clock() {
|
||||||
private int i;
|
private int i;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long millis() {
|
public long millis() {
|
||||||
return times[i++ % times.length] * 1000;
|
return times[i++ % times.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -114,20 +141,31 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IntFunction<byte[]> randomSupplier = UlidFactory.ByteRandom.newRandomFunction(new Random());
|
LongSupplier randomFunction = () -> 0;
|
||||||
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
UlidFactory factory = UlidFactory.newMonotonicInstance(randomFunction, clock);
|
||||||
|
|
||||||
long ms1 = factory.create().getTime(); // second
|
Ulid ulid1 = factory.create();
|
||||||
long ms2 = factory.create().getTime(); // leap second
|
Ulid ulid2 = factory.create();
|
||||||
|
|
||||||
|
long t1 = ulid1.getTime();
|
||||||
|
long t2 = ulid2.getTime(); // leap second
|
||||||
|
|
||||||
|
long r1 = ulid1.getLeastSignificantBits();
|
||||||
|
long r2 = ulid2.getLeastSignificantBits(); // leap second
|
||||||
|
|
||||||
|
assertEquals(time, t1);
|
||||||
|
assertEquals(time, t2); // leap second
|
||||||
|
|
||||||
|
assertEquals(1, r1);
|
||||||
|
assertEquals(2, r2);
|
||||||
|
|
||||||
assertEquals(ms1, ms2); // LEAP SECOND! DON'T MOVE BACKWARDS!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMonotonicUlidAfterRandomBitsOverflowFollowedByTimeBitsIncrement() {
|
public void testGetMonotonicUlidAfterRandomBitsOverflowFollowedByTimeBitsIncrement() {
|
||||||
|
|
||||||
long time = Instant.parse("2021-12-31T23:59:59.999Z").toEpochMilli();
|
long time = Instant.parse("2021-12-31T23:59:59.999Z").toEpochMilli();
|
||||||
long times[] = { time, time, time + 1, time + 2 };
|
long times[] = { /* init */ 0L, time + 1, time + 2, time + 3, time, time, time };
|
||||||
|
|
||||||
Clock clock = new Clock() {
|
Clock clock = new Clock() {
|
||||||
private int i;
|
private int i;
|
||||||
|
@ -156,25 +194,35 @@ public class UlidFactoryMonotonicTest extends UlidFactoryTest {
|
||||||
LongSupplier randomSupplier = () -> 0xffffffffffffffffL;
|
LongSupplier randomSupplier = () -> 0xffffffffffffffffL;
|
||||||
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
UlidFactory factory = UlidFactory.newMonotonicInstance(randomSupplier, clock);
|
||||||
|
|
||||||
|
// System.out.println("time: " + time); // 1640995199999
|
||||||
|
|
||||||
Ulid ulid1 = factory.create();
|
Ulid ulid1 = factory.create();
|
||||||
Ulid ulid2 = factory.create(); // time bits should be incremented here
|
Ulid ulid2 = factory.create();
|
||||||
Ulid ulid3 = factory.create();
|
Ulid ulid3 = factory.create();
|
||||||
Ulid ulid4 = factory.create();
|
Ulid ulid4 = factory.create();
|
||||||
|
Ulid ulid5 = factory.create();
|
||||||
|
Ulid ulid6 = factory.create();
|
||||||
|
|
||||||
assertEquals(ulid1.getTime(), time);
|
assertEquals(time + 1, ulid1.getTime());
|
||||||
assertEquals(ulid2.getTime(), time + 1); // check if time bits increment occurred
|
assertEquals(time + 2, ulid2.getTime());
|
||||||
assertEquals(ulid3.getTime(), time + 1);
|
assertEquals(time + 3, ulid3.getTime());
|
||||||
assertEquals(ulid4.getTime(), time + 2);
|
assertEquals(time + 4, ulid4.getTime());
|
||||||
|
assertEquals(time + 4, ulid5.getTime());
|
||||||
|
assertEquals(time + 4, ulid6.getTime());
|
||||||
|
|
||||||
assertEquals(ulid1.getMostSignificantBits() & 0xffffL, 0xffffL);
|
assertEquals(0xffffL, ulid1.getMostSignificantBits() & 0xffffL);
|
||||||
assertEquals(ulid2.getMostSignificantBits() & 0xffffL, 0x0000L);
|
assertEquals(0xffffL, ulid2.getMostSignificantBits() & 0xffffL);
|
||||||
assertEquals(ulid3.getMostSignificantBits() & 0xffffL, 0x0000L);
|
assertEquals(0xffffL, ulid3.getMostSignificantBits() & 0xffffL);
|
||||||
assertEquals(ulid4.getMostSignificantBits() & 0xffffL, 0xffffL);
|
assertEquals(0x0000L, ulid4.getMostSignificantBits() & 0xffffL);
|
||||||
|
assertEquals(0x0000L, ulid5.getMostSignificantBits() & 0xffffL);
|
||||||
|
assertEquals(0x0000L, ulid6.getMostSignificantBits() & 0xffffL);
|
||||||
|
|
||||||
assertEquals(ulid1.getLeastSignificantBits(), 0xffffffffffffffffL);
|
assertEquals(0xffffffffffffffffL, ulid1.getLeastSignificantBits());
|
||||||
assertEquals(ulid2.getLeastSignificantBits(), 0x0000000000000000L);
|
assertEquals(0xffffffffffffffffL, ulid2.getLeastSignificantBits());
|
||||||
assertEquals(ulid3.getLeastSignificantBits(), 0x0000000000000001L);
|
assertEquals(0xffffffffffffffffL, ulid3.getLeastSignificantBits());
|
||||||
assertEquals(ulid4.getLeastSignificantBits(), 0xffffffffffffffffL);
|
assertEquals(0x0000000000000000L, ulid4.getLeastSignificantBits());
|
||||||
|
assertEquals(0x0000000000000001L, ulid5.getLeastSignificantBits());
|
||||||
|
assertEquals(0x0000000000000002L, ulid6.getLeastSignificantBits());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkOrdering(Ulid[] list) {
|
private void checkOrdering(Ulid[] list) {
|
||||||
|
|
Loading…
Reference in New Issue