openwferu 0.9.11 → 0.9.12
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +0 -3
- data/examples/engine_template.rb +10 -4
- data/lib/openwfe/engine/engine.rb +336 -63
- data/lib/openwfe/engine/file_persisted_engine.rb +9 -1
- data/lib/openwfe/expool/errorjournal.rb +379 -0
- data/lib/openwfe/expool/expressionpool.rb +84 -55
- data/lib/openwfe/expool/expstorage.rb +54 -18
- data/lib/openwfe/expool/journal.rb +31 -22
- data/lib/openwfe/expool/yamlexpstorage.rb +57 -16
- data/lib/openwfe/expressions/fe_sequence.rb +1 -1
- data/lib/openwfe/expressions/flowexpression.rb +13 -1
- data/lib/openwfe/expressions/{fe_raw.rb → raw.rb} +5 -2
- data/lib/openwfe/expressions/raw_prog.rb +1 -1
- data/lib/openwfe/expressions/raw_xml.rb +1 -1
- data/lib/openwfe/expressions/time.rb +2 -0
- data/lib/openwfe/flowexpressionid.rb +21 -6
- data/lib/openwfe/omixins.rb +37 -14
- data/lib/openwfe/participants/atomparticipants.rb +6 -5
- data/lib/openwfe/participants/participantmap.rb +2 -0
- data/lib/openwfe/rest/controlclient.rb +1 -0
- data/lib/openwfe/rudefinitions.rb +5 -1
- data/lib/openwfe/storage/yamlfilestorage.rb +7 -3
- data/lib/openwfe/util/otime.rb +1 -1
- data/lib/openwfe/util/safe.rb +14 -0
- data/lib/openwfe/util/scheduler.rb +8 -5
- data/lib/openwfe/util/workqueue.rb +9 -2
- data/lib/openwfe/utils.rb +18 -0
- data/lib/openwfe/version.rb +1 -1
- data/test/atom_test.rb +27 -26
- data/test/fei_test.rb +3 -3
- data/test/file_persistence_test.rb +19 -2
- data/test/ft_0c_testname.rb +6 -3
- data/test/ft_26_load.rb +14 -7
- data/test/ft_26b_load.rb +87 -0
- data/test/ft_26c_load.rb +71 -0
- data/test/ft_27_getflowpos.rb +22 -3
- data/test/ft_34_cancelwfid.rb +3 -2
- data/test/ft_42_environments.rb +3 -1
- data/test/ft_58_ejournal.rb +119 -0
- data/test/ft_59_ps.rb +118 -0
- data/test/ft_60_ecancel.rb +87 -0
- data/test/ft_tests.rb +4 -0
- data/test/hparticipant_test.rb +1 -1
- data/test/orest_test.rb +27 -4
- data/test/param_test.rb +5 -1
- data/test/participant_test.rb +39 -0
- data/test/rake_qtest.rb +3 -5
- data/test/rest_test.rb +2 -2
- data/test/scheduler_test.rb +10 -15
- metadata +10 -3
@@ -0,0 +1,379 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2007, John Mettraux, OpenWFE.org
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# Redistribution and use in source and binary forms, with or without
|
7
|
+
# modification, are permitted provided that the following conditions are met:
|
8
|
+
#
|
9
|
+
# . Redistributions of source code must retain the above copyright notice, this
|
10
|
+
# list of conditions and the following disclaimer.
|
11
|
+
#
|
12
|
+
# . Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
# this list of conditions and the following disclaimer in the documentation
|
14
|
+
# and/or other materials provided with the distribution.
|
15
|
+
#
|
16
|
+
# . Neither the name of the "OpenWFE" nor the names of its contributors may be
|
17
|
+
# used to endorse or promote products derived from this software without
|
18
|
+
# specific prior written permission.
|
19
|
+
#
|
20
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
24
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
25
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
26
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
27
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
28
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
29
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
#++
|
32
|
+
#
|
33
|
+
# $Id$
|
34
|
+
#
|
35
|
+
|
36
|
+
#
|
37
|
+
# "made in Japan"
|
38
|
+
#
|
39
|
+
# John Mettraux at openwfe.org
|
40
|
+
#
|
41
|
+
|
42
|
+
require 'find'
|
43
|
+
require 'fileutils'
|
44
|
+
|
45
|
+
require 'openwfe/service'
|
46
|
+
require 'openwfe/omixins'
|
47
|
+
|
48
|
+
|
49
|
+
module OpenWFE
|
50
|
+
|
51
|
+
#
|
52
|
+
# Encapsulating process error information.
|
53
|
+
#
|
54
|
+
# Instances of this class may be used to replay_at_error
|
55
|
+
#
|
56
|
+
class ProcessError
|
57
|
+
|
58
|
+
#
|
59
|
+
# When did the error occur.
|
60
|
+
#
|
61
|
+
attr_reader :date
|
62
|
+
|
63
|
+
#
|
64
|
+
# The FlowExpressionId instance uniquely pointing at the expression
|
65
|
+
# which 'failed'.
|
66
|
+
#
|
67
|
+
attr_reader :fei
|
68
|
+
|
69
|
+
#
|
70
|
+
# Generally something like :apply or :reply
|
71
|
+
#
|
72
|
+
attr_reader :message
|
73
|
+
|
74
|
+
#
|
75
|
+
# The workitem accompanying the message (apply(workitem) /
|
76
|
+
# reply (workitem)).
|
77
|
+
#
|
78
|
+
attr_reader :workitem
|
79
|
+
|
80
|
+
#
|
81
|
+
# The String stack trace of the error.
|
82
|
+
#
|
83
|
+
attr_reader :stacktrace
|
84
|
+
|
85
|
+
def initialize (*args)
|
86
|
+
|
87
|
+
@date = Time.new
|
88
|
+
@fei, @message, @workitem, @stacktrace = args
|
89
|
+
end
|
90
|
+
|
91
|
+
#
|
92
|
+
# Returns the parent workflow instance id (process id) of this
|
93
|
+
# ProcessError instance.
|
94
|
+
#
|
95
|
+
def wfid
|
96
|
+
@fei.parent_wfid
|
97
|
+
end
|
98
|
+
|
99
|
+
alias :parent_wfid :wfid
|
100
|
+
|
101
|
+
#
|
102
|
+
# Produces a human readable version of the information in the
|
103
|
+
# ProcessError instance.
|
104
|
+
#
|
105
|
+
def to_s
|
106
|
+
s = ""
|
107
|
+
s << "-- #{self.class.name} --\n"
|
108
|
+
s << " date : #{@date}\n"
|
109
|
+
s << " fei : #{@fei}\n"
|
110
|
+
s << " message : #{@message}\n"
|
111
|
+
s << " workitem : ...\n"
|
112
|
+
s << " stacktrace : #{@stacktrace[0, 80]}\n"
|
113
|
+
s
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# This is a base class for all error journal, don't instantiate,
|
119
|
+
# work rather with InMemoryErrorJournal (only for testing envs though),
|
120
|
+
# or YamlErrorJournal.
|
121
|
+
#
|
122
|
+
class ErrorJournal < Service
|
123
|
+
include OwfeServiceLocator
|
124
|
+
include FeiMixin
|
125
|
+
|
126
|
+
def initialize (service_name, application_context)
|
127
|
+
|
128
|
+
super
|
129
|
+
|
130
|
+
get_expression_pool.add_observer(:error) do |event, *args|
|
131
|
+
#
|
132
|
+
# logs each error occuring in the expression pool
|
133
|
+
|
134
|
+
record_error(ProcessError.new(*args))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# Returns true if the given wfid (or fei) (process instance id)
|
140
|
+
# has had errors.
|
141
|
+
#
|
142
|
+
def has_errors? (wfid)
|
143
|
+
|
144
|
+
get_error_log(wfid).size > 0
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Replays the given process instance (wfid or fei) at its last
|
149
|
+
# recorded error.
|
150
|
+
#
|
151
|
+
# There is an optional 'offset' parameter. Its default value is '0'.
|
152
|
+
# Which means that the replay will occur at the last error.
|
153
|
+
#
|
154
|
+
# ejournal.replay_at_last_error('20070630-hiwakuzara', 1)
|
155
|
+
#
|
156
|
+
# Will replay a given process instance at its 1 to last error.
|
157
|
+
#
|
158
|
+
def replay_at_last_error (wfid, offset=0)
|
159
|
+
|
160
|
+
wfid = to_wfid(wfid)
|
161
|
+
|
162
|
+
log = get_error_log(wfid)
|
163
|
+
|
164
|
+
index = (-1 - offset)
|
165
|
+
|
166
|
+
error = log[index]
|
167
|
+
|
168
|
+
raise "no error for process '#{wfid}' at offset #{offset}" \
|
169
|
+
unless error
|
170
|
+
|
171
|
+
replay_at_error error
|
172
|
+
end
|
173
|
+
|
174
|
+
#
|
175
|
+
# Replays at a specific error (fetched with read_error_log()).
|
176
|
+
#
|
177
|
+
def replay_at_error (error)
|
178
|
+
|
179
|
+
get_expression_pool.queue_work(
|
180
|
+
error.message,
|
181
|
+
error.fei,
|
182
|
+
error.workitem)
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# A utility method : given a list of errors, will make sure that for
|
187
|
+
# each flow expression only one expression (the most recent) will get
|
188
|
+
# listed.
|
189
|
+
# Returns a list of errors, from the oldest to the most recent.
|
190
|
+
#
|
191
|
+
# Could be useful when considering a process where multiple replay
|
192
|
+
# attempts failed.
|
193
|
+
#
|
194
|
+
def ErrorJournal.reduce_error_list (errors)
|
195
|
+
|
196
|
+
h = {}
|
197
|
+
|
198
|
+
errors.each do |e|
|
199
|
+
h[e.fei] = e
|
200
|
+
#
|
201
|
+
# last errors do override previous errors for the
|
202
|
+
# same fei
|
203
|
+
end
|
204
|
+
|
205
|
+
h.values.sort do |error_a, error_b|
|
206
|
+
error_a.date <=> error_b.date
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
#
|
212
|
+
# Stores all the errors in a hash... For testing purposes only, like
|
213
|
+
# the InMemoryExpressionStorage.
|
214
|
+
#
|
215
|
+
class InMemoryErrorJournal < ErrorJournal
|
216
|
+
|
217
|
+
def initialize (service_name, application_context)
|
218
|
+
|
219
|
+
super
|
220
|
+
|
221
|
+
@per_processes = {}
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
# Returns a list (older first) of the errors for a process
|
226
|
+
# instance identified by its fei or wfid.
|
227
|
+
#
|
228
|
+
# Will return an empty list if there a no errors for the process
|
229
|
+
# instances.
|
230
|
+
#
|
231
|
+
def get_error_log (wfid)
|
232
|
+
|
233
|
+
wfid = to_wfid(wfid)
|
234
|
+
@per_processes[wfid] or []
|
235
|
+
end
|
236
|
+
|
237
|
+
#
|
238
|
+
# Removes the error log for a process instance.
|
239
|
+
#
|
240
|
+
def remove_error_log (wfid)
|
241
|
+
|
242
|
+
wfid = to_wfid(wfid)
|
243
|
+
@per_processes.delete(wfid)
|
244
|
+
end
|
245
|
+
|
246
|
+
#
|
247
|
+
# Reads all the error logs currently stored.
|
248
|
+
# Returns a hash wfid --> error list.
|
249
|
+
#
|
250
|
+
def get_error_logs
|
251
|
+
|
252
|
+
@per_processes
|
253
|
+
end
|
254
|
+
|
255
|
+
protected
|
256
|
+
|
257
|
+
def record_error (error)
|
258
|
+
|
259
|
+
(@per_processes[error.wfid] ||= []) << error
|
260
|
+
# not that unreadable after all...
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
#
|
265
|
+
# A Journal that only keep track of error in process execution.
|
266
|
+
#
|
267
|
+
class YamlErrorJournal < ErrorJournal
|
268
|
+
|
269
|
+
attr_reader :workdir
|
270
|
+
|
271
|
+
def initialize (service_name, application_context)
|
272
|
+
|
273
|
+
require 'openwfe/storage/yamlextras'
|
274
|
+
|
275
|
+
super
|
276
|
+
|
277
|
+
@workdir = OpenWFE::get_work_directory + "/ejournal"
|
278
|
+
|
279
|
+
FileUtils.makedirs(@workdir) unless File.exist?(@workdir)
|
280
|
+
end
|
281
|
+
|
282
|
+
#
|
283
|
+
# Returns a list (older first) of the errors for a process
|
284
|
+
# instance identified by its fei or wfid.
|
285
|
+
#
|
286
|
+
# Will return an empty list if there a no errors for the process
|
287
|
+
# instances.
|
288
|
+
#
|
289
|
+
def get_error_log (wfid)
|
290
|
+
|
291
|
+
path = get_path(wfid)
|
292
|
+
|
293
|
+
return [] unless File.exist?(path)
|
294
|
+
|
295
|
+
read_error_log_from path
|
296
|
+
end
|
297
|
+
|
298
|
+
#
|
299
|
+
# Copies the error log of a process instance to a give path (and
|
300
|
+
# filename).
|
301
|
+
#
|
302
|
+
# Could be useful when one has to perform replay operations and wants
|
303
|
+
# to keep a copy of the original error[s].
|
304
|
+
#
|
305
|
+
def copy_error_log_to (wfid, path)
|
306
|
+
|
307
|
+
original_path = get_path wfid
|
308
|
+
FileUtils.copy_file original_path, path
|
309
|
+
end
|
310
|
+
|
311
|
+
#
|
312
|
+
# Reads an error log from a specific file (possibly as copied over
|
313
|
+
# via copy_error_log_to()).
|
314
|
+
#
|
315
|
+
def read_error_log_from (path)
|
316
|
+
|
317
|
+
raise "no error log file at #{path}" unless File.exist?(path)
|
318
|
+
|
319
|
+
File.open(path) do |f|
|
320
|
+
s = YAML.load_stream f
|
321
|
+
s.documents
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
#
|
326
|
+
# Removes the error log of a specific process instance.
|
327
|
+
# Could be a good idea after a succesful replay operation.
|
328
|
+
#
|
329
|
+
# 'wfid' may be either a workflow instance id (String) either
|
330
|
+
# a FlowExpressionId instance.
|
331
|
+
#
|
332
|
+
def remove_error_log (wfid)
|
333
|
+
|
334
|
+
File.delete(get_path(wfid))
|
335
|
+
end
|
336
|
+
|
337
|
+
#
|
338
|
+
# Reads all the error logs currently stored.
|
339
|
+
# Returns a hash wfid --> error list.
|
340
|
+
#
|
341
|
+
def get_error_logs
|
342
|
+
|
343
|
+
result = {}
|
344
|
+
|
345
|
+
Find.find(@workdir) do |path|
|
346
|
+
next unless path.endswith(".ejournal")
|
347
|
+
wfid = path[0..-9]
|
348
|
+
log = read_error_log wfid
|
349
|
+
result[wfid] = log
|
350
|
+
end
|
351
|
+
|
352
|
+
result
|
353
|
+
end
|
354
|
+
|
355
|
+
protected
|
356
|
+
|
357
|
+
#
|
358
|
+
# logs the error as a yaml string in an error log file
|
359
|
+
# (there is one error log file per workflow instance).
|
360
|
+
#
|
361
|
+
def record_error (error)
|
362
|
+
|
363
|
+
path = get_path error.fei
|
364
|
+
|
365
|
+
File.open(path, "a+") do |f|
|
366
|
+
f.puts error.to_yaml
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
#
|
371
|
+
# Returns the path to the error log file of a specific process
|
372
|
+
# instance.
|
373
|
+
#
|
374
|
+
def get_path (fei_or_wfid)
|
375
|
+
|
376
|
+
@workdir + "/" + to_wfid(fei_or_wfid) + ".ejournal"
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
@@ -64,44 +64,6 @@ include OpenWFE
|
|
64
64
|
|
65
65
|
module OpenWFE
|
66
66
|
|
67
|
-
#
|
68
|
-
# a small help class for storing monitors provided on demand
|
69
|
-
# to expressions that need them
|
70
|
-
#
|
71
|
-
class MonitorProvider
|
72
|
-
include MonitorMixin, Logging
|
73
|
-
|
74
|
-
MAX_MONITORS = 10000
|
75
|
-
|
76
|
-
def initialize (application_context=nil)
|
77
|
-
super()
|
78
|
-
@application_context = application_context
|
79
|
-
@monitors = LruHash.new(MAX_MONITORS)
|
80
|
-
end
|
81
|
-
|
82
|
-
def [] (key)
|
83
|
-
synchronize do
|
84
|
-
#ldebug { "[] caller :\n" + OpenWFE::caller_to_s(8) }
|
85
|
-
mon = @monitors[key]
|
86
|
-
if not mon
|
87
|
-
#ldebug { "[] creating new Monitor for #{key}" }
|
88
|
-
mon = Monitor.new
|
89
|
-
@monitors[key] = mon
|
90
|
-
else
|
91
|
-
#ldebug { "[] already had Monitor for #{key}" }
|
92
|
-
end
|
93
|
-
return mon
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def delete (key)
|
98
|
-
synchronize do
|
99
|
-
#ldebug { "delete() removing Monitor for #{key}" }
|
100
|
-
@monitors.delete(key)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
67
|
GONE = "gone"
|
106
68
|
|
107
69
|
#
|
@@ -383,18 +345,40 @@ module OpenWFE
|
|
383
345
|
inflowitem
|
384
346
|
end
|
385
347
|
|
348
|
+
#
|
349
|
+
# Cancels the given expression and makes sure to resume the flow
|
350
|
+
# if the expression or one of its children were active.
|
351
|
+
#
|
352
|
+
# If the cancelled branch was not active, this method will take
|
353
|
+
# care of removing the cancelled expression from the parent
|
354
|
+
# expression.
|
355
|
+
#
|
356
|
+
def cancel_expression (exp)
|
357
|
+
|
358
|
+
exp = fetch_expression(exp)
|
359
|
+
|
360
|
+
wi = cancel(exp)
|
361
|
+
|
362
|
+
if wi
|
363
|
+
reply_to_parent(exp, wi, false)
|
364
|
+
else
|
365
|
+
parent_exp = fetch_expression(exp.parent_id)
|
366
|
+
parent_exp.remove_child(exp.fei) if parent_exp
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
386
370
|
#
|
387
371
|
# Given any expression of a process, cancels the complete process
|
388
372
|
# instance.
|
389
373
|
#
|
390
|
-
def
|
374
|
+
def cancel_process (exp_or_wfid)
|
391
375
|
|
392
|
-
|
376
|
+
ldebug { "cancel_process() from #{exp_or_wfid}" }
|
393
377
|
|
394
378
|
root = fetch_root(exp_or_wfid)
|
395
379
|
cancel(root)
|
396
380
|
end
|
397
|
-
alias :
|
381
|
+
alias :cancel_flow :cancel_process
|
398
382
|
|
399
383
|
#
|
400
384
|
# Forgets the given expression (makes sure to substitute its
|
@@ -515,9 +499,9 @@ module OpenWFE
|
|
515
499
|
|
516
500
|
#ldebug { "fetch() exp is of kind #{exp.class}" }
|
517
501
|
|
518
|
-
if exp.kind_of?
|
502
|
+
if exp.kind_of?(FlowExpression)
|
519
503
|
fei = exp.fei
|
520
|
-
elsif not exp.kind_of?
|
504
|
+
elsif not exp.kind_of?(FlowExpressionId)
|
521
505
|
raise \
|
522
506
|
"Cannot fetch expression with key : "+
|
523
507
|
"'#{fei}' (#{fei.class})"
|
@@ -525,7 +509,7 @@ module OpenWFE
|
|
525
509
|
|
526
510
|
#ldebug { "fetch() for #{fei.to_debug_s}" }
|
527
511
|
|
528
|
-
|
512
|
+
[ get_expression_storage()[fei], fei ]
|
529
513
|
end
|
530
514
|
end
|
531
515
|
|
@@ -536,6 +520,7 @@ module OpenWFE
|
|
536
520
|
# has to be reloaded.
|
537
521
|
#
|
538
522
|
def fetch_expression (exp)
|
523
|
+
|
539
524
|
exp, _fei = fetch(exp)
|
540
525
|
exp
|
541
526
|
end
|
@@ -551,6 +536,8 @@ module OpenWFE
|
|
551
536
|
|
552
537
|
exp = fetch_expression(exp_or_wfid)
|
553
538
|
|
539
|
+
raise "did not find root for expression #{exp_or_wfid}" unless exp
|
540
|
+
|
554
541
|
return exp unless exp.parent_id
|
555
542
|
|
556
543
|
fetch_root(fetch_expression(exp.parent_id))
|
@@ -634,7 +621,9 @@ module OpenWFE
|
|
634
621
|
#
|
635
622
|
def engine_environment_id ()
|
636
623
|
synchronize do
|
624
|
+
|
637
625
|
return @eei if @eei
|
626
|
+
|
638
627
|
@eei = FlowExpressionId.new
|
639
628
|
@eei.owfe_version = OPENWFERU_VERSION
|
640
629
|
@eei.engine_id = get_engine.service_name
|
@@ -645,7 +634,7 @@ module OpenWFE
|
|
645
634
|
@eei.workflow_instance_id = '0'
|
646
635
|
@eei.expression_name = EN_ENVIRONMENT
|
647
636
|
@eei.expression_id = '0'
|
648
|
-
|
637
|
+
@eei
|
649
638
|
end
|
650
639
|
end
|
651
640
|
|
@@ -653,11 +642,13 @@ module OpenWFE
|
|
653
642
|
# Returns the list of applied expressions belonging to a given
|
654
643
|
# workflow instance.
|
655
644
|
#
|
656
|
-
def
|
645
|
+
def get_process_stack (wfid)
|
657
646
|
|
658
647
|
raise "please provide a non-nil workflow instance id" \
|
659
648
|
unless wfid
|
660
649
|
|
650
|
+
wfid = to_wfid wfid
|
651
|
+
|
661
652
|
result = []
|
662
653
|
|
663
654
|
get_expression_storage.real_each do |fei, fexp|
|
@@ -666,21 +657,21 @@ module OpenWFE
|
|
666
657
|
next if fexp.kind_of?(RawExpression)
|
667
658
|
next unless fexp.apply_time
|
668
659
|
|
669
|
-
|
670
|
-
|
671
|
-
next if pi != wfid
|
660
|
+
next if fei.parent_wfid != wfid
|
672
661
|
|
673
662
|
result << fexp
|
674
663
|
end
|
675
664
|
|
676
665
|
ldebug do
|
677
|
-
"
|
666
|
+
"process_stack() " +
|
678
667
|
"found #{result.size} exps for flow #{wfid}"
|
679
668
|
end
|
680
669
|
|
681
670
|
result
|
682
671
|
end
|
683
672
|
|
673
|
+
alias :get_flow_stack :get_process_stack
|
674
|
+
|
684
675
|
#
|
685
676
|
# Lists all workflows (processes) currently in the expool (in
|
686
677
|
# the engine).
|
@@ -693,31 +684,32 @@ module OpenWFE
|
|
693
684
|
# "wfid_prefix" allows your to query for specific workflow instance
|
694
685
|
# id prefixes.
|
695
686
|
#
|
696
|
-
def
|
687
|
+
def list_processes (consider_subprocesses=false, wfid_prefix=nil)
|
697
688
|
|
698
689
|
result = []
|
699
690
|
|
700
|
-
|
691
|
+
# collect() would look better
|
692
|
+
|
693
|
+
get_expression_storage.real_each(wfid_prefix) do |fei, fexp|
|
701
694
|
|
702
695
|
next unless fexp.is_a? DefineExpression
|
703
696
|
|
704
697
|
next if not consider_subprocesses and fei.wfid.index(".")
|
705
698
|
|
706
|
-
next unless fei.wfid.match("^#{wfid_prefix}") if wfid_prefix
|
699
|
+
#next unless fei.wfid.match("^#{wfid_prefix}") if wfid_prefix
|
707
700
|
|
708
701
|
result << fexp
|
709
702
|
end
|
710
703
|
|
711
704
|
result
|
712
705
|
end
|
713
|
-
alias :list_processes :list_workflows
|
714
706
|
|
715
707
|
#
|
716
708
|
# Returns the first expression found with the given wfid.
|
717
709
|
#
|
718
710
|
def fetch_expression_with_wfid (wfid)
|
719
711
|
|
720
|
-
|
712
|
+
list_processes(false, wfid)[0]
|
721
713
|
end
|
722
714
|
|
723
715
|
protected
|
@@ -955,7 +947,44 @@ module OpenWFE
|
|
955
947
|
procdef.raw_expression_class.new(
|
956
948
|
fei, nil, nil, @application_context, procdef)
|
957
949
|
end
|
950
|
+
end
|
951
|
+
|
952
|
+
#
|
953
|
+
# a small help class for storing monitors provided on demand
|
954
|
+
# to expressions that need them
|
955
|
+
#
|
956
|
+
class MonitorProvider
|
957
|
+
include MonitorMixin, Logging
|
958
958
|
|
959
|
+
MAX_MONITORS = 10000
|
960
|
+
|
961
|
+
def initialize (application_context=nil)
|
962
|
+
super()
|
963
|
+
@application_context = application_context
|
964
|
+
@monitors = LruHash.new(MAX_MONITORS)
|
965
|
+
end
|
966
|
+
|
967
|
+
def [] (key)
|
968
|
+
synchronize do
|
969
|
+
#ldebug { "[] caller :\n" + OpenWFE::caller_to_s(8) }
|
970
|
+
mon = @monitors[key]
|
971
|
+
if not mon
|
972
|
+
#ldebug { "[] creating new Monitor for #{key}" }
|
973
|
+
mon = Monitor.new
|
974
|
+
@monitors[key] = mon
|
975
|
+
else
|
976
|
+
#ldebug { "[] already had Monitor for #{key}" }
|
977
|
+
end
|
978
|
+
return mon
|
979
|
+
end
|
980
|
+
end
|
981
|
+
|
982
|
+
def delete (key)
|
983
|
+
synchronize do
|
984
|
+
#ldebug { "delete() removing Monitor for #{key}" }
|
985
|
+
@monitors.delete(key)
|
986
|
+
end
|
987
|
+
end
|
959
988
|
end
|
960
989
|
|
961
990
|
end
|