Class: Cql::TimeUuid::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/cql/time_uuid.rb

Overview

A UUID version 1, variant 1 generator. It can generate a sequence of UUIDs with reasonable uniqueness guarantees:

  • The clock ID and node ID components are set to random numbers when the generator is created.

  • If two calls to #next happen within the time afforded by the system clock resolution a counter is incremented and added to the time component.

  • If the clock moves backwards the clock ID is reset to a new random number.

Instances of this class are absolutely not threadsafe. You should never share instances between threads.

Instance Method Summary collapse

Constructor Details

#initialize(node_id = nil, clock_id = nil, clock = Time) ⇒ Generator

Create a new UUID generator.

Parameters:

  • node_id (Integer) (defaults to: nil)

    an alternate node ID (defaults to a random number)

  • clock_id (Integer) (defaults to: nil)

    an alternate clock ID (defaults to a random number)



43
44
45
46
47
# File 'lib/cql/time_uuid.rb', line 43

def initialize(node_id=nil, clock_id=nil, clock=Time)
  @node_id = node_id || (rand(2**47) | 0x010000000000)
  @clock_id = clock_id || rand(2**16)
  @clock = clock
end

Instance Method Details

#from_time(time, jitter = rand(2**16)) ⇒ Cql::TimeUuid

Returns a new UUID with a time component based on the specified Time. A piece of jitter is added to ensure that multiple calls with the same time do not generate the same UUID (if you want determinism you can set the second parameter to zero).

Parameters:

  • time (Time)

    the time to encode into the UUID

  • jitter (Integer) (defaults to: rand(2**16))

    a number of microseconds to add to the time to make it unique

Returns:



77
78
79
80
# File 'lib/cql/time_uuid.rb', line 77

def from_time(time, jitter=rand(2**16))
  usecs = time.to_i * 1_000_000 + time.usec + jitter
  from_usecs(usecs)
end

#from_usecs(usecs) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/cql/time_uuid.rb', line 83

def from_usecs(usecs)
  t = GREGORIAN_OFFSET + usecs * 10
  time_hi  = t & 0x0fff000000000000
  time_mid = t & 0x0000ffff00000000
  time_low = t & 0x00000000ffffffff
  version = 1
  clock_id = @clock_id & 0x3fff
  node_id = @node_id & 0xffffffffffff
  variant = 0x8000
  n = (time_low << 96) | (time_mid << 48) | (time_hi << 16)
  n |= version << 76
  n |= (clock_id | variant) << 48
  n |= node_id
  TimeUuid.new(n)
end

#nextCql::TimeUuid

Returns a new UUID with a time component that is the current time.

Returns:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/cql/time_uuid.rb', line 53

def next
  now = @clock.now
  usecs = now.to_i * 1_000_000 + now.usec
  if @last_usecs && @last_usecs - @sequence <= usecs && usecs <= @last_usecs
    @sequence += 1
  elsif @last_usecs && @last_usecs > usecs
    @sequence = 0
    @clock_id = rand(2**16)
  else
    @sequence = 0
  end
  @last_usecs = usecs + @sequence
  from_usecs(@last_usecs)
end