The Clock That Ran Backwards — Java Bug Hunt
Inspired by Twitter's Snowflake ID generator — and the NTP clock-rollback duplicates it explicitly guards against.
- Language: Java
- Layer: Database
- Difficulty: Hard
- Concepts: IDs, Clocks
- Modelled on: Twitter Snowflake
- Visible tests: a new tick resets the sequence; the same tick increments the sequence; a backwards clock is refused
- Reward: 50 XP for a complete fix
Briefing
Inspired by Twitter's Snowflake ID generator — and the NTP clock-rollback duplicates it explicitly guards against. IDs are (timestamp << 12) | sequence and must be strictly increasing; if the wall clock ever runs backwards, the generator must refuse rather than mint colliding IDs.
IdGen.java currently trusts the clock and never resets the sequence.
Bug report
BUG-SNOW · Priority: Critical · Reported by: storage
next(lastTimestamp, lastSeq, now):
- now < lastTimestamp -> throw (clock moved backwards!)
- now == lastTimestamp -> same tick: sequence + 1
- now > lastTimestamp -> new tick: sequence resets to 0
- returns id = now * 4096 + seq
Observed: duplicate IDs after an NTP correction, and sequences that never reset — overflowing the 12-bit field within a busy second.
Logs
[idgen] now=1699999999 < last=1700000042 -> id went BACKWARDS
[db] duplicate key: 6963200172032The code as shipped
IdGen.java (editable)
class IdGen {
// Returns { id, seqUsed } packed as long[2].
static long[] next(long lastTimestamp, long lastSeq, long now) {
long seq = lastSeq + 1;
long id = now * 4096 + seq;
return new long[] { id, seq };
}
}Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Java bug hunts.