Skip to content
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

Add uuids v6, v7, and v8 draft #55

Merged
merged 8 commits into from
Jul 16, 2024

Conversation

mitch-kyle
Copy link
Contributor

Hello, I started working on this because I'm bored and have too much time on my hands. I just noticed you created a new branch for this feature. This is my WIP; I'm sure there are several mistakes but I wanted to share early to prevent duplicate effort. feel free to use any or none of it.

  • Add support for max, v6, v7, v8 uuids
  • Add helper functions for comparing the ordinality of multiple uuids

Draft RFC4122 ammendment
https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html

- Add support for max, v6, v7, v8 uuids
- Add helper functions for comparing the ordinality of multiple uuids

Draft RFC4122 ammendment
https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-04.html
[java.util UUID
Date]
[java.lang IllegalArgumentException]))
Date]))
Copy link
Contributor Author

@mitch-kyle mitch-kyle Jul 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just ran clojure-sort-ns after adding a some namespaces out of habit

@dco-lentz
Copy link
Collaborator

very nice. and thanks for the contributions, i'm going through them now.

One concern I have is confusing or conflating these new features with the adopted standard, given the (abandoned?) draft status of this IETF memo. Especially insofar as it disagrees with or updates some details of the existing RFC-4122. Do you have any links to any current news about the standardization process?

@mitch-kyle
Copy link
Contributor Author

mitch-kyle commented Jul 12, 2024

Oh good call, I guess this is published RFC https://datatracker.ietf.org/doc/html/rfc9562

Not sure why that old draft is so ubiquitous and this one so hard to find.

Some notes from reading it:

  • RFC designation and numbering is off in the comments.
  • Section 6.2: There are 3 methods for the v7 monotonic counter. I've opted for the first but the others could be implemented as well if desired.

src/clj_uuid.clj Outdated Show resolved Hide resolved
Copy link
Collaborator

@dco-lentz dco-lentz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

really nice job. i left a few thoughts/questions, but this looks pretty sound.

I can go head and merge this progress into my 1.2.0 branch? or I can hold off if you wanted to keep going on this PR. I'd say my goals from here:

  • double check the monotonic+random spec vs. implementation
  • ensure backward compatibility (esp. protocol names etc)
  • maybe take a look at the naming /shadowing
  • supplement / improve internal code documentation
  • supplement / improve external code documentation
  • more tests? (you did a nice job on that though)

src/clj_uuid.clj Outdated Show resolved Hide resolved
@@ -631,6 +658,35 @@ _(function)_ `squuid []`
> time (seconds since 12:00am January 1, 1970 UTC) with the most
> significant 32 bits of the UUID

_(function)_ `= [x]`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm normally a fan of concise syntax, but wondering if shadowing the clojure core numerical comparators is really the right thing to do here

@@ -180,9 +193,9 @@



(defprotocol UUIDRfc4122
(defprotocol UUIDRfc9562
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, you think that RFC9562 should just replace/reimplement RFC4122 protcol? I wonder if it might be feasible to have this new protocol extend/supplement the other, in order to eliminate breaking changes for current users

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The protocol is bound to it's old name in a var below; I was trying to avoid breaking changes while being precise with the name but if this breaks something then it should absolutely go back to the old name.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or something like that. I was actually thinking of breaking it into two protocols. Not that would make a difference in practice though. one difference (maybe) is if anyone has extended rfc4122UUID somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating two protocols is a fine option.

you're right, as is, implementers would have to define the new function in order to upgrade.

src/clj_uuid.clj Show resolved Hide resolved
@@ -396,16 +429,20 @@
(URI/create (to-urn-string uuid)))

(get-time-low ^long [uuid]
(bitmop/ldb #=(bitmop/mask 32 0)
(bit-shift-right (.getMostSignificantBits uuid) 32)))
(let [msb (.getMostSignificantBits uuid)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since these guys are special casing types under the hood, i wonder if it would help readability if I/we added some docstrings to these

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

documenting the differences in resolution between v1 and v6 wouldn't be a bad thing

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, i'm going to spend some time on some of this i always wanted this library to have good documentation, since UUIDs seem so poorly understood


(defn max
"Generates the maximum UUID, ffffffff-ffff-ffff-ffff-ffffffffffff."
^java.util.UUID
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know this is consistent withnull and the name of the thing is "max uuid". unfortunately as yet i don't have a better name.

Copy link
Contributor Author

@mitch-kyle mitch-kyle Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It matches the documentation and is consistent with the null function. But I am open to giving this a different name because we could conceivably add min and max functions for uuids. Maybe maximum?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i dunno. we're sort of painted into a corner with the nomenclature. in common lisp maybe it would be analogous to t -- true, the top type, opposite of nil? one idea anyway. maybe a bad one

Copy link
Contributor Author

@mitch-kyle mitch-kyle Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the name should follow from the RFC

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya fair point

src/clj_uuid.clj Outdated
guaranteed to be unique and thread-safe regardless of clock
precision or degree of concurrency. Creation of v6 UUID's does not
require any call to a cryptographic generator and can be
accomplished much more efficiently than v3, v4, v5, or squuid's. A
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't this then also be more efficient than v7?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, v7 could be added to this list. v7 is still preferred by the RFC because it's less guessable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i see, gotcha. that's good context I'll add, as well. I really want to also do some micro benchmarking and timing

(f y (first more)))
false))

(defn =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one idea regarding the >, =, etc shadowing. -- what if instead we added variable arity under the hood to uuid= and uuid> ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue is as far as I know, protocol functions can't have variadic arguments.
https://clojure.atlassian.net/browse/CLJ-888

shadowing core functions is matter of taste, I like it because clojure.core is a huge library and it takes all the good names :P. We see official clojure libraries like core.async override many core names.

Here's a video of Rich talking about how he loves namespaces because he got tired of coming up with new names: https://youtu.be/oyLBGkS5ICk?feature=shared&t=662

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, right, variadic protocol arguments. I see your point. Well, let me see if i can come up with alternative. otherwise, not the end of the world unless anyone :use s the namespace or :refer :all

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:refer :all is considered an anti-pattern for this reason. This is why I like clojure's use of namespaces over scheme's default use-module semantics




(deftest check-monotonic-unix-time-and-random-counter
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah the function is kind of a mouthful but at least it's specific :P I'm open to alternatives

@@ -324,9 +352,11 @@
"Return the unique URN URI associated with this UUID."))


;; For backwards compatibility
(def UUIDRfc4122 UUIDRfc9562)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should make the protocol name change backwards compatible but if I'm mistaken we should put the old protocol name back.

@mitch-kyle
Copy link
Contributor Author

I can go head and merge this progress into my 1.2.0 branch?

Absolutely, I don't think I have anything else to add to this PR.

I'll still be available to make or review changes if you need it.

@dco-lentz dco-lentz merged commit 8e57ecc into danlentz:53-v7-support Jul 16, 2024
@dco-lentz
Copy link
Collaborator

can we connect over email? i'd love to know more about what you're up to

@mitch-kyle
Copy link
Contributor Author

Sure, my email is mitch.tux@gmail.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants