feat: PAT improvements (UUIDv7 for random + hashing) - #2048
Conversation
Introduce faster `java-uuid-generator` library from Tatu. For now just as "drop in replacement", but we should also do cluster-wide-sync using Redis maybe?
This comment was marked as outdated.
This comment was marked as outdated.
|
Let me verify the current JUG API since I want to give you the right generator methods.The short version: the answer depends entirely on which UUID version you pick, and the good news is the modern choice makes cross-pod coordination a non-issue. If you use v4 (random) or v7, you don't need to coordinate anything between pods. Both draw the bulk of their bits from a CSPRNG, so uniqueness comes from entropy rather than from any per-node identifier. For v7 the layout is a 48-bit millisecond timestamp plus ~74 bits of randomness. Two pods generating in the very same millisecond would both have to draw the same 74-bit value to collide — the birthday bound puts that at roughly 2³⁷ UUIDs within a single millisecond before collision probability becomes meaningful. That's not a scenario you'll hit, and it holds regardless of how many pods you run or how you schedule them. No downward API, no node assignment, nothing. Given your stack (Spring Boot, JPA, TimescaleDB), I'd default to v7 specifically. It's time-sortable (lexicographic order matches creation order), which keeps B-tree index inserts near the right edge instead of scattering them like v4 does — much friendlier as a primary key, and it plays nicely with time-partitioned data. In JUG that's: // v7 — recommended default, no per-pod setup needed
private static final NoArgGenerator UUIDS = Generators.timeBasedEpochGenerator();
UUID id = UUIDS.generate();There's also The only case where multi-pod coordination actually matters is v1 or v6 (time-based with a node identifier). These derive part of the value from the host's MAC address / node ID plus timestamp plus clock sequence. In containers the MAC is often randomly assigned or, worse, could repeat across pods depending on your CNI, and JUG falls back to a random "dummy" address if it can't read a real one. Collisions there require same node ID + same 100ns tick + same clock sequence — unlikely, but the whole design assumes the node ID is genuinely unique, so you'd want to guarantee it rather than hope. If you have a reason to use v6 (say you want time-ordering and the v1-style structure), inject a stable per-pod identifier via the downward API and hand it to JUG as the ethernet address: env:
- name: POD_UID
valueFrom:
fieldRef:
fieldPath: metadata.uid// derive a 48-bit node id from the pod UID, set the multicast bit
// so it can never collide with a real hardware MAC
byte[] node = deriveFrom(System.getenv("POD_UID")); // hash -> 6 bytes
node[0] |= 0x01;
EthernetAddress addr = new EthernetAddress(node);
UUID id = Generators.timeBasedReorderedGenerator(addr).generate(); // v6Pod UID is better than pod name or IP here — names collide across namespaces and restarts, and pod IPs get recycled, whereas the UID is unique for the lifetime of that object. Setting the multicast bit (the So my recommendation: go v7 with One aside — for v4 you don't even need JUG, since |
This comment was marked as outdated.
This comment was marked as outdated.
Hash token values, also PAT table got version column that is 0 for existing tokens, and current version is 1. "On the fly" upgrade added but also a job. Changes: * token config got hashAlg + salt * token table got version smallint field (initialized to 0 on migration) * new job upgrades token (replaces value with hash(value + salt) and sets version = 1) * use token upgrade on the fly if (needed) * tests reworked to use less mocks
Changes: