Class: Meangirls::LWWSet

Inherits:
Set
  • Object
show all
Defined in:
lib/meangirls/lww_set.rb

Defined Under Namespace

Classes: Pair

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Set

#&, #+, #-, #===, #each, #empty?, #size, #to_a, #|

Methods inherited from CRDT

merge, #to_json

Constructor Details

#initialize(hash = nil) ⇒ LWWSet

Returns a new instance of LWWSet.



53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/meangirls/lww_set.rb', line 53

def initialize(hash = nil)
  @e = {}
  @bias = 'a'

  if hash
    raise ArgumentError, "hash must contain e" unless hash['e']
    @bias = hash['bias'] if hash['bias']
    hash['e'].each do |list|
      element, add, delete = list
      @e[element] = Pair.new(add, delete).merge(@e[element])
    end    
  end
end

Instance Attribute Details

#biasObject

Returns the value of attribute bias.



52
53
54
# File 'lib/meangirls/lww_set.rb', line 52

def bias
  @bias
end

#eObject

Returns the value of attribute e.



51
52
53
# File 'lib/meangirls/lww_set.rb', line 51

def e
  @e
end

Class Method Details

.biasesObject



47
48
49
# File 'lib/meangirls/lww_set.rb', line 47

def self.biases
  ['a', 'r']
end

Instance Method Details

#<<(e) ⇒ Object

Inserts e into the set with a default generated timestamp. Your clocks ARE synchronized, right? WRONG!



69
70
71
# File 'lib/meangirls/lww_set.rb', line 69

def <<(e)
  add(e, timestamp)
end

#==(other) ⇒ Object

Strict equality: both adds and removes are equal.



74
75
76
77
# File 'lib/meangirls/lww_set.rb', line 74

def ==(other)
  other.kind_of? self.class and
  e == other.e
end

#add(e, time = timestamp) ⇒ Object

Add e, with an optional timestamp.



80
81
82
83
# File 'lib/meangirls/lww_set.rb', line 80

def add(e, time = timestamp)
  merge_element! e, Pair.new(time, nil)
  self
end

#as_jsonObject



85
86
87
88
89
90
91
92
# File 'lib/meangirls/lww_set.rb', line 85

def as_json
  {
    'type' => type,
    'e' => @e.map { |e, pair|
      [e, pair.add, pair.remove]
    }
  }
end

#cloneObject



94
95
96
97
98
# File 'lib/meangirls/lww_set.rb', line 94

def clone
  c = super
  c.e = e.clone
  c
end

#delete(e, time = timestamp) ⇒ Object

Delete e from self, with optional timestamp.



101
102
103
104
# File 'lib/meangirls/lww_set.rb', line 101

def delete(e, time = timestamp)
  merge_element! e, Pair.new(nil, time)
  e
end

#include?(e) ⇒ Boolean

Is e an element of the set?

Returns:

  • (Boolean)


107
108
109
110
111
112
113
114
115
116
117
# File 'lib/meangirls/lww_set.rb', line 107

def include?(e)
  return false unless pair = @e[e]
  case bias
    when 'a'
      pair.exists_a?
    when 'r'
      pair.exists_r?
    else
      raise RuntimeError, "unsupported bias #{bias.inspect}"
   end
end

#merge(other) ⇒ Object

Merge with another lww-set



120
121
122
123
124
125
126
127
128
129
130
# File 'lib/meangirls/lww_set.rb', line 120

def merge(other)
  unless other.kind_of? self.class
    raise ArgumentError, "other must be a #{self.class}"
  end

  c = clone
  other.e.each do |element, pair|
    c.merge_element!(element, pair)
  end
  c
end

#merge_element!(e, pair) ⇒ Object

Mutates self to update the value for e with the given pair.



133
134
135
136
137
138
139
# File 'lib/meangirls/lww_set.rb', line 133

def merge_element!(e, pair)
  if cur = @e[e]
    @e[e] = cur | pair
  else
    @e[e] = pair
  end
end

#timestampObject

Default timestamps are the present time in UTC as ISO 8601 strings, WITH a seconds fraction guaranteed to be unique and monotonically increasing for all use of Meangirls.



161
162
163
# File 'lib/meangirls/lww_set.rb', line 161

def timestamp
  Meangirls.timestamp
end

#to_setObject



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/meangirls/lww_set.rb', line 141

def to_set
  case bias
    when 'a'
      @e.inject(Set.new) do |s, l|
        element, pair = l
        s << element if pair.exists_a?
        s
      end
    when 'r'
      @e.inject(Set.new) do |s, l|
        element, pair = l
        s << element if pair.exists_r?
        s
      end
  end
end

#typeObject



165
166
167
# File 'lib/meangirls/lww_set.rb', line 165

def type
  'lww-set'
end