Module: KOrderedFlake

Defined in:
lib/k_ordered_flake.rb,
lib/k_ordered_flake/version.rb,
lib/k_ordered_flake/exceptions.rb

Defined Under Namespace

Classes: CounterOverflowException, TimeDiscontinuityException

Constant Summary collapse

STATE =
Concurrent::Atom.new({
time: self.epoc,
identity: self.identity,
counter: 0 })
DIGITS =
('0'..'9').to_a + ('A'..'Z').to_a + ('a'..'z').to_a
VERSION =
"0.2.0"

Class Method Summary collapse

Class Method Details

.clock(state, time) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/k_ordered_flake.rb', line 38

def self.clock(state, time)
  s = state.clone
  if (time == s[:time])
    s[:counter] = (s[:counter] + 1) % 65536
    raise KOrderedFlake::CounterOverflowException.new("Too many increments per millisecond") if s[:counter] == 0
  elsif time > s[:time]
    s[:counter] = 0
    s[:time] = time
  else
    raise KOrderedFlake::TimeDiscontinuityException.new("Time may not run backwards #{state[:time]} > #{time}")
  end
  s
end

.encode(state) ⇒ Object



52
53
54
55
# File 'lib/k_ordered_flake.rb', line 52

def self.encode(state)
  x = (state[:time] << 64) + (state[:identity] << 16) + state[:counter]
  self.to_base_62(x)
end

.epocObject



10
11
12
# File 'lib/k_ordered_flake.rb', line 10

def self.epoc
  DateTime.now.strftime('%Q').to_i
end

.flakeObject



57
58
59
60
61
# File 'lib/k_ordered_flake.rb', line 57

def self.flake
  t = self.epoc
  sample = self::STATE.swap(t) { |s, t| self.clock(s, t) }
  self.encode(sample)
end

.identityObject



14
15
16
17
18
# File 'lib/k_ordered_flake.rb', line 14

def self.identity
  mac = Mac.address.split(':').join('')
  code = Digest::SHA1.hexdigest(mac)[28..-1]
  code.to_i(16)
end

.to_base_62(x) ⇒ Object



27
28
29
30
31
32
33
34
35
36
# File 'lib/k_ordered_flake.rb', line 27

def self.to_base_62(x)
  result = []
  while x > 61
    y = x % 62
    x /= 62
    result.unshift self::DIGITS[y]
  end
  result.unshift self::DIGITS[x]
  result.join ""
end