Class: Riak::Ledger

Inherits:
Object
  • Object
show all
Defined in:
lib/ledger.rb,
lib/ledger/version.rb

Constant Summary collapse

VERSION =
"0.0.5"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bucket, key, options = {}) ⇒ Ledger

Create a new Ledger object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/ledger.rb', line 18

def initialize(bucket, key, options={})
  self.bucket = bucket
  self.key = key
  self.retry_count = options[:retry_count] || 10

  self.counter_options = {}
  self.counter_options[:actor] = options[:actor] || Thread.current["name"] || "ACTOR1"
  self.counter_options[:history_length] = options[:history_length] || 10
  self.counter = Riak::CRDT::TPNCounter.new(self.counter_options)

  unless bucket.allow_mult
    self.bucket.allow_mult = true
  end
end

Instance Attribute Details

#bucketObject

Returns the value of attribute bucket.



7
8
9
# File 'lib/ledger.rb', line 7

def bucket
  @bucket
end

#counterObject

Returns the value of attribute counter.



7
8
9
# File 'lib/ledger.rb', line 7

def counter
  @counter
end

#counter_optionsObject

Returns the value of attribute counter_options.



7
8
9
# File 'lib/ledger.rb', line 7

def counter_options
  @counter_options
end

#keyObject

Returns the value of attribute key.



7
8
9
# File 'lib/ledger.rb', line 7

def key
  @key
end

#retry_countObject

Returns the value of attribute retry_count.



7
8
9
# File 'lib/ledger.rb', line 7

def retry_count
  @retry_count
end

Class Method Details

.find!(bucket, key, options = {}) ⇒ Riak::Ledger

Find an existing Ledger object, merge and save it



43
44
45
46
47
48
49
# File 'lib/ledger.rb', line 43

def self.find!(bucket, key, options={})
  candidate = new(bucket, key, options)
  vclock = candidate.refresh()
  candidate.save(vclock)

  return candidate
end

Instance Method Details

#credit!(transaction, value) ⇒ Boolean

Increment the counter, merge and save it

See Also:

  • value)


56
57
58
# File 'lib/ledger.rb', line 56

def credit!(transaction, value)
  self.update!(transaction, value)
end

#debit!(transaction, value) ⇒ Boolean

Decrement the counter, merge and save it

See Also:

  • value)


65
66
67
# File 'lib/ledger.rb', line 65

def debit!(transaction, value)
  self.update!(transaction, value * -1)
end

#deleteBoolean

Delete the counter



121
122
123
124
125
126
127
128
# File 'lib/ledger.rb', line 121

def delete()
  begin
    self.bucket.delete(self.key)
    return true
  rescue => e
    return false
  end
end

#has_transaction?(transaction) ⇒ Boolean

Check if the counter has transaction



109
110
111
# File 'lib/ledger.rb', line 109

def has_transaction?(transaction)
  self.counter.has_transaction?(transaction)
end

#refreshString

Get the current state of the counter and merge it



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/ledger.rb', line 132

def refresh()
  obj = self.bucket.get_or_new(self.key)
  return if obj.nil?

  self.counter = Riak::CRDT::TPNCounter.new(self.counter_options)

  if obj.siblings.length > 1
    obj.siblings.each do | sibling |
      unless sibling.raw_data.nil? or sibling.raw_data.empty?
        self.counter.merge(Riak::CRDT::TPNCounter.from_json(sibling.raw_data, self.counter_options))
      end
    end
  elsif !obj.raw_data.nil?
    self.counter.merge(Riak::CRDT::TPNCounter.from_json(obj.raw_data, self.counter_options))
  end

  return obj.vclock
end

#save(vclock = nil) ⇒ Boolean

Save the counter with an optional vclock



154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/ledger.rb', line 154

def save(vclock=nil)
  object = self.bucket.new(self.key)
  object.vclock = vclock if vclock
  object.content_type = 'application/json'
  object.raw_data = self.to_json()

  begin
    options = {:returnbody => false}
    object.store(options)
    return true
  rescue => e
    return false
  end
end

#to_jsonObject



169
170
171
# File 'lib/ledger.rb', line 169

def to_json()
  self.counter.to_json
end

#update!(transaction, value, current_retry = nil) ⇒ Boolean

Update the counter, merge and save it. Retry if unsuccessful



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/ledger.rb', line 74

def update!(transaction, value, current_retry=nil)
  # Failure case, not able to successfully complete the operation, retry a.s.a.p.
  if current_retry && current_retry <= 0
    return false
  end

  # Get the current merged state of this counter
  vclock = self.refresh()


  if self.has_transaction?(transaction)
    # If the transaction already exists in the counter, no problem
    return true
  else
    # If the transaction doesn't exist, attempt to add it and save
    if value < 0
      self.counter.decrement(transaction, value * -1)
    else
      self.counter.increment(transaction, value)
    end

    unless self.save(vclock)
      # If the save wasn't successful, retry
      current_retry = self.retry_count unless current_retry
      self.update!(transaction, value, current_retry - 1)
    else
      # If the save succeeded, no problem
      return true
    end
  end
end

#valueInteger

Calculate the current value of the counter



115
116
117
# File 'lib/ledger.rb', line 115

def value()
  self.counter.value
end