class Mara::Batch
Perform operations in batches.
@note This is not the same as a transaction. It only saves on the number
of API calls to DynamoDB.
@example Saving Multiple Records
Mara::Batch.in_batch do person1.save person2.save end
@author Maddie Schipper @since 1.0.0
Constants
- BATCH_STACK_VAR_NAME
@private
The name of the thread variable that holds the current batch spec.
Attributes
The current batch id.
@return [String]
@private
The queue of operations to perform on commit.
@return [Array<Array<Symbol, Hash>>]
Public Class Methods
@private
Perform a delete model. If there is a current batch it is added to the operation queue. If there is no current batch, this will be forwarded directly to the { Mara::Persistence}.
@param item [Hash] The model to perform the action with.
# File lib/mara/batch.rb, line 95 def delete_model(item) perform_for_model(:delete_model, item) end
@private
Perform a delete model. If there is a current batch it is added to the operation queue. If there is no current batch, this will be forwarded directly to the { Mara::Persistence}.
@param item [Hash] The model to perform the action with.
# File lib/mara/batch.rb, line 107 def delete_model!(item) perform_for_model(:delete_model!, item) end
Perform in a batch.
All save/destroy calls on a model will be routed into the current batch.
If there is a error raised all operations will be dropped.
If the error is a { Mara::Rollback} the batch will silently rollback. If not, it will be re-thrown after the rollback.
@yield The batch operation.
# File lib/mara/batch.rb, line 47 def in_batch begin_new_batch begin yield rescue Mara::Rollback abort_current_batch # rubocop:disable Lint/RescueException rescue Exception => exception # rubocop:enable Lint/RescueException abort_current_batch raise exception else commit_current_batch end end
@private
Create a new batch.
# File lib/mara/batch.rb, line 160 def initialize @batch_id = SecureRandom.uuid @operations = [] end
@private
Perform a save model. If there is a current batch it is added to the operation queue. If there is no current batch, this will be forwarded directly to the { Mara::Persistence}.
@param item [Hash] The model to perform the action with.
# File lib/mara/batch.rb, line 71 def save_model(item) perform_for_model(:save_model, item) end
@private
Perform a save model. If there is a current batch it is added to the operation queue. If there is no current batch, this will be forwarded directly to the { Mara::Persistence}.
@param item [Hash] The model to perform the action with.
# File lib/mara/batch.rb, line 83 def save_model!(item) perform_for_model(:save_model!, item) end
Private Class Methods
# File lib/mara/batch.rb, line 137 def abort_current_batch batch_stack.pop.abort_batch end
# File lib/mara/batch.rb, line 125 def batch_stack Thread.current[BATCH_STACK_VAR_NAME] ||= [] end
# File lib/mara/batch.rb, line 129 def begin_new_batch batch_stack << Mara::Batch.new end
# File lib/mara/batch.rb, line 133 def commit_current_batch batch_stack.pop.commit_batch end
# File lib/mara/batch.rb, line 121 def current_batch batch_stack.first end
# File lib/mara/batch.rb, line 113 def perform_for_model(action_name, item) if (batch = current_batch) batch.add(action_name, item) else Mara::Persistence.send(action_name, item) end end
Public Instance Methods
@private
Abort the batch and clear the current batch operations.
@return [void]
# File lib/mara/batch.rb, line 198 def abort_batch @operations = [] Mara.instrument('batch.abort', batch_id: batch_id) end
@private
Add an item to the operation queue.
@param action_name [Symbol] The action to perform for the item. @param item [Hash] The hash of data for the action.
@return [void]
# File lib/mara/batch.rb, line 174 def add(action_name, item) Mara.instrument('batch.add_item', batch_id: batch_id, action: action_name, item: item) do operations << [action_name, item] end end
@private
Perform all the operations in the queue.
@return [void]
# File lib/mara/batch.rb, line 186 def commit_batch Mara.instrument('batch.commit', batch_id: batch_id) do execute_commit end end
Private Instance Methods
# File lib/mara/batch.rb, line 205 def execute_commit ops = operations.map do |action_name, item| case action_name when :save_model, :save_model! Mara::Persistence::CreateRequest.new(item) when :delete_model, :delete_model! Mara::Persistence::DestroyRequest.new(item) else raise "Unexpected operation action name #{action_name}" end end Mara::Persistence.perform_requests( Mara::Client.shared, Mara.config.dynamodb.table_name, ops ) end