Method: Factbase#txn

Defined in:
lib/factbase.rb

#txnFactbase::Churn

Run an ACID transaction, which will either modify the factbase or rollback in case of an error.

If necessary to terminate a transaction and rollback all changes, you should raise the Factbase::Rollback exception:

fb = Factbase.new
fb.txn do |fbt|
  fbt.insert.bar = 42
  raise Factbase::Rollback
end

At the end of this script, the factbase will be empty. No facts will be inserted and all changes that happened in the block will be rolled back.

Returns:

  • (Factbase::Churn)

    How many facts have been changed (zero if rolled back)



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/factbase.rb', line 167

def txn
  pairs = {}
  before =
    @maps.map do |m|
      n = m.transform_values(&:dup)
      # rubocop:disable Lint/HashCompareByIdentity
      pairs[n.object_id] = m.object_id
      # rubocop:enable Lint/HashCompareByIdentity
      n
    end
  require_relative 'factbase/taped'
  taped = Factbase::Taped.new(before)
  begin
    require_relative 'factbase/light'
    yield Factbase::Light.new(Factbase.new(taped))
  rescue Factbase::Rollback
    return 0
  end
  require_relative 'factbase/churn'
  churn = Factbase::Churn.new
  taped.inserted.each do |oid|
    b = taped.find_by_object_id(oid)
    next if b.nil?
    @maps << b
    churn.append(1, 0, 0)
  end
  garbage = []
  taped.added.each do |oid|
    b = taped.find_by_object_id(oid)
    next if b.nil?
    garbage << pairs[oid]
    @maps << b
    churn.append(0, 0, 1)
  end
  taped.deleted.each do |oid|
    garbage << pairs[oid]
    churn.append(0, 1, 0)
  end
  @maps.delete_if { |m| garbage.include?(m.object_id) }
  churn
end