You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If the clock is set backwards, or might have been set backwards
(e.g., while the system was powered off), and the UUID generator can
not be sure that no UUIDs were generated with timestamps larger than
the value to which the clock was set, then the clock sequence has to
be changed. If the previous value of the clock sequence is known, it
can just be incremented; otherwise it should be set to a random or
high-quality pseudo-random value.
If the state was available, but the saved timestamp is later than
the current timestamp, increment the clock sequence value.
However, in get_v1/1, the clock sequence is never altered. Incrementing the clock is implemented in increment/1, but increment/1 is never called during uuid v1 generation.
In case of a new timestamp being older than the last timestamp instead of adjusting the clock sequence (as intended by RFC 4122) the timestamp itself is altered in timestamp/2, at least for erlang_timestamp. It is obviously arguable what the "correct" timestamp is in such cases but in my opinion messing with the timestamp is not the correct answer, thats exactly what the clock sequence is for.
An example where messing with the timestamp is problematic: This library is used by the Erlang Cassandra driver cqerl. Cassandra in turn relies on extracting the time portion of the uuid v1 (timeuuid in Cassandra) as timestamp.
Both of the these behaviours do not seem to be correct in the sense of RFC 4122. Am I missing something in your implementation? Do I misunderstand the standard?
The text was updated successfully, but these errors were encountered:
@jvf Incrementing the clock sequence is something that must be done by source code that is aware of the clock going backwards, using a function call to uuid:increment/1 and that source code would need to be outside of the uuid source code to be aware of the clock going backwards (in a meaningful way).
The v1 UUIDs are created with a state variable that is first created with the uuid:new/2 function. In the Options variable, the uuid:new/2 function takes a timestamp_type value which defaults to erlang. This option represents the default behavior of the deprecated erlang:now/0 function which only provided incrementing time values, so the timestamp_type == erlang code path in the uuid:get_v1/1 function call will ensure the time is incrementing (by single microseconds if the clock moved backwards, using erlang:system_time(microsecond) (as shown here)). This is safe to use with the Multi-Time Warp Mode if you have a ntpd setup to keep the machine's time in-sync, which is a typical requirement for server deployments.
If instead you wanted the time to move backwards/forwards without the uuid:get_v1/1 function doing anything to alter the time value, it is possible to use timestamp_type == warp. You would then need to have an Erlang process that called erlang:monitor/2 with time_offset and use that event to call uuid:increment/1. However, I find it better to have the ordering guarantee with timestamp_type == erlang and avoid the need to call uuid:increment/1 while depending on ntpd to handle minor time changes.
You can also do timestamp_type == os but that basically means you don't care about the time changing (by getting the time directly from the hardware), so you probably wouldn't care about the uuid:increment/1 function if you were using that.
RFC 4122 states:
RFC 4122 also states in 4.2.1. Basic Algorithm:
However, in
get_v1/1
, the clock sequence is never altered. Incrementing the clock is implemented inincrement/1
, butincrement/1
is never called during uuid v1 generation.In case of a new timestamp being older than the last timestamp instead of adjusting the clock sequence (as intended by RFC 4122) the timestamp itself is altered in
timestamp/2
, at least forerlang_timestamp
. It is obviously arguable what the "correct" timestamp is in such cases but in my opinion messing with the timestamp is not the correct answer, thats exactly what the clock sequence is for.An example where messing with the timestamp is problematic: This library is used by the Erlang Cassandra driver
cqerl
. Cassandra in turn relies on extracting the time portion of the uuid v1 (timeuuid
in Cassandra) as timestamp.Both of the these behaviours do not seem to be correct in the sense of RFC 4122. Am I missing something in your implementation? Do I misunderstand the standard?
The text was updated successfully, but these errors were encountered: