Module: Lev::RoutineNesting

Defined in:
lib/lev/routine_nesting.rb

Overview

Manages running of routines inside other routines. In the Lev context, Handlers and Algorithms are routines. A routine and any routines nested inside of it are executed within a single transaction, or depending on the requirements of all the routines, no transaction at all.

Classes that include this module get:

1) a "run" method for running nested routines in a standardized way.
   Routines executed through the run method get hooked into the calling
   hierarchy.

2) a "runner" accessor which points to the routine which called it. If
   runner is nil that means that no other routine called it (some other 
   code did)

3) a "topmost_runner" which points to the highest routine in the calling
   hierarchy (that routine whose 'runner' is nil)

Classes that include this module must:

1) supply a "call" instance method (def call(*args, &block)) that passes
   its arguments and block to whatever code inside the class does the work
   of the class

Classes that include this module may:

1) Call the class-level "uses_routine" method to indicate which other 
   routines will be run.  Helps set isolation levels, etc.  When this
   method is used, the provided routine may

2) Set a default transaction isolation level by declaring a class method
   named "default_transaction_isolation" that returns an instance of 
   Lev::TransactionIsolation

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#runnerObject

Returns the value of attribute runner.



105
106
107
# File 'lib/lev/routine_nesting.rb', line 105

def runner
  @runner
end

Class Method Details

.included(base) ⇒ Object



40
41
42
# File 'lib/lev/routine_nesting.rb', line 40

def self.included(base)
  base.extend(ClassMethods)
end

Instance Method Details

#in_transaction(options = {}) ⇒ Object



74
75
76
77
78
79
80
81
82
# File 'lib/lev/routine_nesting.rb', line 74

def in_transaction(options={}) 
  if self != topmost_runner || self.class.transaction_isolation == TransactionIsolation.no_transaction
    yield
  else
    ActiveRecord::Base.isolation_level( self.class.transaction_isolation.symbol ) do
      ActiveRecord::Base.transaction { yield }
    end
  end
end

#run(other_routine, *args, &block) ⇒ Object

Raises:

  • (IllegalArgument)


84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/lev/routine_nesting.rb', line 84

def run(other_routine, *args, &block)
  if other_routine.is_a? Symbol
    nested_routine = self.class.nested_routines[other_routine]
    if nested_routine.nil?
      raise IllegalArgument, 
            "Routine symbol #{other_routine} does not point to a registered routine"
    end
    other_routine = nested_routine
  end

  other_routine = other_routine.new if other_routine.is_a? Class

  included_modules = other_routine.eigenclass.included_modules

  raise IllegalArgument, "Can only run another nested routine" \
    if !(included_modules.include? Lev::RoutineNesting)

  other_routine.runner = self
  other_routine.call(*args, &block)
end