class Snowflake::Rb::Snowflake

Constants

MAX_REGION_ID

区域id最大值

MAX_WORKDER_ID

机器id最大值

REGION_ID_BITS

区域标志位数

REGION_ID_LEFT_SHIFT

业务ID偏左移20位

SEQUENCE_BITS

序列号识位数

SEQUENCE_MASK

序列号ID最大值

TIMESTAMP_LEFT_SHIFT

时间毫秒左移23位

TWEPOCH

基准时间

WORKDER_ID_LEFT_SHIFT

机器id偏左移10位

WORKER_ID_BITS

机器标识位数

Attributes

last_timestamp[RW]
lock[RW]
region_id[RW]
sequence[RW]
worker_id[RW]

Public Class Methods

new(worker_id, region_id) click to toggle source
# File lib/snowflake-rb/snowflake.rb, line 33
def initialize(worker_id, region_id)
  @worker_id = worker_id
  @region_id = region_id
  @lock = Monitor.new
  @last_timestamp = 0
  @sequence = 0
  valid_range
end

Public Instance Methods

get_timestamp() click to toggle source
# File lib/snowflake-rb/snowflake.rb, line 78
def get_timestamp
  (Time.now.to_f * 1000).to_i 
end
next()
Alias for: next_id
next_id() click to toggle source
# File lib/snowflake-rb/snowflake.rb, line 42
def next_id
  lock.synchronize do
    timestamp = get_timestamp

    if timestamp < last_timestamp
      diff_milliseconds = last_timestamp - timestamp
      raise TimeMoveBackWardError.new("Refusing to generate id for #{ diff_milliseconds } milliseconds")
    end

    if timestamp == last_timestamp
      @sequence = (sequence + 1) & SEQUENCE_MASK

      if sequence == 0
        timestamp = tail_next_timestamp(last_timestamp)
      end
    else
      @sequence = rand(10)
    end

    @last_timestamp = timestamp

    return ((timestamp - TWEPOCH) << TIMESTAMP_LEFT_SHIFT) | (region_id << REGION_ID_LEFT_SHIFT) | (worker_id << WORKDER_ID_LEFT_SHIFT) | sequence
  end
end
Also aliased as: next
tail_next_timestamp(last_timestamp) click to toggle source
# File lib/snowflake-rb/snowflake.rb, line 68
def tail_next_timestamp(last_timestamp)
  timestamp = get_timestamp

  while (timestamp <= last_timestamp)
    timestamp = get_timestamp
  end

  return timestamp
end
valid_range() click to toggle source
# File lib/snowflake-rb/snowflake.rb, line 82
def valid_range
  if worker_id < 0 || worker_id > MAX_WORKDER_ID
    raise WorkerIdOutRangeError.new
  end

  if region_id < 0 || region_id > MAX_REGION_ID
    raise RegionIdOutRangeError.new
  end
end