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
update UUIDv7 implementation with RFC Draft Rev 03 spec #99
Conversation
f4883ec
to
c5459d3
Compare
I checked with gophers slack, @theckman seems to be in a situation where he can't do reviews... |
@cameracker |
generator.go
Outdated
return Nil, err | ||
} | ||
|
||
tn := g.epochFunc() | ||
ms := uint64(tn.Unix())*1e3 + uint64(tn.Nanosecond())/1e6 |
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.
Can we simplify this by just doing UnixMilli()?
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, it seems to be simpler to use UnixMilli() here!
The original code was receiving and processing sec and nanosec for flexibility, and I was writing the same way without thinking about it in detail.
Lines 376 to 384 in edd511b
sec, nano, seq, err := g.getV7ClockSequence(MillisecondPrecision) | |
if err != nil { | |
return Nil, err | |
} | |
msec := (nano / 1000000) & 0xfff | |
d := (sec << 28) // set unixts field | |
d |= (msec << 16) // set msec field |
Since we no longer need to worry about timestamp accuracy flexibility, it looks like we can use UnixMili().
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.
Fixed to use UnixMilli() in this commit.
5279295
u[2] = byte(ms >> 24) | ||
u[3] = byte(ms >> 16) | ||
u[4] = byte(ms >> 8) | ||
u[5] = byte(ms) |
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.
Do you think we benefit any from using the binary.BigEndian.PutUint32
interface that we use for the v6? As written makes sense given the lack of a PutUint48 to cover the size of the time in milliseconds..
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.
As you commented, I wrote this code because PutUint48 is not supported. v6 may have similar conditions as far as the specification is concerned.
However, there is a slight difference in v6.
The v6 specification specifies 32bit time_high , 16bit time_mid, 16bit time_low_and_version separately, which may have the effect of expressing the layout more explicitly.
(v7 is specified in the specification as a single field, unix_ts_ms, so I have taken the approach described in the code.)
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.
Can we get the build to run?
I see the passing build in the upstream repo, but would you mind rebasing to get the tests to run on two latest versions of go? The comments I left are questions, willing to merge with no changes but wanted to at least ask.
Currently, UUIDv6 and UUIDv7 implementations follow RFC draft rev 02 [1]. However, it has already been updated by RFC draft rev 03 [2] in March 2022. Rev3 updates v6 and v7 and v8 specifications, but the v6 changes seem to have no impact on implementation. Therefore, v6 and (unimplemented) v8 are not affected, so only the UUIDv7 implementation will be updated. [1] https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-02 [2] https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03
db76638
to
5279295
Compare
@cameracker |
Thank you so much for the submission @convto :) It's nice to have the WIP versions of the new uuid features in the library. Thanks for keeping them up to date 👍 |
replace the gofrs uuid lib as it broke support for old versions of go in a recent commit (gofrs/uuid#99) and has no mechanism for version control
Currently, UUIDv6 and UUIDv7 implementations follow RFC draft rev 02 [1].
However, it has already been updated by RFC draft rev 03 [2] in March 2022.
Rev3 updates v6 and v7 and v8 specifications, but the v6 changes seem to
have no impact on implementation. Therefore, v6 and (unimplemented) v8 are
not affected, so only the UUIDv7 implementation will be updated.
[1] https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-02
[2] https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03
In rev 03, complex sequences and variable precision timestamps have been removed from the specification.
The implementation is now simple and lock-free. It looks good.
This PR has breaking changes to the signature of the exported function
NewV7()
andGen.NewV7()
,but this does not seem to need consideration. I have referenced the following comment.
uuid/generator.go
Lines 92 to 97 in 028e840