openwferu 0.9.11 → 0.9.12
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.
- 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
data/README.txt
CHANGED
data/examples/engine_template.rb
CHANGED
|
@@ -8,9 +8,6 @@ require 'rubygems'
|
|
|
8
8
|
|
|
9
9
|
require 'openwfe/engine/engine'
|
|
10
10
|
require 'openwfe/engine/file_persisted_engine'
|
|
11
|
-
require 'openwfe/expool/history'
|
|
12
|
-
require 'openwfe/expool/journal'
|
|
13
|
-
require 'openwfe/listeners/listeners'
|
|
14
11
|
require 'openwfe/participants/participants'
|
|
15
12
|
|
|
16
13
|
|
|
@@ -62,9 +59,11 @@ engine = OpenWFE::CachedFilePersistedEngine.new
|
|
|
62
59
|
|
|
63
60
|
# -- process history
|
|
64
61
|
|
|
62
|
+
#require 'openwfe/expool/history'
|
|
63
|
+
|
|
65
64
|
#engine.init_service("history", InMemoryHistory)
|
|
66
65
|
#
|
|
67
|
-
# keeps all process history in an
|
|
66
|
+
# keeps all process history in an array in memory
|
|
68
67
|
# use only for test purposes !
|
|
69
68
|
|
|
70
69
|
#engine.init_service("history", FileHistory)
|
|
@@ -74,12 +73,17 @@ engine = OpenWFE::CachedFilePersistedEngine.new
|
|
|
74
73
|
|
|
75
74
|
# -- process journaling
|
|
76
75
|
|
|
76
|
+
#require 'openwfe/expool/journal'
|
|
77
77
|
#engine.init_service("journal", Journal)
|
|
78
78
|
#
|
|
79
79
|
# activates 'journaling',
|
|
80
80
|
#
|
|
81
81
|
# see http://openwferu.rubyforge.org/journal.html
|
|
82
82
|
#
|
|
83
|
+
# Journaling has a cost in terms of performace.
|
|
84
|
+
# Journaling should be used only in case you might want to migrate
|
|
85
|
+
# [segments of] running processes.
|
|
86
|
+
#
|
|
83
87
|
#engine.application_context[:keep_journals] = true
|
|
84
88
|
#
|
|
85
89
|
# if set to true, the journal of terminated processes will be kept
|
|
@@ -93,6 +97,8 @@ engine = OpenWFE::CachedFilePersistedEngine.new
|
|
|
93
97
|
# participants or LaunchItem requesting the launch of a particular flow)
|
|
94
98
|
#
|
|
95
99
|
|
|
100
|
+
#require 'openwfe/listeners/listeners'
|
|
101
|
+
|
|
96
102
|
#sl = OpenWFE::SocketListener.new(
|
|
97
103
|
# "socket_listener", @engine.application_context, 7008)
|
|
98
104
|
#engine.add_workitem_listener(sl)
|
|
@@ -43,15 +43,18 @@
|
|
|
43
43
|
require 'logger'
|
|
44
44
|
require 'fileutils'
|
|
45
45
|
|
|
46
|
-
require 'openwfe/
|
|
46
|
+
require 'openwfe/omixins'
|
|
47
47
|
require 'openwfe/rudefinitions'
|
|
48
48
|
require 'openwfe/service'
|
|
49
|
+
require 'openwfe/workitem'
|
|
49
50
|
require 'openwfe/util/irb'
|
|
50
51
|
require 'openwfe/util/scheduler'
|
|
51
52
|
require 'openwfe/util/schedulers'
|
|
52
53
|
require 'openwfe/expool/wfidgen'
|
|
53
54
|
require 'openwfe/expool/expressionpool'
|
|
54
55
|
require 'openwfe/expool/expstorage'
|
|
56
|
+
require 'openwfe/expool/errorjournal'
|
|
57
|
+
require 'openwfe/expressions/environment'
|
|
55
58
|
require 'openwfe/expressions/expressionmap'
|
|
56
59
|
require 'openwfe/participants/participantmap'
|
|
57
60
|
|
|
@@ -64,6 +67,7 @@ module OpenWFE
|
|
|
64
67
|
#
|
|
65
68
|
class Engine < Service
|
|
66
69
|
include OwfeServiceLocator
|
|
70
|
+
include FeiMixin
|
|
67
71
|
|
|
68
72
|
#
|
|
69
73
|
# Builds an OpenWFEru engine.
|
|
@@ -82,8 +86,10 @@ module OpenWFE
|
|
|
82
86
|
$OWFE_LOG = application_context[:logger]
|
|
83
87
|
|
|
84
88
|
unless $OWFE_LOG
|
|
89
|
+
#puts "Creating logs in " + FileUtils.pwd
|
|
85
90
|
FileUtils.mkdir("logs") unless File.exist?("logs")
|
|
86
|
-
$OWFE_LOG = Logger.new("logs/openwferu.log")
|
|
91
|
+
$OWFE_LOG = Logger.new("logs/openwferu.log", 10, 1024000)
|
|
92
|
+
$OWFE_LOG.level = Logger::INFO
|
|
87
93
|
end
|
|
88
94
|
|
|
89
95
|
# build order matters.
|
|
@@ -92,14 +98,40 @@ module OpenWFE
|
|
|
92
98
|
# pool and thus needs to be instantiated after it.
|
|
93
99
|
|
|
94
100
|
build_scheduler()
|
|
101
|
+
#
|
|
102
|
+
# for delayed or repetitive executions (it's the engine's clock)
|
|
103
|
+
# see http://openwferu.rubyforge.org/scheduler.html
|
|
95
104
|
|
|
96
105
|
build_expression_map()
|
|
106
|
+
#
|
|
107
|
+
# mapping expression names ('sequence', 'if', 'concurrence',
|
|
108
|
+
# 'when'...) to their implementations (SequenceExpression,
|
|
109
|
+
# IfExpression, ConcurrenceExpression, ...)
|
|
97
110
|
|
|
98
111
|
build_wfid_generator()
|
|
112
|
+
#
|
|
113
|
+
# the workflow instance (process instance) id generator
|
|
114
|
+
# making sure each process instance has a unique identifier
|
|
115
|
+
|
|
99
116
|
build_expression_pool()
|
|
117
|
+
#
|
|
118
|
+
# the core (hairy ball) of the engine
|
|
119
|
+
|
|
100
120
|
build_expression_storage()
|
|
121
|
+
#
|
|
122
|
+
# the engine persistence (persisting the expression instances
|
|
123
|
+
# that make up process instances)
|
|
101
124
|
|
|
102
125
|
build_participant_map()
|
|
126
|
+
#
|
|
127
|
+
# building the services that maps participant names to
|
|
128
|
+
# participant implementations / instances.
|
|
129
|
+
|
|
130
|
+
build_error_journal()
|
|
131
|
+
#
|
|
132
|
+
# builds the error journal (keeping track of failures
|
|
133
|
+
# in business process executions, and an opportunity to
|
|
134
|
+
# fix and replay)
|
|
103
135
|
|
|
104
136
|
linfo { "new() --- engine started --- #{self.object_id}" }
|
|
105
137
|
end
|
|
@@ -136,6 +168,10 @@ module OpenWFE
|
|
|
136
168
|
# either a String containing the URL of the process definition
|
|
137
169
|
# to launch (with an empty LaunchItem created on the fly).
|
|
138
170
|
#
|
|
171
|
+
# The launch object can also be a String containing the XML process
|
|
172
|
+
# definition or directly a class extending OpenWFE::ProcessDefinition
|
|
173
|
+
# (Ruby process definition).
|
|
174
|
+
#
|
|
139
175
|
# Returns the FlowExpressionId instance of the expression at the
|
|
140
176
|
# root of the newly launched process.
|
|
141
177
|
#
|
|
@@ -163,7 +199,12 @@ module OpenWFE
|
|
|
163
199
|
li
|
|
164
200
|
end
|
|
165
201
|
|
|
166
|
-
get_expression_pool.launch launchitem
|
|
202
|
+
fei = get_expression_pool.launch launchitem
|
|
203
|
+
|
|
204
|
+
fei.dup
|
|
205
|
+
#
|
|
206
|
+
# so that users of this launch() method can play with their
|
|
207
|
+
# fei without breaking things
|
|
167
208
|
end
|
|
168
209
|
|
|
169
210
|
#
|
|
@@ -292,6 +333,21 @@ module OpenWFE
|
|
|
292
333
|
get_scheduler.join
|
|
293
334
|
end
|
|
294
335
|
|
|
336
|
+
#
|
|
337
|
+
# Calling this method makes the control flow block until the
|
|
338
|
+
# workflow engine is inactive.
|
|
339
|
+
#
|
|
340
|
+
# TODO : implement idle_for
|
|
341
|
+
#
|
|
342
|
+
def join_until_idle ()
|
|
343
|
+
|
|
344
|
+
storage = get_expression_storage
|
|
345
|
+
|
|
346
|
+
while storage.size > 1
|
|
347
|
+
sleep 1
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
295
351
|
#
|
|
296
352
|
# Enabling the console means that hitting CTRL-C on the window /
|
|
297
353
|
# term / dos box / whatever does run the OpenWFEru engine will
|
|
@@ -346,56 +402,139 @@ module OpenWFE
|
|
|
346
402
|
end
|
|
347
403
|
|
|
348
404
|
#
|
|
405
|
+
# Waits for a given process instance to terminate.
|
|
406
|
+
# The method only exits when the flow terminates, but beware : if
|
|
407
|
+
# the process already terminated, the method will never exit.
|
|
408
|
+
#
|
|
409
|
+
# The parameter can be a FlowExpressionId instance, for example the
|
|
410
|
+
# one given back by a launch(), or directly a workflow instance id
|
|
411
|
+
# (String).
|
|
412
|
+
#
|
|
413
|
+
# This method is mainly used in utests.
|
|
414
|
+
#
|
|
415
|
+
def wait_for (fei_or_wfid)
|
|
416
|
+
|
|
417
|
+
wfid = if fei_or_wfid.kind_of?(FlowExpressionId)
|
|
418
|
+
fei_or_wfid.workflow_instance_id
|
|
419
|
+
else
|
|
420
|
+
fei_or_wfid
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
#Thread.pass
|
|
424
|
+
# #
|
|
425
|
+
# # let the flow 'stabilize' or progress before enquiring
|
|
426
|
+
#fexp = get_expression_pool.fetch_expression(fei)
|
|
427
|
+
#return unless fexp
|
|
428
|
+
#
|
|
429
|
+
# doesn't work well
|
|
430
|
+
|
|
431
|
+
t = Thread.new { Thread.stop }
|
|
432
|
+
|
|
433
|
+
get_expression_pool.add_observer(:terminate) do |channel, fe, wi|
|
|
434
|
+
t.wakeup if fe.fei.workflow_instance_id == wfid
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
ldebug { "wait_for() #{wfid}" }
|
|
438
|
+
|
|
439
|
+
t.join
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
#
|
|
443
|
+
# Returns a hash of ProcessStatus instances. The keys of the hash
|
|
444
|
+
# are workflow instance ids.
|
|
445
|
+
#
|
|
446
|
+
# A ProcessStatus is a description of the state of a process instance
|
|
447
|
+
# it enumerates the expressions where the process is currently
|
|
448
|
+
# located (waiting certainly) and the errors the process currently
|
|
449
|
+
# has (hopefully none).
|
|
450
|
+
#
|
|
451
|
+
def get_process_status (wfid=nil)
|
|
452
|
+
|
|
453
|
+
wfid = to_wfid(wfid) if wfid
|
|
454
|
+
|
|
455
|
+
result = {}
|
|
456
|
+
|
|
457
|
+
get_expression_storage.real_each(wfid) do |fei, fexp|
|
|
458
|
+
next if fexp.kind_of?(Environment)
|
|
459
|
+
next unless fexp.apply_time
|
|
460
|
+
(result[fei.parent_wfid] ||= ProcessStatus.new) << fexp
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
result.values.each do |ps|
|
|
464
|
+
get_error_journal.get_error_log(ps.wfid).each do |error|
|
|
465
|
+
ps << error
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
class << result
|
|
470
|
+
def to_s
|
|
471
|
+
pretty_print_process_status(self)
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
result
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
#--
|
|
349
479
|
# METHODS FROM THE EXPRESSION POOL
|
|
350
480
|
#
|
|
351
481
|
# These methods are 'proxy' to method found in the expression pool.
|
|
352
482
|
# They are made available here for a simpler model.
|
|
353
|
-
|
|
483
|
+
#++
|
|
354
484
|
|
|
355
485
|
#
|
|
356
486
|
# Returns the list of applied expressions belonging to a given
|
|
357
487
|
# workflow instance.
|
|
358
488
|
# May be used to determine where a process instance currently is.
|
|
359
489
|
#
|
|
360
|
-
|
|
361
|
-
|
|
490
|
+
# This method returns all the expressions (the stack) a process
|
|
491
|
+
# went through to reach its current state.
|
|
492
|
+
#
|
|
493
|
+
def get_process_stack (workflow_instance_id)
|
|
494
|
+
|
|
495
|
+
get_expression_pool.get_process_stack(workflow_instance_id)
|
|
362
496
|
end
|
|
363
|
-
alias :
|
|
497
|
+
alias :get_flow_stack :get_process_stack
|
|
364
498
|
|
|
365
499
|
#
|
|
366
|
-
# Lists all
|
|
500
|
+
# Lists all workflow (process) instances currently in the expool (in
|
|
367
501
|
# the engine).
|
|
368
502
|
# This method will return a list of "process-definition" expressions
|
|
369
503
|
# (root of flows).
|
|
370
504
|
#
|
|
371
|
-
# If consider_subprocesses is set to true, "process-definition"
|
|
372
|
-
# expressions of subprocesses will be returned as well.
|
|
373
|
-
#
|
|
374
505
|
# "wfid_prefix" allows your to query for specific workflow instance
|
|
375
506
|
# id prefixes.
|
|
376
507
|
#
|
|
377
|
-
|
|
508
|
+
# If consider_subprocesses is set to true, "process-definition"
|
|
509
|
+
# expressions of subprocesses will be returned as well.
|
|
510
|
+
#
|
|
511
|
+
def list_processes (consider_subprocesses=false, wfid_prefix=nil)
|
|
378
512
|
|
|
379
|
-
get_expression_pool.
|
|
513
|
+
get_expression_pool.list_processes(
|
|
380
514
|
consider_subprocesses, wfid_prefix)
|
|
381
515
|
end
|
|
382
|
-
alias :
|
|
516
|
+
alias :list_workflows :list_processes
|
|
383
517
|
|
|
384
518
|
#
|
|
385
519
|
# Given any expression of a process, cancels the complete process
|
|
386
520
|
# instance.
|
|
387
521
|
#
|
|
388
|
-
def
|
|
389
|
-
|
|
522
|
+
def cancel_process (exp_or_wfid)
|
|
523
|
+
|
|
524
|
+
get_expression_pool.cancel_process(exp_or_wfid)
|
|
390
525
|
end
|
|
391
|
-
alias :
|
|
526
|
+
alias :cancel_flow :cancel_process
|
|
392
527
|
|
|
393
528
|
#
|
|
394
529
|
# Cancels the given expression (and its children if any)
|
|
395
530
|
# (warning : advanced method)
|
|
396
531
|
#
|
|
532
|
+
# Cancelling the root expression of a process is equivalent to
|
|
533
|
+
# cancelling the process.
|
|
534
|
+
#
|
|
397
535
|
def cancel_expression (exp_or_fei)
|
|
398
|
-
|
|
536
|
+
|
|
537
|
+
get_expression_pool.cancel_expression(exp_or_fei)
|
|
399
538
|
end
|
|
400
539
|
|
|
401
540
|
#
|
|
@@ -403,53 +542,16 @@ module OpenWFE
|
|
|
403
542
|
# (warning : advanced method)
|
|
404
543
|
#
|
|
405
544
|
def forget_expression (exp_or_fei)
|
|
406
|
-
get_expression_pool.forget(exp_or_fei)
|
|
407
|
-
end
|
|
408
545
|
|
|
409
|
-
|
|
410
|
-
# Waits for a given process instance to terminate.
|
|
411
|
-
# The method only exits when the flow terminates, but beware : if
|
|
412
|
-
# the process already terminated, the method will never exit.
|
|
413
|
-
#
|
|
414
|
-
# The parameter can be a FlowExpressionId instance, for example the
|
|
415
|
-
# one given back by a launch(), or directly a workflow instance id
|
|
416
|
-
# (String).
|
|
417
|
-
#
|
|
418
|
-
# This method is mainly used in utests.
|
|
419
|
-
#
|
|
420
|
-
def wait_for (fei_or_wfid)
|
|
421
|
-
|
|
422
|
-
wfid = if fei_or_wfid.kind_of?(FlowExpressionId)
|
|
423
|
-
fei_or_wfid.workflow_instance_id
|
|
424
|
-
else
|
|
425
|
-
fei_or_wfid
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
#Thread.pass
|
|
429
|
-
# #
|
|
430
|
-
# # let the flow 'stabilize' or progress before enquiring
|
|
431
|
-
#fexp = get_expression_pool.fetch_expression(fei)
|
|
432
|
-
#return unless fexp
|
|
433
|
-
#
|
|
434
|
-
# doesn't work well
|
|
435
|
-
|
|
436
|
-
t = Thread.new { Thread.stop }
|
|
437
|
-
|
|
438
|
-
get_expression_pool.add_observer(:terminate) do |channel, fe, wi|
|
|
439
|
-
t.wakeup if fe.fei.workflow_instance_id == wfid
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
ldebug { "wait_for() #{wfid}" }
|
|
443
|
-
|
|
444
|
-
t.join
|
|
546
|
+
get_expression_pool.forget(exp_or_fei)
|
|
445
547
|
end
|
|
446
548
|
|
|
447
549
|
protected
|
|
448
550
|
|
|
449
|
-
|
|
551
|
+
#--
|
|
450
552
|
# the following methods may get overridden upon extension
|
|
451
553
|
# see for example file_persisted_engine.rb
|
|
452
|
-
|
|
554
|
+
#++
|
|
453
555
|
|
|
454
556
|
def build_expression_map
|
|
455
557
|
|
|
@@ -458,13 +560,14 @@ module OpenWFE
|
|
|
458
560
|
# the expression map is not a Service anymore,
|
|
459
561
|
# it's a simple instance (that will be reused in other
|
|
460
562
|
# OpenWFEru components)
|
|
461
|
-
|
|
462
|
-
#ldebug do
|
|
463
|
-
# "build_expression_map() :\n" +
|
|
464
|
-
# get_expression_map.to_s
|
|
465
|
-
#end
|
|
466
563
|
end
|
|
467
564
|
|
|
565
|
+
#
|
|
566
|
+
# This implementation builds a KotobaWfidGenerator instance and
|
|
567
|
+
# binds it in the engine context.
|
|
568
|
+
# There are other WfidGeneration implementations available, like
|
|
569
|
+
# UuidWfidGenerator or FieldWfidGenerator.
|
|
570
|
+
#
|
|
468
571
|
def build_wfid_generator
|
|
469
572
|
|
|
470
573
|
#init_service S_WFID_GENERATOR, DefaultWfidGenerator
|
|
@@ -479,26 +582,196 @@ module OpenWFE
|
|
|
479
582
|
# the field "wfid" of the LaunchItem.
|
|
480
583
|
end
|
|
481
584
|
|
|
585
|
+
#
|
|
586
|
+
# Builds the OpenWFEru expression pool (the core of the engine)
|
|
587
|
+
# and binds it in the engine context.
|
|
588
|
+
# There is only one implementation of the expression pool, so
|
|
589
|
+
# this method is usually never overriden.
|
|
590
|
+
#
|
|
482
591
|
def build_expression_pool
|
|
483
592
|
|
|
484
593
|
init_service(S_EXPRESSION_POOL, ExpressionPool)
|
|
485
594
|
end
|
|
486
595
|
|
|
596
|
+
#
|
|
597
|
+
# The implementation here builds an InMemoryExpressionStorage
|
|
598
|
+
# instance.
|
|
599
|
+
#
|
|
600
|
+
# See FilePersistedEngine or CachedFilePersistedEngine for
|
|
601
|
+
# overrides of this method.
|
|
602
|
+
#
|
|
487
603
|
def build_expression_storage
|
|
488
604
|
|
|
489
605
|
init_service(S_EXPRESSION_STORAGE, InMemoryExpressionStorage)
|
|
490
606
|
end
|
|
491
607
|
|
|
608
|
+
#
|
|
609
|
+
# The ParticipantMap is a mapping between participant names
|
|
610
|
+
# (well rather regular expressions) and participant implementations
|
|
611
|
+
# (see http://openwferu.rubyforge.org/participants.html)
|
|
612
|
+
#
|
|
492
613
|
def build_participant_map
|
|
493
614
|
|
|
494
615
|
init_service(S_PARTICIPANT_MAP, ParticipantMap)
|
|
495
616
|
end
|
|
496
617
|
|
|
618
|
+
#
|
|
619
|
+
# There is only one Scheduler implementation, that's the one
|
|
620
|
+
# built and bound here.
|
|
621
|
+
#
|
|
497
622
|
def build_scheduler
|
|
498
623
|
|
|
499
624
|
init_service(S_SCHEDULER, SchedulerService)
|
|
500
625
|
end
|
|
501
626
|
|
|
627
|
+
#
|
|
628
|
+
# The default implementation of this method uses an
|
|
629
|
+
# InMemoryErrorJournal (do not use in production).
|
|
630
|
+
#
|
|
631
|
+
def build_error_journal
|
|
632
|
+
|
|
633
|
+
init_service(S_ERROR_JOURNAL, InMemoryErrorJournal)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
#
|
|
639
|
+
# ProcessStatus gathers information about the status of a business
|
|
640
|
+
# process instance.
|
|
641
|
+
#
|
|
642
|
+
# The status is mainly a list of expressions and a hash of errors.
|
|
643
|
+
#
|
|
644
|
+
# Instances of this class are obtained via Engine.process_status().
|
|
645
|
+
#
|
|
646
|
+
class ProcessStatus
|
|
647
|
+
|
|
648
|
+
#
|
|
649
|
+
# the String workflow instance id of the Process.
|
|
650
|
+
#
|
|
651
|
+
attr_reader :wfid
|
|
652
|
+
|
|
653
|
+
#
|
|
654
|
+
# The list of the expressions currently active in the process instance.
|
|
655
|
+
#
|
|
656
|
+
# For instance, if your process definition is currently in a
|
|
657
|
+
# concurrence, more than one expressions may be listed here.
|
|
658
|
+
#
|
|
659
|
+
attr_reader :expressions
|
|
660
|
+
|
|
661
|
+
#
|
|
662
|
+
# a hash whose values are ProcessError instances, the keys
|
|
663
|
+
# are FlowExpressionId instances (fei) (identifying the expressions
|
|
664
|
+
# that are concerned with the error)
|
|
665
|
+
#
|
|
666
|
+
attr_reader :errors
|
|
667
|
+
|
|
668
|
+
def initialize
|
|
669
|
+
@wfid = nil
|
|
670
|
+
@expressions = []
|
|
671
|
+
@errors = {}
|
|
672
|
+
end
|
|
673
|
+
|
|
674
|
+
#
|
|
675
|
+
# this method is used by Engine.get_process_status() when
|
|
676
|
+
# it prepares its results.
|
|
677
|
+
#
|
|
678
|
+
def << (item)
|
|
679
|
+
|
|
680
|
+
if item.kind_of?(FlowExpression)
|
|
681
|
+
add_expression item
|
|
682
|
+
else
|
|
683
|
+
add_error item
|
|
684
|
+
end
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
#
|
|
688
|
+
# A String representation, handy for debugging, quick viewing.
|
|
689
|
+
#
|
|
690
|
+
def to_s
|
|
691
|
+
s = ""
|
|
692
|
+
s << "-- #{self.class.name} --\n"
|
|
693
|
+
s << " wfid : #{@wfid}\n"
|
|
694
|
+
s << " expressions :\n"
|
|
695
|
+
@expressions.each do |fexp|
|
|
696
|
+
s << " #{fexp.fei}\n"
|
|
697
|
+
end
|
|
698
|
+
s << " errors : #{@errors.size}"
|
|
699
|
+
s
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
protected
|
|
703
|
+
|
|
704
|
+
def add_expression (fexp)
|
|
705
|
+
|
|
706
|
+
set_wfid fexp.fei.parent_wfid
|
|
707
|
+
|
|
708
|
+
#@expressions << fexp
|
|
709
|
+
|
|
710
|
+
exps = @expressions
|
|
711
|
+
@expressions = []
|
|
712
|
+
|
|
713
|
+
added = false
|
|
714
|
+
@expressions = exps.collect do |fe|
|
|
715
|
+
if added or fe.fei.wfid != fexp.fei.wfid
|
|
716
|
+
fe
|
|
717
|
+
else
|
|
718
|
+
if OpenWFE::starts_with(fexp.fei.expid, fe.fei.expid)
|
|
719
|
+
added = true
|
|
720
|
+
fexp
|
|
721
|
+
elsif OpenWFE::starts_with(fe.fei.expid, fexp.fei.expid)
|
|
722
|
+
added = true
|
|
723
|
+
fe
|
|
724
|
+
else
|
|
725
|
+
fe
|
|
726
|
+
end
|
|
727
|
+
end
|
|
728
|
+
end
|
|
729
|
+
@expressions << fexp unless added
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
def add_error (error)
|
|
733
|
+
@errors[error.fei] = error
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
def set_wfid (wfid)
|
|
737
|
+
|
|
738
|
+
return if @wfid
|
|
739
|
+
@wfid = wfid
|
|
740
|
+
end
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
#
|
|
744
|
+
# Renders a nice, terminal oriented, representation of an
|
|
745
|
+
# Engine.get_process_status() result.
|
|
746
|
+
#
|
|
747
|
+
# You usually directly benefit from this when doing
|
|
748
|
+
#
|
|
749
|
+
# puts engine.get_process_status.to_s
|
|
750
|
+
#
|
|
751
|
+
def pretty_print_process_status (ps)
|
|
752
|
+
|
|
753
|
+
s = ""
|
|
754
|
+
s << "process_id | name | rev | brn | err\n"
|
|
755
|
+
s << "--------------------+-------------------+---------+-----+-----\n"
|
|
756
|
+
|
|
757
|
+
ps.keys.sort.each do |wfid|
|
|
758
|
+
|
|
759
|
+
status = ps[wfid]
|
|
760
|
+
fexp = status.expressions[0]
|
|
761
|
+
ffei = fexp.fei
|
|
762
|
+
|
|
763
|
+
s << "%-19s" % wfid[0, 19]
|
|
764
|
+
s << " | "
|
|
765
|
+
s << "%-17s" % ffei.workflow_definition_name[0, 17]
|
|
766
|
+
s << " | "
|
|
767
|
+
s << "%-7s" % ffei.workflow_definition_revision[0, 7]
|
|
768
|
+
s << " | "
|
|
769
|
+
s << "%3s" % status.expressions.size.to_s[0, 3]
|
|
770
|
+
s << " | "
|
|
771
|
+
s << "%3s" % status.errors.size.to_s[0, 3]
|
|
772
|
+
s << "\n"
|
|
773
|
+
end
|
|
774
|
+
s
|
|
502
775
|
end
|
|
503
776
|
|
|
504
777
|
end
|
|
@@ -68,6 +68,14 @@ module OpenWFE
|
|
|
68
68
|
|
|
69
69
|
init_service(S_EXPRESSION_STORAGE, YamlFileExpressionStorage)
|
|
70
70
|
end
|
|
71
|
+
|
|
72
|
+
#
|
|
73
|
+
# Uses a file persisted error journal.
|
|
74
|
+
#
|
|
75
|
+
def build_error_journal ()
|
|
76
|
+
|
|
77
|
+
init_service(S_ERROR_JOURNAL, YamlErrorJournal)
|
|
78
|
+
end
|
|
71
79
|
end
|
|
72
80
|
|
|
73
81
|
#
|
|
@@ -78,7 +86,7 @@ module OpenWFE
|
|
|
78
86
|
# like 'sleep', 'cron', ... But if you do it before registering the
|
|
79
87
|
# participants you'll end up with broken processes.
|
|
80
88
|
#
|
|
81
|
-
class CachedFilePersistedEngine <
|
|
89
|
+
class CachedFilePersistedEngine < FilePersistedEngine
|
|
82
90
|
|
|
83
91
|
protected
|
|
84
92
|
|