class Uuidx::Version7

UUID Version 7 defined by the RFC 4122 BIS-01 Draft.

To construct a new UUID v7 value create a generator, then use generate.

g = Uuidx::Version7.new
g.generate # => "01863d24-6d1e-78ba-92ee-6e80c79c4e28"

The implementation will cache 640 bytes of random data from SecureRandom to facilitate faster construction.

If you have need to make sure that the clock resolution is sufficient for the v7 specification you can call ::verify_clock_resolution! and handle the ClockResolutionError as you see fit.

begin
  Uuidx::Version7.verify_clock_resolution!
rescue Uuidx::ClockResolutionError
  # ...
end

The necessary clock resolution for v6 is 1ms.

A Note on Clock Timings

To combat clock drift, leap-second smearing, and other clock value changes that can appear without requiring additional compute cost this implementation relies on secure random data to have sufficient variation such that all generated UUIDs within 1ms have a low probability of collision.

For a 0.001% chance of collision, the 74 bits of random data will require between 6.1×10^6 and 4.0×10^11 UUIDs to be generated in 1ms.

Public Class Methods

new() click to toggle source

Construct a UUID v7 generator.

# File lib/uuidx/version7.rb, line 45
def initialize
  @pool = []
end
verify_clock_resolution!() click to toggle source

Verify that the clock resolution is capable of 1ms resolution.

Raises ClockResolutionError when the clock resolution is insufficient.

# File lib/uuidx/version7.rb, line 62
def self.verify_clock_resolution!
  ms_res = Process.clock_getres(Process::CLOCK_REALTIME, :millisecond)
  raise ClockResolutionError, "Detected #{ms_res}ms resolution, need <= 1ms" if ms_res > 1

  true
end

Public Instance Methods

generate() click to toggle source

Construct a UUID v7 value.

# File lib/uuidx/version7.rb, line 50
def generate
  @pool = SecureRandom.bytes(NEEDED_BYTES).unpack(UNPACK_FORMAT) if @pool.empty?
  a, b = @pool.pop(2)
  ts = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond) & TS_MASK
  high = (ts << TS_SHIFT) | (a & RAND_A_MASK)

  Uuidx.format(VERSION_VARIANT | (high << HIGH_SHIFT) | (b & RAND_B_MASK))
end