-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HHH-18377 Support for uuid v6 and v7 generated ids #8719
base: main
Are you sure you want to change the base?
Conversation
5b0017a
to
066a676
Compare
How will it handle if a separate server generates the same id into the same database? Will it recreate a new ID automatically and try again? |
No. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a few comments about odd references to UUID#randomUUID()
. Let's clean those up.
Additionally, you write great detail about what each value generator does. But you do it on #generateUuid
. I'd prefer to see those on the class Javadoc, because...
Another thing we should do here is to add values for these into UuidGenerator.Style
. Its probably best to have these link to the class Javadoc for the corresponding value-generator.
hibernate-core/src/main/java/org/hibernate/id/uuid/UuidV6ValueGenerator.java
Outdated
Show resolved
Hide resolved
hibernate-core/src/main/java/org/hibernate/id/uuid/UuidV6ValueGenerator.java
Outdated
Show resolved
Hide resolved
hibernate-core/src/main/java/org/hibernate/id/uuid/UuidV7ValueGenerator.java
Outdated
Show resolved
Hide resolved
hibernate-core/src/main/java/org/hibernate/id/uuid/UuidV7ValueGenerator.java
Outdated
Show resolved
Hide resolved
5134d12
to
e44c59b
Compare
A few naming related points here...
I'll need to pull this locally to squash the commits before I apply. I can apply the name changes at that time if you prefer. Thanks again for the work on this! |
Changed both things.
I've squashed everything into two commits, one for implementation, other for test case. Hope that this is OK?
You're welcome. Happy if I can help. Not that I was too busy lately. |
In general, we like the test/impl split for the PR as it shows (1) what is addressed and (2) how it was addressed. When we apply them, though, we generally (not always) squash to one as it makes it easier to cherry-pick to other branches. This we won't be backporting, so its less important. Long story short, 2 commits is fine here. |
else if ( config.style() == VERSION_6 ) { | ||
return new UuidVersion6Strategy(); | ||
} | ||
else if ( config.style() == VERSION_7 ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would a switch case make sense?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You certainly could. Personally I don't see the benefit here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this will look any better than now ...
if ( config.algorithm() != UuidValueGenerator.class ) {
...
}
else {
switch (config.style()) {
...
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You won't need the else
since the first if statement returns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that is true, and was actually my fault from the first :)
It really could/should be:
if ( config != null ) {
if ( config.algorithm() != UuidValueGenerator.class ) {
// this block returns or throws an exception...
}
if ( config.style() == TIME ) {
return ...
}
if ( config.style() == VERSION_6 ) {
return UuidVersion6Strategy.INSTANCE;
}
if ( config.style() == VERSION_7 ) {
return UuidVersion7Strategy.INSTANCE;
}
}
return StandardRandomStrategy.INSTANCE;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or like
if(config == null) {
return StandardRandomStrategy.INSTANCE;
}
if(config.algorithm() != UuidValueGenerator.class) {
// throw or return logic
}
switch(config.style()) {
case TIME:
return ..
case VERSION_6:
return UuidVersion6Strategy.INSTANCE;
case VERSION_7:
return UuidVersion7Strategy.INSTANCE;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well no. You are missing what is effectively the AUTO, which also happens to be the config == null
case.
I'm not following the desire to add a switch just to add a switch. A switch with so few case options is unuseful imo. In fact, IntelliJ will even suggest this as a refactoring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well was trying to flatten the if statement and moved it up as a guard clause for the AUTO.
https://blog.codinghorror.com/flattening-arrow-code/
final long nanosPart = Math.round( ( currentTimestamp.getNano() % 1_000_000L ) * 0.004096 ); | ||
|
||
return new UUID( | ||
millis << 16 & 0xFFFF_FFFF_FFFF_0000L | 0x7000L | nanosPart & 0xFFFL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feel fine to ignore this comment, but would it make it more self documenting to save this mask to a constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wdyt @cigaly ?
Or at least some code comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would advise against code comments, as code comments tend to trend to lie as the project ages.
https://dev.to/ruben_alapont/magic-numbers-and-magic-strings-its-time-to-talk-about-it-ci2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor suggestions/requests. Let me know what you think. FWIW I left "suggested changes" in those places to make it easy to apply if you agree.
* <li>14 bits - the clock sequence, resets to 0 when timestamp changes. </li> | ||
* <li>48 bits - pseudorandom data to provide uniqueness.</li> | ||
* </ul> | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* | |
* | |
* @apiNote Version 6 is field-compatible with Version 1, with the time bits reordered for improved DB locality. | |
* |
*/ | ||
@Override | ||
public int getGeneratedVersion() { | ||
// UUIDv6 is a field-compatible version of UUIDv1, reordered for improved DB locality |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// UUIDv6 is a field-compatible version of UUIDv1, reordered for improved DB locality |
* @param session session | ||
* | ||
* @return UUID version 6 | ||
* @see UuidValueGenerator#generateUuid(SharedSessionContractImplementor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param session session | |
* | |
* @return UUID version 6 | |
* @see UuidValueGenerator#generateUuid(SharedSessionContractImplementor) | |
* Generates a Version 6 compliant {@linkplain UUID} value. | |
* | |
* @return A Version 6 compliant {@linkplain UUID}. | |
* | |
* @see UuidValueGenerator#generateUuid |
* <li>14 bits - counter to guarantee additional monotonicity, resets to 0 when timestamp changes. </li> | ||
* <li>48 bits - pseudorandom data to provide uniqueness.</li> | ||
* </ul> | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* | |
* | |
* @apiNote A Version 7 UUID features a time-ordered value field derived from the widely | |
* implemented and well known Unix Epoch timestamp source, the number of milliseconds | |
* since midnight 1 Jan 1970 UTC, leap seconds excluded. | |
* |
/* | ||
* UUIDv7 features a time-ordered value field derived from the widely implemented and well- | ||
* known Unix Epoch timestamp source, the number of milliseconds since midnight 1 Jan 1970 UTC, | ||
* leap seconds excluded. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* | |
* UUIDv7 features a time-ordered value field derived from the widely implemented and well- | |
* known Unix Epoch timestamp source, the number of milliseconds since midnight 1 Jan 1970 UTC, | |
* leap seconds excluded. | |
*/ |
* @param session session | ||
* | ||
* @return UUID version 7 | ||
* @see UuidValueGenerator#generateUuid(SharedSessionContractImplementor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* @param session session | |
* | |
* @return UUID version 7 | |
* @see UuidValueGenerator#generateUuid(SharedSessionContractImplementor) | |
* Generates a Version 7 {@linkplain UUID}. | |
* | |
* @return A Version version 7 {@linkplain UUID}. | |
* @see UuidValueGenerator#generateUuid(SharedSessionContractImplementor) |
Also, clearly we need to address the failures :) Execution failed for task ':hibernate-core:compileTestJava'.
> Compilation failed; see the compiler error output for details. |
One will expect that IDE should know to make basic refactoring things like renaming classes :-) |
Jira issue HHH-18377
Implementation of UUID Versioin 6 and UUID Version 7
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license
and can be relicensed under the terms of the LGPL v2.1 license in the future at the maintainers' discretion.
For more information on licensing, please check here.