class Pokan::Entity

Entity is the class that takes care of data management, including versioning and persistence.

Basic Usage

e = Entity.new
e.id = 'my_id'
e.store(:my_key, 'my_value')
e.value(:my_key) # => 'my_value'
e.save # persists the data

Attributes

id[RW]

Public Class Methods

new() click to toggle source
# File lib/pokan/entity.rb, line 18
def initialize
  @key_set = Hash.new
end

Public Instance Methods

destroy() click to toggle source

Deletes all persisted data related to the entity

# File lib/pokan/entity.rb, line 94
def destroy
  db = Connection.redis
  db.del("entity:#{@id}:key")
  db.del("entity:#{@id}:timestamp")
  db.del("entity:#{@id}:value")
  db.srem('entities', @id)
end
digest() click to toggle source

Gets a digest containing all entity’s key/timestamp It returns a hash with all the pairs in the following structure: { key: timestamp, … }

# File lib/pokan/entity.rb, line 72
def digest
  digest = Hash.new
  @key_set.each {|k, v| digest[k] = v[:timestamp]}
  digest
end
keys() click to toggle source

Returns all keys of the peer in an array

# File lib/pokan/entity.rb, line 53
def keys
  @key_set.keys
end
match?(query) click to toggle source

Verifies if the entity have the given keys with the same values. The query structure must be similar to: { key1: ‘v’, key2: [‘1’, ‘2’] }

# File lib/pokan/entity.rb, line 151
def match?(query)
  accepted = true
  query.each do |key, value|
    value = [value]  unless value.is_a?(Array) || value.is_a?(Hash)
    if value.is_a?(Array)
      accepted = false  unless value.include?(value(key))
    else
      accepted = false  if value[:min] && value[:min] >= value(key)
      accepted = false  if value[:max] && value[:max] <= value(key)
    end
  end
  accepted
end
merge(keys) click to toggle source

Stores the keys-values-timestamps with timestamp greater than the entity’s timestamp. The ‘keys’ parameter must have the following structure: { key: {value: ‘value’, timestamp: <Time obj> }, key1:.… }

# File lib/pokan/entity.rb, line 120
def merge(keys)
 keys.each do |key, data|
   if data[:timestamp].to_f > timestamp(key).to_f
     store(key, data[:value], Time.at(data[:timestamp].to_f))
   end
 end
end
newer(digest) click to toggle source

Returns all peer’s updated keys-values-timestamps in relation to a given digest.

Return structure: { key: { value: ‘value’, timestamp: <Time obj> }, … }

# File lib/pokan/entity.rb, line 141
def newer(digest)
 newer = digest.select { |key, tmsp| Time.at(tmsp.to_f) < timestamp(key) }
 newer.each_key do |key|
   newer[key] = { value: value(key), timestamp: timestamp(key).to_f }
 end
end
older(digest) click to toggle source

Returns all entity’s outdated keys in relation to a given digest.

Return Structure: [:old_key, …]

# File lib/pokan/entity.rb, line 132
def older(digest)
  digest.select { |key, tmsp| Time.at(tmsp.to_f) > timestamp(key) }.keys
end
reload() click to toggle source

Gets all the data related to the peer from database. Newer keys that wasn't saved in any momentwill also be substituted.

# File lib/pokan/entity.rb, line 105
def reload
  db = Connection.redis
  values = db.hgetall("entity:#{@id}:value")
  timestamps = db.hgetall("entity:#{@id}:timestamp")
  @key_set = Hash.new
  values.each do |k, v|
    @key_set[k.to_sym] = { value: v, timestamp: timestamps[k].to_f }
  end
end
save() click to toggle source

Persists all the entity’s data

# File lib/pokan/entity.rb, line 80
def save
  db = Connection.redis

  raise "Could not save the data, id not defined"  unless @id
  @key_set.each do |k, v|
    db.hset("entity:#{@id}:value", k.to_s, v[:value])
    db.hset("entity:#{@id}:timestamp", k.to_s, v[:timestamp])
    db.sadd("entity:#{@id}:keys", k.to_s)
  end
  db.sadd("entities", @id)
end
store(key, value, timestamp = Time.now) click to toggle source

Stores the value and the timestamp for a given key. If the key, which must be a symbol, already exists, it will be updated if the timestamp is greater. The timestamp defaults to Time.now.

# File lib/pokan/entity.rb, line 27
def store(key, value, timestamp = Time.now)
  if !@key_set.has_key?(key) || @key_set[key][:timestamp] < timestamp.to_f
    @key_set[key] = { value: value, timestamp: timestamp.to_f }
  end
end
timestamp(key) click to toggle source

Gets the current timestamp of the requested key The given key must be a symbol and the returned timestamp will be a Time object.

# File lib/pokan/entity.rb, line 43
def timestamp(key)
  if @key_set.has_key?(key)
    Time.at(@key_set[key][:timestamp])
  else
    Time.at(0)
  end
end
value(key) click to toggle source

Gets the value of the requested key. The given key must be a symbol.

# File lib/pokan/entity.rb, line 36
def value(key)
  @key_set[key][:value] if @key_set.has_key?(key)
end
values(keys) click to toggle source

Returns all the values/timestamps for each given key in 'keys' Array in the following structure: { key: { value: ‘value’, timestamp: <Time obj> }, key2:… }

# File lib/pokan/entity.rb, line 61
def values(keys)
  key_values = Hash.new
  keys.each do |k|
    key_values[k] = @key_set[k.to_sym] || {}
  end
  key_values
end