oflow 0.6.0 → 0.8.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.
- checksums.yaml +4 -4
- data/README.md +23 -41
- data/lib/oflow.rb +2 -3
- data/lib/oflow/actor.rb +3 -0
- data/lib/oflow/actors/httpserver.rb +3 -1
- data/lib/oflow/actors/log.rb +3 -2
- data/lib/oflow/actors/persister.rb +29 -6
- data/lib/oflow/actors/timer.rb +29 -12
- data/lib/oflow/box.rb +2 -2
- data/lib/oflow/env.rb +221 -15
- data/lib/oflow/flow.rb +217 -37
- data/lib/oflow/graffle.rb +293 -0
- data/lib/oflow/haserrorhandler.rb +3 -22
- data/lib/oflow/haslog.rb +21 -15
- data/lib/oflow/inspector.rb +18 -17
- data/lib/oflow/link.rb +11 -6
- data/lib/oflow/task.rb +134 -22
- data/lib/oflow/test/actorwrap.rb +1 -1
- data/lib/oflow/version.rb +1 -1
- data/test/actors/balancer_test.rb +17 -12
- data/test/actors/httpserver_test.rb +11 -10
- data/test/actors/log_test.rb +3 -6
- data/test/actors/merger_test.rb +23 -18
- data/test/actors/persister_test.rb +6 -8
- data/test/actors/timer_test.rb +63 -35
- data/test/actorwrap_test.rb +2 -6
- data/test/all_tests.rb +3 -7
- data/test/box_test.rb +4 -10
- data/test/flow_basic_test.rb +24 -22
- data/test/flow_cfg_error_test.rb +17 -13
- data/test/flow_linked_test.rb +146 -0
- data/test/flow_log_test.rb +43 -29
- data/test/flow_rescue_test.rb +41 -27
- data/test/flow_tracker_test.rb +26 -30
- data/test/helper.rb +15 -0
- data/test/task_test.rb +3 -7
- data/test/tracker_test.rb +3 -11
- metadata +5 -7
- data/lib/oflow/haslinks.rb +0 -68
- data/lib/oflow/hasname.rb +0 -31
- data/lib/oflow/hastasks.rb +0 -214
- data/test/flow_nest_test.rb +0 -215
@@ -7,25 +7,6 @@ module OFlow
|
|
7
7
|
# the next Flow until an error handler is found.
|
8
8
|
module HasErrorHandler
|
9
9
|
|
10
|
-
# Returns an error handler Task by checking for an @error_handler variable,
|
11
|
-
# then looking for a Task with a base name of :error in itself or any of the
|
12
|
-
# containing Flows.
|
13
|
-
# @return [Task|nil] Task to handle errors
|
14
|
-
def error_handler()
|
15
|
-
return @error_handler if instance_variable_defined?(:@error_handler) && !@error_handler.nil?
|
16
|
-
if instance_variable_defined?(:@flow)
|
17
|
-
if @flow.respond_to?(:find_task)
|
18
|
-
eh = @flow.find_task(:error)
|
19
|
-
return eh unless eh.nil?
|
20
|
-
end
|
21
|
-
if @flow.respond_to?(:error_handler)
|
22
|
-
eh = @flow.error_handler()
|
23
|
-
return eh unless eh.nil?
|
24
|
-
end
|
25
|
-
end
|
26
|
-
nil
|
27
|
-
end
|
28
|
-
|
29
10
|
# Sets avaliable for handling errors.
|
30
11
|
# @param t [Task|nil] Task for handling error or nil to unset
|
31
12
|
def error_handler=(t)
|
@@ -36,11 +17,11 @@ module OFlow
|
|
36
17
|
# @param e [Exception] error to handle
|
37
18
|
def handle_error(e)
|
38
19
|
handler = error_handler()
|
39
|
-
|
40
|
-
handler.receive(nil, Box.new([e, full_name()]))
|
41
|
-
else
|
20
|
+
if handler.nil?
|
42
21
|
puts "** [#{full_name()}] #{e.class}: #{e.message}"
|
43
22
|
e.backtrace.each { |line| puts " #{line}" }
|
23
|
+
else
|
24
|
+
handler.receive(nil, Box.new([e, full_name()]))
|
44
25
|
end
|
45
26
|
end
|
46
27
|
|
data/lib/oflow/haslog.rb
CHANGED
@@ -4,26 +4,12 @@ module OFlow
|
|
4
4
|
# Adds the ability to log by sending log requests to a log Task.
|
5
5
|
module HasLog
|
6
6
|
|
7
|
-
# Returns a log Task by looking for that Task in an attribute and then in
|
8
|
-
# the contained Tasks or Tasks in outer Flows.
|
9
|
-
# @return [Task] log Task.
|
10
|
-
def log()
|
11
|
-
return @log if instance_variable_defined?(:@log) && !@log.nil?
|
12
|
-
# Log task take precedence over log variable.
|
13
|
-
if respond_to?(:find_task)
|
14
|
-
lg = find_task(:log)
|
15
|
-
return lg unless lg.nil?
|
16
|
-
end
|
17
|
-
return @flow.log if instance_variable_defined?(:@flow) && @flow.respond_to?(:log)
|
18
|
-
nil
|
19
|
-
end
|
20
|
-
|
21
7
|
# Sets the log attribute.
|
22
8
|
# @param t [Task] log Task
|
23
9
|
def log=(t)
|
24
10
|
@log = t
|
25
11
|
end
|
26
|
-
|
12
|
+
|
27
13
|
# Lower level logging method. Generally only used when one of the primary
|
28
14
|
# severity methods are called.
|
29
15
|
# @param level [String] message severity or level
|
@@ -45,6 +31,26 @@ module OFlow
|
|
45
31
|
end
|
46
32
|
end
|
47
33
|
|
34
|
+
# @return true if errors would be logged.
|
35
|
+
def error?()
|
36
|
+
Env.log_level <= Logger::Severity::ERROR
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return true if warn messages would be logged.
|
40
|
+
def warn?()
|
41
|
+
Env.log_level <= Logger::Severity::WARN
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return true if info messages would be logged.
|
45
|
+
def info?()
|
46
|
+
Env.log_level <= Logger::Severity::INFO
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return true if debug messages would be logged.
|
50
|
+
def debug?()
|
51
|
+
Env.log_level <= Logger::Severity::DEBUG
|
52
|
+
end
|
53
|
+
|
48
54
|
# Logs the message if logging level is at least debug.
|
49
55
|
# @param msg [String] message to log
|
50
56
|
def debug(msg)
|
data/lib/oflow/inspector.rb
CHANGED
@@ -6,8 +6,9 @@ module OFlow
|
|
6
6
|
class Inspector < ::OTerm::Executor
|
7
7
|
attr_reader :running
|
8
8
|
|
9
|
-
def initialize(port=6060)
|
9
|
+
def initialize(env, port=6060)
|
10
10
|
super()
|
11
|
+
@env = env
|
11
12
|
@running = true
|
12
13
|
|
13
14
|
register('busy', self, :busy, 'returns the busy state of the system.', nil)
|
@@ -44,7 +45,7 @@ available for sorting on name, activity, or queue size.|)
|
|
44
45
|
def shutdown(listener, args)
|
45
46
|
super
|
46
47
|
@running = false
|
47
|
-
|
48
|
+
@env.shutdown()
|
48
49
|
end
|
49
50
|
|
50
51
|
def greeting()
|
@@ -56,7 +57,7 @@ available for sorting on name, activity, or queue size.|)
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def busy(listener, args)
|
59
|
-
if
|
60
|
+
if @env.busy?()
|
60
61
|
listener.out.pl("One or more Tasks is busy.")
|
61
62
|
else
|
62
63
|
listener.out.pl("All Tasks are idle.")
|
@@ -64,14 +65,14 @@ available for sorting on name, activity, or queue size.|)
|
|
64
65
|
end
|
65
66
|
|
66
67
|
def flows(listener, args)
|
67
|
-
|
68
|
+
@env.each_task() do |t|
|
68
69
|
listener.out.pl(t.full_name)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
72
73
|
def list(listener, args)
|
73
74
|
if nil == args
|
74
|
-
|
75
|
+
@env.each_task() do |task|
|
75
76
|
listener.out.pl(task.full_name)
|
76
77
|
end
|
77
78
|
return
|
@@ -81,7 +82,7 @@ available for sorting on name, activity, or queue size.|)
|
|
81
82
|
if id.nil?
|
82
83
|
flow = Env
|
83
84
|
else
|
84
|
-
flow =
|
85
|
+
flow = @env.locate(id)
|
85
86
|
end
|
86
87
|
if flow.nil?
|
87
88
|
listener.out.pl("--- No Flow or Task found for #{id}")
|
@@ -100,7 +101,7 @@ available for sorting on name, activity, or queue size.|)
|
|
100
101
|
detail, id, ok = _parse_opt_id_args(args, 'v', listener)
|
101
102
|
return unless ok
|
102
103
|
|
103
|
-
task =
|
104
|
+
task = @env.locate(id)
|
104
105
|
if task.nil?
|
105
106
|
listener.out.pl("--- Failed to find '#{id}'")
|
106
107
|
return
|
@@ -110,11 +111,11 @@ available for sorting on name, activity, or queue size.|)
|
|
110
111
|
|
111
112
|
def start(listener, args)
|
112
113
|
if nil == args || 0 == args.size()
|
113
|
-
|
114
|
+
@env.start()
|
114
115
|
listener.out.pl("All Tasks restarted")
|
115
116
|
else
|
116
117
|
args.strip!
|
117
|
-
task =
|
118
|
+
task = @env.locate(args)
|
118
119
|
if task.nil?
|
119
120
|
listener.out.pl("--- Failed to find '#{args}'")
|
120
121
|
else
|
@@ -125,7 +126,7 @@ available for sorting on name, activity, or queue size.|)
|
|
125
126
|
end
|
126
127
|
|
127
128
|
def step(listener, args)
|
128
|
-
lg =
|
129
|
+
lg = @env.log()
|
129
130
|
stop_after = false
|
130
131
|
if !lg.nil? && Task::STOPPED == lg.state
|
131
132
|
lg.start()
|
@@ -136,7 +137,7 @@ available for sorting on name, activity, or queue size.|)
|
|
136
137
|
task = Env
|
137
138
|
else
|
138
139
|
args.strip!
|
139
|
-
task =
|
140
|
+
task = @env.locate(args)
|
140
141
|
end
|
141
142
|
if task.nil?
|
142
143
|
listener.out.pl("--- Failed to find '#{args}'")
|
@@ -153,11 +154,11 @@ available for sorting on name, activity, or queue size.|)
|
|
153
154
|
|
154
155
|
def stop(listener, args)
|
155
156
|
if nil == args || 0 == args.size()
|
156
|
-
|
157
|
+
@env.stop()
|
157
158
|
listener.out.pl("All Tasks stopped(paused)")
|
158
159
|
else
|
159
160
|
args.strip!
|
160
|
-
task =
|
161
|
+
task = @env.locate(args)
|
161
162
|
if task.nil?
|
162
163
|
listener.out.pl("--- Failed to find '#{args}'")
|
163
164
|
else
|
@@ -168,7 +169,7 @@ available for sorting on name, activity, or queue size.|)
|
|
168
169
|
end
|
169
170
|
|
170
171
|
def verbosity(listener, args)
|
171
|
-
lg =
|
172
|
+
lg = @env.log
|
172
173
|
if lg.nil?
|
173
174
|
listener.out.pl("--- No logger")
|
174
175
|
return
|
@@ -188,10 +189,10 @@ available for sorting on name, activity, or queue size.|)
|
|
188
189
|
def watch(listener, args)
|
189
190
|
tasks = []
|
190
191
|
if args.nil? || 0 == args.size()
|
191
|
-
|
192
|
+
@env.walk_tasks() { |t| tasks << t }
|
192
193
|
else
|
193
194
|
args.strip!
|
194
|
-
task =
|
195
|
+
task = @env.locate(args)
|
195
196
|
if task.nil?
|
196
197
|
listener.out.pl("--- Failed to find '#{args}'")
|
197
198
|
return
|
@@ -388,7 +389,7 @@ available for sorting on name, activity, or queue size.|)
|
|
388
389
|
names = ['fatal', 'error', 'warn', 'info', 'debug'].select { |s| s.start_with?(last.downcase()) }
|
389
390
|
else # expect id or options
|
390
391
|
with_colon = ':' == last[0]
|
391
|
-
|
392
|
+
@env.walk_tasks(false) do |t|
|
392
393
|
fn = t.full_name
|
393
394
|
fn = fn[1..-1] unless with_colon
|
394
395
|
names << fn if fn.start_with?(last)
|
data/lib/oflow/link.rb
CHANGED
@@ -7,24 +7,25 @@ module OFlow
|
|
7
7
|
|
8
8
|
# Name of the target.
|
9
9
|
attr_reader :target_name
|
10
|
+
# Name of the target's parent flow.
|
11
|
+
attr_reader :flow_name
|
10
12
|
# Operation to provide the target.
|
11
13
|
attr_reader :op
|
12
|
-
# The actual target Task
|
14
|
+
# The actual target Task.
|
13
15
|
attr_reader :target
|
14
|
-
# Flag indicating the Link is from a Flow to a Task contained in the Flow.
|
15
|
-
attr_reader :ingress
|
16
16
|
|
17
17
|
# Creates a new Link. This is called from link() and route() methods on
|
18
18
|
# Tasks and Flows.
|
19
|
+
# @param flow_name [Symbol|String] parent flow name to find the target task in or nil for this parent
|
19
20
|
# @param target_name [Symbol] target Task base name
|
20
21
|
# @param op [Symbol] operation to use on the target
|
21
22
|
# @param ingress [true|false] indicates the Link is internal
|
22
23
|
# @return [Link] new Link
|
23
|
-
def initialize(target_name, op
|
24
|
+
def initialize(flow_name, target_name, op)
|
24
25
|
@target_name = target_name
|
26
|
+
@flow_name = flow_name
|
25
27
|
@op = op
|
26
28
|
@target = nil
|
27
|
-
@ingress = ingress
|
28
29
|
end
|
29
30
|
|
30
31
|
# Delivers a package (Box) to the target.
|
@@ -35,7 +36,11 @@ module OFlow
|
|
35
36
|
|
36
37
|
# Returns a string representation of the Link.
|
37
38
|
def to_s()
|
38
|
-
|
39
|
+
if @flow_name.nil?
|
40
|
+
"Link{target_name: #{@target_name}, op: #{op}, target: #{@target}}"
|
41
|
+
else
|
42
|
+
"Link{target_name: #{@flow_name}:#{@target_name}, op: #{op}, target: #{@target}}"
|
43
|
+
end
|
39
44
|
end
|
40
45
|
alias inspect to_s
|
41
46
|
|
data/lib/oflow/task.rb
CHANGED
@@ -6,11 +6,17 @@ module OFlow
|
|
6
6
|
# data by the receive() method. The request is put on a queue and popped off
|
7
7
|
# one at a time and handed to an Actor associatesd with the Task.
|
8
8
|
class Task
|
9
|
-
|
10
|
-
include HasLinks
|
9
|
+
|
11
10
|
include HasErrorHandler
|
12
11
|
include HasLog
|
13
12
|
|
13
|
+
# The name.
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
attr_accessor :bounds
|
17
|
+
attr_accessor :shape
|
18
|
+
attr_accessor :color
|
19
|
+
|
14
20
|
# value of @state that indicates the Task is being created.
|
15
21
|
STARTING = 0
|
16
22
|
# value of @state that indicates the Task is not currently processing requests
|
@@ -36,7 +42,12 @@ module OFlow
|
|
36
42
|
# @param actor_class [Class] _class Class of the Actor to create
|
37
43
|
# @param options [Hash] additional options for the Task or Actor
|
38
44
|
def initialize(flow, name, actor_class, options={})
|
45
|
+
@flow = flow
|
46
|
+
@name = name.to_sym
|
39
47
|
@state = STARTING
|
48
|
+
@bounds = nil # [x, y, w, h] as fixnums
|
49
|
+
@color = nil # [r, g, b] as floats
|
50
|
+
@shape = nil # Rectangle is the default
|
40
51
|
@queue = []
|
41
52
|
@req_mutex = Mutex.new()
|
42
53
|
@req_thread = nil
|
@@ -47,9 +58,10 @@ module OFlow
|
|
47
58
|
@current_req = nil
|
48
59
|
@proc_cnt = 0
|
49
60
|
@loop = nil
|
61
|
+
@links = {}
|
62
|
+
@log = nil
|
63
|
+
@error_handler = nil
|
50
64
|
|
51
|
-
init_name(flow, name)
|
52
|
-
init_links()
|
53
65
|
set_options(options)
|
54
66
|
|
55
67
|
info("Creating actor #{actor_class} with options #{options}.")
|
@@ -57,6 +69,7 @@ module OFlow
|
|
57
69
|
raise Exception.new("#{actor} does not respond to the perform() method.") unless @actor.respond_to?(:perform)
|
58
70
|
|
59
71
|
@state = options.fetch(:state, RUNNING)
|
72
|
+
|
60
73
|
return unless @actor.with_own_thread()
|
61
74
|
|
62
75
|
@loop = Thread.start(self) do |me|
|
@@ -77,7 +90,11 @@ module OFlow
|
|
77
90
|
|
78
91
|
@current_req = req
|
79
92
|
begin
|
80
|
-
|
93
|
+
if debug?
|
94
|
+
debug("perform(#{req.op}, #{req.box.nil? ? '<nil>' : req.box})")
|
95
|
+
else
|
96
|
+
info("perform(#{req.op})")
|
97
|
+
end
|
81
98
|
@actor.perform(req.op, req.box) unless req.nil?
|
82
99
|
rescue Exception => e
|
83
100
|
handle_error(e)
|
@@ -100,17 +117,63 @@ module OFlow
|
|
100
117
|
end
|
101
118
|
end
|
102
119
|
|
120
|
+
# Creates a Link identified by the label that has a target Task and
|
121
|
+
# operation.
|
122
|
+
|
123
|
+
# @param label [Symbol|String] identifer of the Link
|
124
|
+
# @param target [Symbol|String] identifer of the target Task
|
125
|
+
# @param op [Symbol|String] operation to perform on the target Task
|
126
|
+
# @param flow_name [Symbol|String] parent flow name to find the target task in or nil for this parent
|
127
|
+
def link(label, target, op, flow_name=nil)
|
128
|
+
label = label.to_sym unless label.nil?
|
129
|
+
op = op.to_sym unless op.nil?
|
130
|
+
flow_name = flow_name.to_sym unless flow_name.nil?
|
131
|
+
raise ConfigError.new("Link #{label} already exists.") unless @links[label].nil?
|
132
|
+
@links[label] = Link.new(flow_name, target.to_sym, op)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Similar to a full file path. The full_name described the containment of
|
136
|
+
# the named item.
|
137
|
+
# @return [String] full name of item
|
138
|
+
def full_name()
|
139
|
+
if @flow.nil?
|
140
|
+
':' + @name.to_s
|
141
|
+
else
|
142
|
+
@flow.full_name() + ':' + @name.to_s
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns a log Task by looking for that Task as an attribute and then in
|
147
|
+
# the parent Flow.
|
148
|
+
# @return [Task] log Task.
|
149
|
+
def log()
|
150
|
+
return @log unless @log.nil?
|
151
|
+
@flow.log()
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns an error handler Task by looking for that Task as an attribute and then in
|
155
|
+
# the parent Flow.
|
156
|
+
# @return [Task] error handler Task.
|
157
|
+
def error_handler()
|
158
|
+
return @error_handler unless @error_handler.nil?
|
159
|
+
@flow.error_handler()
|
160
|
+
end
|
161
|
+
|
103
162
|
# Returns the state of the Task as a String.
|
104
163
|
# @return [String] String representation of the state
|
105
164
|
def state_string()
|
106
165
|
ss = 'UNKNOWN'
|
107
166
|
case @state
|
167
|
+
when STARTING
|
168
|
+
ss = 'STARTING'
|
108
169
|
when STOPPED
|
109
170
|
ss = 'STOPPED'
|
110
171
|
when RUNNING
|
111
172
|
ss = 'RUNNING'
|
112
173
|
when CLOSING
|
113
174
|
ss = 'CLOSING'
|
175
|
+
when BLOCKED
|
176
|
+
ss = 'BLOCKED'
|
114
177
|
when STEP
|
115
178
|
ss = 'STEP'
|
116
179
|
end
|
@@ -124,7 +187,11 @@ module OFlow
|
|
124
187
|
i = ' ' * indent
|
125
188
|
lines = ["#{i}#{name} (#{actor.class}) {"]
|
126
189
|
@links.each { |local,link|
|
127
|
-
|
190
|
+
if link.flow_name.nil?
|
191
|
+
lines << " #{i}#{local} => :#{link.target_name}:#{link.op}"
|
192
|
+
else
|
193
|
+
lines << " #{i}#{local} => #{link.flow_name}:#{link.target_name}:#{link.op}"
|
194
|
+
end
|
128
195
|
}
|
129
196
|
if 1 <= detail
|
130
197
|
lines << " #{i}queued: #{queue_count()} (#{busy? ? 'busy' : 'idle'})"
|
@@ -281,8 +348,11 @@ module OFlow
|
|
281
348
|
# @param op [Symbol] operation to perform
|
282
349
|
# @param box [Box] contents or data for the request
|
283
350
|
def receive(op, box)
|
284
|
-
|
285
|
-
|
351
|
+
if debug?
|
352
|
+
debug("receive(#{op}, #{box.nil? ? '<nil>' : box}) #{state_string}")
|
353
|
+
else
|
354
|
+
info("receive(#{op})")
|
355
|
+
end
|
286
356
|
return if CLOSING == @state
|
287
357
|
|
288
358
|
raise BlockedError.new() if BLOCKED == @state
|
@@ -317,7 +387,11 @@ module OFlow
|
|
317
387
|
box.freeze() unless box.nil?
|
318
388
|
link = resolve_link(dest)
|
319
389
|
raise LinkError.new(dest) if link.nil? || link.target.nil?
|
320
|
-
|
390
|
+
if debug?
|
391
|
+
debug("shipping #{box} to #{link.target_name}:#{link.op}")
|
392
|
+
else
|
393
|
+
info("shipping to #{link.target_name}:#{link.op}")
|
394
|
+
end
|
321
395
|
link.target.receive(link.op, box)
|
322
396
|
link
|
323
397
|
end
|
@@ -333,6 +407,17 @@ module OFlow
|
|
333
407
|
@req_timeout = options.fetch(:request_timeout, @req_timeout).to_f
|
334
408
|
end
|
335
409
|
|
410
|
+
def set_option(key, value)
|
411
|
+
case key.to_sym()
|
412
|
+
when :max_queue_count
|
413
|
+
@max_queue_count = value.to_i
|
414
|
+
when :request_timeout
|
415
|
+
@req_timeout = value.to_f
|
416
|
+
else
|
417
|
+
@actor.set_option(key, value)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
336
421
|
def _validation_errors()
|
337
422
|
errors = []
|
338
423
|
@links.each_value { |lnk| _check_link(lnk, errors) }
|
@@ -377,6 +462,46 @@ module OFlow
|
|
377
462
|
}
|
378
463
|
end
|
379
464
|
|
465
|
+
# Attempts to find and resolve the Link identified by the label. Resolving a
|
466
|
+
# Link uses the target identifier to find the target Task and save that in
|
467
|
+
# the Link.
|
468
|
+
# @param label [Symbol|String] identifer of the Link
|
469
|
+
# @return [Link] returns the Link for the label
|
470
|
+
def resolve_link(label)
|
471
|
+
label = label.to_sym unless label.nil?
|
472
|
+
lnk = @links[label] || @links[nil]
|
473
|
+
return nil if lnk.nil?
|
474
|
+
set_link_target(lnk) if lnk.target.nil?
|
475
|
+
lnk
|
476
|
+
end
|
477
|
+
|
478
|
+
# Sets the target Task for a Link.
|
479
|
+
# @param lnk [Link] Link to find the target Task for.
|
480
|
+
def set_link_target(lnk)
|
481
|
+
f = @flow
|
482
|
+
f = @flow.env.find_flow(lnk.flow_name) unless lnk.flow_name.nil?
|
483
|
+
raise ConfigError.new("Flow '#{lnk.flow_name}' not found.") if f.nil?
|
484
|
+
lnk.instance_variable_set(:@target, f.find_task(lnk.target_name))
|
485
|
+
end
|
486
|
+
|
487
|
+
# Attempts to find the Link identified by the label.
|
488
|
+
# @param label [Symbol|String] identifer of the Link
|
489
|
+
# @return [Link] returns the Link for the label
|
490
|
+
def find_link(label)
|
491
|
+
label = label.to_sym unless label.nil?
|
492
|
+
@links[label] || @links[nil]
|
493
|
+
end
|
494
|
+
|
495
|
+
# Returns the Links.
|
496
|
+
# @return [Hash] Hash of Links with the keys as Symbols that are the labels of the Links.
|
497
|
+
def links()
|
498
|
+
@links
|
499
|
+
end
|
500
|
+
|
501
|
+
def has_links?()
|
502
|
+
!@links.nil? && !@links.empty?
|
503
|
+
end
|
504
|
+
|
380
505
|
private
|
381
506
|
|
382
507
|
# Internal class used to store information about asynchronous method
|
@@ -404,18 +529,5 @@ module OFlow
|
|
404
529
|
|
405
530
|
end # Request
|
406
531
|
|
407
|
-
class Link
|
408
|
-
attr_reader :name
|
409
|
-
attr_reader :task
|
410
|
-
attr_reader :op
|
411
|
-
|
412
|
-
def initialize(name, task, op)
|
413
|
-
@name = name
|
414
|
-
@task = task
|
415
|
-
@op = op
|
416
|
-
end
|
417
|
-
|
418
|
-
end # Link
|
419
|
-
|
420
532
|
end # Task
|
421
533
|
end # OFlow
|