lib/rails_workflow/operation_runner.rb
# frozen_string_literal: true
module RailsWorkflow
# Workflow::OperationRunner responsible for operation execution
class OperationRunner
attr_accessor :operation
delegate :can_start?, :completed?, :completable?, :update_attribute,
:update_attributes, :is_background, :child_process, :context,
to: :operation
def self.start(operations)
operations.each do |operation|
new(operation).start
end
end
def initialize(operation)
@operation = operation
end
def start
can_start? ? starting : waiting
rescue => exception
error_builder.handle(
exception,
parent: operation, target: :operation_runner, method: :start
)
end
def starting
update_attribute(:status, Status::IN_PROGRESS)
if is_background && config.activejob_enabled
OperationExecutionJob.perform_later(operation.id)
else
OperationExecutionJob.perform_now(operation.id)
end
end
def waiting
update_attribute(:status, Status::WAITING)
start_waiting if respond_to? :start_waiting
rescue => exception
error_builder.handle(
exception,
parent: operation,
target: :operation_runner,
method: :waiting
)
end
def execute_in_transaction
with_transaction do
child_process_runner.start if child_process.present?
operation.execute if operation.respond_to?(:execute)
complete
end
rescue => exception
handle_exception(exception)
end
def complete(to_status = Status::DONE)
return unless completable?
context&.save
update_attributes(
status: to_status,
completed_at: Time.zone.now
)
process_runner.operation_completed(operation)
end
def cancel
complete Status::CANCELED
end
def skip
complete Status::SKIPPED
end
private
def error_builder
config.error_builder
end
def handle_exception(exception)
error_builder.handle(
exception,
parent: operation, target: :operation_runner,
method: :execute_in_transaction
)
end
def with_transaction
operation.class.transaction(requires_new: true) do
yield
end
end
def child_process_runner
@child_process_runner ||= config.process_runner.new(child_process)
end
def process_runner
@process_runner ||= config.process_runner.new(operation.process)
end
def config
RailsWorkflow.config
end
end
end