class Riak::Stamp

Implements a client-side form of monotonically-increasing k-sorted unique identifiers. These are useful for key generation if your data is time-sequential and needs to be sorted by key, perhaps in Riak Search. Inspired by Twitter's Snowflake project.

Constants

CLIENT_ID_MASK
SEQUENCE_MASK
SEQUENCE_SHIFT
TIMESTAMP_MASK
TIMESTAMP_SHIFT

Attributes

client[R]

Public Class Methods

new(client) click to toggle source

@param [Client] client a {Riak::Client} which will be used for

the "worker ID" component of the stamp.

@see Client#stamp

# File lib/riak/stamp.rb, line 22
def initialize(client)
  @client = client
  @mutex = Mutex.new
  @timestamp = time_gen
  @sequence = 0
end

Public Instance Methods

next() click to toggle source

Generates a k-sorted unique ID for use as a key or other disambiguation purposes.

# File lib/riak/stamp.rb, line 31
def next
  @mutex.synchronize do
    now = time_gen
    if @timestamp == now
      @sequence = (@sequence + 1) & SEQUENCE_MASK
      now = wait_for_next_ms(@timestamp) if @sequence == 0
    else
      @sequence = 0
    end

    raise BackwardsClockError.new(@timestamp - now) if now < @timestamp

    @timestamp = now
    @timestamp << TIMESTAMP_SHIFT | @sequence << SEQUENCE_SHIFT | client_id
  end
end

Private Instance Methods

client_id() click to toggle source
# File lib/riak/stamp.rb, line 49
def client_id
  case id = @client.client_id
  when Integer
    id & CLIENT_ID_MASK
  else
    id.hash & CLIENT_ID_MASK
  end
end
time_gen() click to toggle source
# File lib/riak/stamp.rb, line 58
def time_gen
  (Time.now.to_f * 1000).floor & TIMESTAMP_MASK
end
wait_for_next_ms(start) click to toggle source
# File lib/riak/stamp.rb, line 62
def wait_for_next_ms(start)
  now = time_gen
  now = time_gen while now <= start
  now
end