lib/cequel/metal/batch_manager.rb
# -*- encoding : utf-8 -*-
module Cequel
module Metal
#
# Manage a current batch per thread. Used by {Keyspace}
#
# @api private
#
class BatchManager
#
# @param keyspace [Keyspace] keyspace to make writes to
# @api private
#
def initialize(keyspace)
@keyspace = keyspace
end
#
# Execute write operations in a batch. Any inserts, updates, and deletes
# inside this method's block will be executed inside a CQL BATCH
# operation.
#
# @param options [Hash]
# @option (see Batch#initialize)
# @yield context within which all write operations will be batched
# @return return value of block
# @raise [ArgumentError] if attempting to start a logged batch while
# already in an unlogged batch, or vice versa.
#
# @example Perform inserts in a batch
# DB.batch do
# DB[:posts].insert(:id => 1, :title => 'One')
# DB[:posts].insert(:id => 2, :title => 'Two')
# end
#
# @note If this method is created while already in a batch of the same
# type (logged or unlogged), this method is a no-op.
#
def batch(options = {})
new_batch = Batch.new(keyspace, options)
if current_batch
if current_batch.unlogged? && new_batch.logged?
fail ArgumentError,
"Already in an unlogged batch; can't start a logged batch."
end
return yield(current_batch)
end
begin
self.current_batch = new_batch
yield(new_batch).tap { new_batch.apply }
ensure
self.current_batch = nil
end
end
def current_batch
::Thread.current[batch_key]
end
private
attr_reader :keyspace
def current_batch=(batch)
::Thread.current[batch_key] = batch
end
def batch_key
:"cequel-batch-#{object_id}"
end
end
end
end