lev 0.0.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,127 +0,0 @@
1
- module Lev
2
-
3
- # Manages running of routines inside other routines. In the Lev context,
4
- # Handlers and Algorithms are routines. A routine and any routines nested
5
- # inside of it are executed within a single transaction, or depending on the
6
- # requirements of all the routines, no transaction at all.
7
- #
8
- # Classes that include this module get:
9
- #
10
- # 1) a "run" method for running nested routines in a standardized way.
11
- # Routines executed through the run method get hooked into the calling
12
- # hierarchy.
13
- #
14
- # 2) a "runner" accessor which points to the routine which called it. If
15
- # runner is nil that means that no other routine called it (some other
16
- # code did)
17
- #
18
- # 3) a "topmost_runner" which points to the highest routine in the calling
19
- # hierarchy (that routine whose 'runner' is nil)
20
- #
21
- # Classes that include this module must:
22
- #
23
- # 1) supply a "call" instance method (def call(*args, &block)) that passes
24
- # its arguments and block to whatever code inside the class does the work
25
- # of the class
26
- #
27
- # Classes that include this module may:
28
- #
29
- # 1) Call the class-level "uses_routine" method to indicate which other
30
- # routines will be run. Helps set isolation levels, etc. When this
31
- # method is used, the provided routine may
32
- #
33
- # 2) Set a default transaction isolation level by declaring a class method
34
- # named "default_transaction_isolation" that returns an instance of
35
- # Lev::TransactionIsolation
36
- #
37
- #
38
- module RoutineNesting
39
-
40
- def self.included(base)
41
- base.extend(ClassMethods)
42
- end
43
-
44
- module ClassMethods
45
-
46
- # Called at a routine's class level to foretell which other routines will
47
- # be used when this routine executes. Helpful for figuring out ahead of
48
- # time what kind of transaction isolation level should be used.
49
- def uses_routine(routine_class, options={})
50
- symbol = options[:as] || routine_class.name.underscore.gsub('/','_').to_sym
51
-
52
- raise IllegalArgument, "Routine #{routine_class} has already been registered" \
53
- if nested_routines[symbol]
54
-
55
- nested_routines[symbol] = routine_class
56
-
57
- transaction_isolation.replace_if_more_isolated(routine_class.transaction_isolation)
58
- end
59
-
60
- def transaction_isolation
61
- @transaction_isolation ||= default_transaction_isolation
62
- end
63
-
64
- def default_transaction_isolation
65
- TransactionIsolation.no_transaction
66
- end
67
-
68
- def nested_routines
69
- @nested_routines ||= {}
70
- end
71
-
72
- end
73
-
74
- def in_transaction(options={})
75
- if self != topmost_runner || self.class.transaction_isolation == TransactionIsolation.no_transaction
76
- yield
77
- else
78
- ActiveRecord::Base.isolation_level( self.class.transaction_isolation.symbol ) do
79
- ActiveRecord::Base.transaction { yield }
80
- end
81
- end
82
- end
83
-
84
- def run(other_routine, *args, &block)
85
- if other_routine.is_a? Symbol
86
- nested_routine = self.class.nested_routines[other_routine]
87
- if nested_routine.nil?
88
- raise IllegalArgument,
89
- "Routine symbol #{other_routine} does not point to a registered routine"
90
- end
91
- other_routine = nested_routine
92
- end
93
-
94
- other_routine = other_routine.new if other_routine.is_a? Class
95
-
96
- included_modules = other_routine.eigenclass.included_modules
97
-
98
- raise IllegalArgument, "Can only run another nested routine" \
99
- if !(included_modules.include? Lev::RoutineNesting)
100
-
101
- other_routine.runner = self
102
- other_routine.call(*args, &block)
103
- end
104
-
105
- attr_reader :runner
106
-
107
- protected
108
-
109
- attr_writer :runner
110
-
111
- def topmost_runner
112
- runner.nil? ? self : runner.topmost_runner
113
- end
114
-
115
- def runner=(runner)
116
- @runner = runner
117
-
118
- if topmost_runner.class.transaction_isolation.weaker_than(self.class.default_transaction_isolation)
119
- raise IsolationMismatch,
120
- "The routine being run has a stronger isolation requirement than " +
121
- "the isolation being used by the routine(s) running it; call the " +
122
- "'uses' method in the running routine's initializer"
123
- end
124
- end
125
-
126
- end
127
- end