Class: Pokan::Entity

Inherits:
Object
  • Object
show all
Defined in:
lib/pokan/entity.rb

Overview

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

Direct Known Subclasses

Peer

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEntity

Returns a new instance of Entity.



18
19
20
# File 'lib/pokan/entity.rb', line 18

def initialize
  @key_set = Hash.new
end

Instance Attribute Details

#idObject

Returns the value of attribute id.



16
17
18
# File 'lib/pokan/entity.rb', line 16

def id
  @id
end

Instance Method Details

#destroyObject

Deletes all persisted data related to the entity



94
95
96
97
98
99
100
# 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

#digestObject

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



72
73
74
75
76
# File 'lib/pokan/entity.rb', line 72

def digest
  digest = Hash.new
  @key_set.each {|k, v| digest[k] = v[:timestamp]}
  digest
end

#keysObject

Returns all keys of the peer in an array



53
54
55
# File 'lib/pokan/entity.rb', line 53

def keys
  @key_set.keys
end

#match?(query) ⇒ Boolean

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

Returns:

  • (Boolean)


151
152
153
154
155
156
157
158
159
160
161
162
163
# 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) ⇒ Object

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:.… }



120
121
122
123
124
125
126
# 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) ⇒ Object

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

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



141
142
143
144
145
146
# 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) ⇒ Object

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

Return Structure: [:old_key, …]



132
133
134
# File 'lib/pokan/entity.rb', line 132

def older(digest)
  digest.select { |key, tmsp| Time.at(tmsp.to_f) > timestamp(key) }.keys
end

#reloadObject

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



105
106
107
108
109
110
111
112
113
# 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

#saveObject

Persists all the entity’s data



80
81
82
83
84
85
86
87
88
89
90
# 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) ⇒ Object

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.



27
28
29
30
31
# 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) ⇒ Object

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



43
44
45
46
47
48
49
# 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) ⇒ Object

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



36
37
38
# File 'lib/pokan/entity.rb', line 36

def value(key)
  @key_set[key][:value] if @key_set.has_key?(key)
end

#values(keys) ⇒ Object

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



61
62
63
64
65
66
67
# 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