Conversation
| } | ||
|
|
||
| @Test | ||
| public void generateUuidV7_hasVersionAndVariant() { |
There was a problem hiding this comment.
nit: we don't use _ for method names
| * 2-bit variant (RFC 4122, 0b10) - 62-bit random (rand_b) | ||
| */ | ||
| public static String generateUuidV7() { | ||
| long epochMs = System.currentTimeMillis() & 0xFFFFFFFFFFFFL; // 48 bits |
There was a problem hiding this comment.
I haven't reviewed this yet but just wanted to link how the JDK generates a UUIDv7 in JDK26: openjdk/jdk@642ba4c
There was a problem hiding this comment.
Thanks for the pointer! I didn’t realize JDK 26 includes UUIDv7. I’ll compare my implementation with UUID.ofEpochMillis, and align as needed.
There was a problem hiding this comment.
I compared with JDK 26’s UUID.ofEpochMillis and our layout matches (48‑bit timestamp, version 7 nibble, RFC 4122 variant, 12+62 random bits). I’d like to keep a no‑arg generateUuidV7() to mirror UUID.randomUUID() and avoid exposing timestamps; since callers need a header value, it returns String. I’ll align by using SecureRandom and adding a 48‑bit range check. I won’t copy JDK code (licensing), but the behavior is equivalent. The test is also the same: verify version() == 7 and variant()==2.
| private static final Joiner NAMESPACE_ESCAPED_JOINER = Joiner.on(NAMESPACE_ESCAPED_SEPARATOR); | ||
| private static final Splitter NAMESPACE_ESCAPED_SPLITTER = | ||
| Splitter.on(NAMESPACE_ESCAPED_SEPARATOR); | ||
| private static final SecureRandom SECURE_RANDOM = new SecureRandom(); |
There was a problem hiding this comment.
new SecureRandom() is relatively expensive; one shared instance is thread‑safe and sufficient.
|
I wonder if this can go to a more common package (maybe a dedicated |
singhpk234
left a comment
There was a problem hiding this comment.
LGTM, thanks @huaxingao !
| if ((epochMs >>> 48) != 0) { | ||
| throw new IllegalArgumentException("timestamp does not fit within 48 bits: " + epochMs); | ||
| } |
There was a problem hiding this comment.
nit: We could use checkArgument method instead:
Preconditions.checkArgument(
(epochMs >>> 48) == 0, "timestamp does not fit within 48 bits: %s", epochMs);| public static String generateUuidV7() { | ||
| long epochMs = System.currentTimeMillis(); | ||
| Preconditions.checkArgument( | ||
| (epochMs >>> 48) == 0, "timestamp does not fit within 48 bits: %s", epochMs); |
There was a problem hiding this comment.
maybe this should be an IllegalStateException, since the user can't really provide an argument here and we're throwing a IAE? Also I would probably update the error msg to align with the rest of the codebase to something like Invalid timestamp: does not fit within 48 bits: ...
| * <p>Layout: - 48-bit Unix epoch milliseconds - 4-bit version (0b0111) - 12-bit random (rand_a) - | ||
| * 2-bit variant (RFC 4122, 0b10) - 62-bit random (rand_b) | ||
| */ | ||
| public static String generateUuidV7() { |
There was a problem hiding this comment.
How about returning UUID instead of String? then the caller can call toString if necessary.
There was a problem hiding this comment.
Changed the return type to UUID.
| } | ||
|
|
||
| /** | ||
| * Generate a RFC 9562 UUIDv7 string. |
There was a problem hiding this comment.
The returned type isn't string anymore.
| * Generate a RFC 9562 UUIDv7 string. | |
| * Generate a RFC 9562 UUIDv7. |
### Why are the changes needed? https://datatracker.ietf.org/doc/html/rfc9562#name-uuid-version-7 https://uuidv7.org/ > The Key Benefits of UUIDv7 UUIDv7 is rapidly gaining traction for various use cases across many industries. Here are some of the primary benefits: > > 1. Time-Ordered and Sortable: UUIDv7 encodes the time of creation as part of the identifier, making it naturally sortable. This is especially valuable for systems where data needs to be ordered by time without needing an additional timestamp field. > ... I think it's very useful - e.g., use UUIDv7 as session ID, then we can infer the session creation time from the UUID itself, or use UUIDv7 as a staging dir name, then we can easily clean dangling staging folders (for example, created 3 months ago) with a prefix. Implementation is inspired by apache/iceberg#14700 ### How was this patch tested? New UTs are added. ### Was this patch authored or co-authored using generative AI tooling? No. Closes #7277 from pan3793/uuidv7. Closes #7277 1dc1801 [Cheng Pan] style 3c7d3c5 [Cheng Pan] Add UUID v7 generator Authored-by: Cheng Pan <chengpan@apache.org> Signed-off-by: Cheng Pan <chengpan@apache.org>
This is the 2nd PR for Idempotency Key. This PR adds a UUIDv7 generator to REST Util.
First PR: Add idempotency-key-lifetime to ConfigResponse
Follow-ups (separate PRs)