ruote 0.9.18
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 +24 -0
- data/bin/validate-workflow.rb +89 -0
- data/examples/about_state.rb +81 -0
- data/examples/bigflow.rb +19 -0
- data/examples/csv_weather.rb +23 -0
- data/examples/engine_template.rb +247 -0
- data/examples/flowtracing.rb +24 -0
- data/examples/homeworkreview.rb +68 -0
- data/examples/kotoba.rb +22 -0
- data/examples/mano_tracker.rb +172 -0
- data/examples/openwferu.rb +58 -0
- data/examples/quotereporter.rb +157 -0
- data/examples/scheduler_cron_usage.rb +48 -0
- data/examples/scheduler_usage.rb +56 -0
- data/lib/openwfe.rb +41 -0
- data/lib/openwfe/contextual.rb +111 -0
- data/lib/openwfe/def.rb +46 -0
- data/lib/openwfe/engine.rb +37 -0
- data/lib/openwfe/engine/engine.rb +756 -0
- data/lib/openwfe/engine/expool_methods.rb +172 -0
- data/lib/openwfe/engine/file_persisted_engine.rb +105 -0
- data/lib/openwfe/engine/participant_methods.rb +133 -0
- data/lib/openwfe/engine/status_methods.rb +353 -0
- data/lib/openwfe/engine/update_exp_methods.rb +112 -0
- data/lib/openwfe/exceptions.rb +51 -0
- data/lib/openwfe/expool/errorjournal.rb +476 -0
- data/lib/openwfe/expool/expressionpool.rb +1144 -0
- data/lib/openwfe/expool/expstorage.rb +403 -0
- data/lib/openwfe/expool/history.rb +174 -0
- data/lib/openwfe/expool/journal.rb +224 -0
- data/lib/openwfe/expool/journal_replay.rb +321 -0
- data/lib/openwfe/expool/parser.rb +242 -0
- data/lib/openwfe/expool/representation.rb +121 -0
- data/lib/openwfe/expool/threadedexpstorage.rb +188 -0
- data/lib/openwfe/expool/wfidgen.rb +388 -0
- data/lib/openwfe/expool/yamlexpstorage.rb +224 -0
- data/lib/openwfe/expressions/condition.rb +244 -0
- data/lib/openwfe/expressions/environment.rb +246 -0
- data/lib/openwfe/expressions/expressionmap.rb +258 -0
- data/lib/openwfe/expressions/fe_cancel.rb +109 -0
- data/lib/openwfe/expressions/fe_command.rb +241 -0
- data/lib/openwfe/expressions/fe_concurrence.rb +662 -0
- data/lib/openwfe/expressions/fe_cron.rb +259 -0
- data/lib/openwfe/expressions/fe_cursor.rb +259 -0
- data/lib/openwfe/expressions/fe_define.rb +192 -0
- data/lib/openwfe/expressions/fe_do.rb +168 -0
- data/lib/openwfe/expressions/fe_equals.rb +291 -0
- data/lib/openwfe/expressions/fe_filter.rb +129 -0
- data/lib/openwfe/expressions/fe_filter_definition.rb +168 -0
- data/lib/openwfe/expressions/fe_fqv.rb +250 -0
- data/lib/openwfe/expressions/fe_if.rb +303 -0
- data/lib/openwfe/expressions/fe_iterator.rb +145 -0
- data/lib/openwfe/expressions/fe_listen.rb +371 -0
- data/lib/openwfe/expressions/fe_losfor.rb +111 -0
- data/lib/openwfe/expressions/fe_misc.rb +421 -0
- data/lib/openwfe/expressions/fe_participant.rb +269 -0
- data/lib/openwfe/expressions/fe_reserve.rb +212 -0
- data/lib/openwfe/expressions/fe_save.rb +274 -0
- data/lib/openwfe/expressions/fe_sequence.rb +117 -0
- data/lib/openwfe/expressions/fe_set.rb +139 -0
- data/lib/openwfe/expressions/fe_sleep.rb +166 -0
- data/lib/openwfe/expressions/fe_step.rb +159 -0
- data/lib/openwfe/expressions/fe_subprocess.rb +168 -0
- data/lib/openwfe/expressions/fe_timeout.rb +127 -0
- data/lib/openwfe/expressions/fe_wait.rb +78 -0
- data/lib/openwfe/expressions/fe_when.rb +142 -0
- data/lib/openwfe/expressions/filter.rb +104 -0
- data/lib/openwfe/expressions/flowexpression.rb +847 -0
- data/lib/openwfe/expressions/iterator.rb +221 -0
- data/lib/openwfe/expressions/merge.rb +84 -0
- data/lib/openwfe/expressions/raw.rb +547 -0
- data/lib/openwfe/expressions/rprocdef.rb +375 -0
- data/lib/openwfe/expressions/time.rb +333 -0
- data/lib/openwfe/expressions/timeout.rb +178 -0
- data/lib/openwfe/expressions/value.rb +126 -0
- data/lib/openwfe/filterdef.rb +259 -0
- data/lib/openwfe/flowexpressionid.rb +357 -0
- data/lib/openwfe/listeners/listener.rb +97 -0
- data/lib/openwfe/listeners/listeners.rb +139 -0
- data/lib/openwfe/listeners/socketlisteners.rb +272 -0
- data/lib/openwfe/logging.rb +122 -0
- data/lib/openwfe/omixins.rb +95 -0
- data/lib/openwfe/orest/controlclient.rb +119 -0
- data/lib/openwfe/orest/definitions.rb +113 -0
- data/lib/openwfe/orest/exception.rb +60 -0
- data/lib/openwfe/orest/oldrestservlet.rb +279 -0
- data/lib/openwfe/orest/osocket.rb +148 -0
- data/lib/openwfe/orest/restclient.rb +176 -0
- data/lib/openwfe/orest/workitem.rb +206 -0
- data/lib/openwfe/orest/worklistclient.rb +272 -0
- data/lib/openwfe/orest/xmlcodec.rb +670 -0
- data/lib/openwfe/participants.rb +38 -0
- data/lib/openwfe/participants/enoparticipants.rb +230 -0
- data/lib/openwfe/participants/participant.rb +141 -0
- data/lib/openwfe/participants/participantmap.rb +249 -0
- data/lib/openwfe/participants/participants.rb +407 -0
- data/lib/openwfe/participants/soapparticipants.rb +135 -0
- data/lib/openwfe/participants/socketparticipants.rb +202 -0
- data/lib/openwfe/participants/storeparticipants.rb +254 -0
- data/lib/openwfe/rudefinitions.rb +130 -0
- data/lib/openwfe/service.rb +103 -0
- data/lib/openwfe/storage/yamlcustom.rb +106 -0
- data/lib/openwfe/storage/yamlfilestorage.rb +245 -0
- data/lib/openwfe/tools/flowtracer.rb +81 -0
- data/lib/openwfe/util/dollar.rb +217 -0
- data/lib/openwfe/util/irb.rb +86 -0
- data/lib/openwfe/util/observable.rb +144 -0
- data/lib/openwfe/util/ometa.rb +62 -0
- data/lib/openwfe/util/workqueue.rb +124 -0
- data/lib/openwfe/util/xml.rb +418 -0
- data/lib/openwfe/utils.rb +554 -0
- data/lib/openwfe/version.rb +37 -0
- data/lib/openwfe/workitem.rb +499 -0
- data/lib/openwfe/worklist/oldrest.rb +244 -0
- data/lib/openwfe/worklist/storelocks.rb +293 -0
- data/lib/openwfe/worklist/storeparticipant.rb +44 -0
- data/lib/openwfe/worklist/worklist.rb +297 -0
- data/test/README.txt +27 -0
- data/test/back_0916_test.rb +111 -0
- data/test/bm/bm_1_xml_vs_prog.rb +56 -0
- data/test/bm/bm_2_step.rb +109 -0
- data/test/bm/ft_0f_5ms.rb +35 -0
- data/test/bm/ft_26_load.rb +210 -0
- data/test/bm/ft_26b_load.rb +86 -0
- data/test/bm/ft_26c_load.rb +97 -0
- data/test/bm/ft_26d_load.rb +97 -0
- data/test/bm/ft_recu.rb +71 -0
- data/test/clone_test.rb +122 -0
- data/test/concurrence_test.rb +77 -0
- data/test/condition_test.rb +155 -0
- data/test/console_test.rb +12 -0
- data/test/cron_ltest.rb +15 -0
- data/test/description_test.rb +87 -0
- data/test/eno_test.rb +76 -0
- data/test/expmap_test.rb +54 -0
- data/test/expool_20031219_0916.tgz +0 -0
- data/test/fe_lookup_att_test.rb +62 -0
- data/test/fei_test.rb +181 -0
- data/test/file_persisted_engine_test.rb +64 -0
- data/test/file_persistence_test.rb +134 -0
- data/test/filep_cancel_test.rb +123 -0
- data/test/filter_test.rb +109 -0
- data/test/flowtestbase.rb +351 -0
- data/test/ft_0.rb +68 -0
- data/test/ft_0b_sequence.rb +36 -0
- data/test/ft_0c_testname.rb +33 -0
- data/test/ft_0d_participant.rb +30 -0
- data/test/ft_0e_multibody.rb +34 -0
- data/test/ft_10_loop.rb +134 -0
- data/test/ft_11_ppd.rb +415 -0
- data/test/ft_11b_ppd.rb +54 -0
- data/test/ft_12_blockparticipant.rb +97 -0
- data/test/ft_13_eno.rb +52 -0
- data/test/ft_14_subprocess.rb +88 -0
- data/test/ft_14b_subprocess.rb +192 -0
- data/test/ft_14c_subprocess.rb +68 -0
- data/test/ft_15_iterator.rb +216 -0
- data/test/ft_15b_iterator.rb +74 -0
- data/test/ft_16_fqv.rb +73 -0
- data/test/ft_17_condition.rb +84 -0
- data/test/ft_18_pname.rb +56 -0
- data/test/ft_1_unset.rb +175 -0
- data/test/ft_1b_unset.rb +39 -0
- data/test/ft_20_cron.rb +53 -0
- data/test/ft_21_cron.rb +87 -0
- data/test/ft_21b_cron_pause.rb +82 -0
- data/test/ft_22_history.rb +74 -0
- data/test/ft_23_when.rb +77 -0
- data/test/ft_23b_when.rb +70 -0
- data/test/ft_23c_wait.rb +80 -0
- data/test/ft_23d_cww.rb +58 -0
- data/test/ft_24_def.rb +44 -0
- data/test/ft_25_cancel.rb +89 -0
- data/test/ft_27_getflowpos.rb +147 -0
- data/test/ft_28_fileparticipant.rb +63 -0
- data/test/ft_29_httprb.rb +106 -0
- data/test/ft_2_concurrence.rb +135 -0
- data/test/ft_2b_concurrence.rb +188 -0
- data/test/ft_2c_concurrence.rb +64 -0
- data/test/ft_30_socketlistener.rb +203 -0
- data/test/ft_31_flowname.rb +40 -0
- data/test/ft_32_journal.rb +91 -0
- data/test/ft_32c_journal.rb +102 -0
- data/test/ft_32d_journal.rb +84 -0
- data/test/ft_33_description.rb +107 -0
- data/test/ft_34_cancelwfid.rb +80 -0
- data/test/ft_35_localdefs.rb +75 -0
- data/test/ft_36_subprocids.rb +97 -0
- data/test/ft_37_pnames.rb +70 -0
- data/test/ft_38_tag.rb +127 -0
- data/test/ft_38b_tag.rb +161 -0
- data/test/ft_38c_tag.rb +100 -0
- data/test/ft_39_reserve.rb +63 -0
- data/test/ft_39b_reserve.rb +84 -0
- data/test/ft_3_equals.rb +170 -0
- data/test/ft_3b_lookup_vf.rb +83 -0
- data/test/ft_40_defined.rb +61 -0
- data/test/ft_41_case.rb +110 -0
- data/test/ft_42_environments.rb +75 -0
- data/test/ft_43_pat10.rb +85 -0
- data/test/ft_44_save.rb +70 -0
- data/test/ft_44b_restore.rb +212 -0
- data/test/ft_45_citerator.rb +214 -0
- data/test/ft_46_pparams.rb +62 -0
- data/test/ft_47_filter.rb +160 -0
- data/test/ft_48_fe_filter.rb +88 -0
- data/test/ft_49_condition.rb +126 -0
- data/test/ft_4_misc.rb +237 -0
- data/test/ft_50_xml_attribute.rb +155 -0
- data/test/ft_51_stack.rb +55 -0
- data/test/ft_52_obs_participant.rb +123 -0
- data/test/ft_53_null_noop_participant.rb +62 -0
- data/test/ft_54_listen.rb +288 -0
- data/test/ft_54b_listen.rb +66 -0
- data/test/ft_54c_listen.rb +99 -0
- data/test/ft_55_ptimeout.rb +59 -0
- data/test/ft_56_timeout.rb +59 -0
- data/test/ft_57_a.rb +145 -0
- data/test/ft_58_ejournal.rb +151 -0
- data/test/ft_59_ps.rb +150 -0
- data/test/ft_59b_ps_for_pat.rb +58 -0
- data/test/ft_5_time.rb +118 -0
- data/test/ft_60_ecancel.rb +161 -0
- data/test/ft_61_elsub.rb +51 -0
- data/test/ft_62_procparticipant.rb +71 -0
- data/test/ft_63_pause.rb +124 -0
- data/test/ft_64_alias.rb +102 -0
- data/test/ft_64_clone.rb +69 -0
- data/test/ft_65_stringlaunch.rb +59 -0
- data/test/ft_66_subforget.rb +70 -0
- data/test/ft_67_schedlaunch.rb +116 -0
- data/test/ft_68_ifparticipant.rb +70 -0
- data/test/ft_69_cancelmissing.rb +51 -0
- data/test/ft_6_lambda.rb +64 -0
- data/test/ft_70_lookupvar.rb +55 -0
- data/test/ft_71_log.rb +60 -0
- data/test/ft_72_lookup_processes.rb +76 -0
- data/test/ft_73_cancel_sub.rb +139 -0
- data/test/ft_74_block_and_workitem_dup.rb +63 -0
- data/test/ft_75_ruby_attributes.rb +87 -0
- data/test/ft_76_merge_isolate.rb +88 -0
- data/test/ft_77_segments.rb +35 -0
- data/test/ft_78_eval.rb +150 -0
- data/test/ft_79_tticket.rb +187 -0
- data/test/ft_79b_tticket.rb +172 -0
- data/test/ft_79c_outcome.rb +56 -0
- data/test/ft_7_lose.rb +104 -0
- data/test/ft_7b_lose.rb +78 -0
- data/test/ft_80_spname.rb +91 -0
- data/test/ft_81_exp.rb +60 -0
- data/test/ft_82_trecu.rb +46 -0
- data/test/ft_83_badpause.rb +58 -0
- data/test/ft_84_updateexp.rb +198 -0
- data/test/ft_85_dolhash.rb +43 -0
- data/test/ft_86_dollar_fv.rb +68 -0
- data/test/ft_87_define.rb +74 -0
- data/test/ft_8_forget.rb +44 -0
- data/test/ft_9_cursor.rb +145 -0
- data/test/ft_9b_cursor.rb +105 -0
- data/test/ft_tests.rb +124 -0
- data/test/hash_test.rb +75 -0
- data/test/hparticipant_test.rb +164 -0
- data/test/lookup_att_test.rb +90 -0
- data/test/lookup_vf_test.rb +94 -0
- data/test/misc_test.rb +90 -0
- data/test/nut_0_irb.rb +20 -0
- data/test/obs_test.rb +142 -0
- data/test/orest_test.rb +251 -0
- data/test/param_test.rb +290 -0
- data/test/participant_test.rb +101 -0
- data/test/pending.rb +23 -0
- data/test/ps_representation.rb +133 -0
- data/test/rake_ltest.rb +38 -0
- data/test/rake_qtest.rb +68 -0
- data/test/raw_prog_test.rb +412 -0
- data/test/restart_cron_test.rb +136 -0
- data/test/restart_paused_test.rb +98 -0
- data/test/restart_sleep_test.rb +140 -0
- data/test/restart_tests.rb +18 -0
- data/test/restart_when_test.rb +112 -0
- data/test/ruby_procdef_test.rb +132 -0
- data/test/rutest_utils.rb +63 -0
- data/test/sec_test.rb +205 -0
- data/test/slock_test.rb +80 -0
- data/test/storage_test.rb +44 -0
- data/test/test.rb +3 -0
- data/test/timeout_test.rb +105 -0
- data/test/util_xml_test.rb +112 -0
- data/test/wfid_test.rb +175 -0
- data/test/wi_test.rb +75 -0
- metadata +433 -0
|
@@ -0,0 +1,662 @@
|
|
|
1
|
+
#
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (c) 2006-2008, 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
|
+
|
|
34
|
+
#
|
|
35
|
+
# "made in Japan"
|
|
36
|
+
#
|
|
37
|
+
# John Mettraux at openwfe.org
|
|
38
|
+
#
|
|
39
|
+
|
|
40
|
+
require 'openwfe/utils'
|
|
41
|
+
require 'openwfe/rudefinitions'
|
|
42
|
+
require 'openwfe/expressions/merge'
|
|
43
|
+
require 'openwfe/expressions/condition'
|
|
44
|
+
require 'openwfe/expressions/flowexpression'
|
|
45
|
+
require 'openwfe/expressions/iterator'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# base expressions like 'sequence' and 'concurrence'
|
|
50
|
+
#
|
|
51
|
+
|
|
52
|
+
module OpenWFE
|
|
53
|
+
|
|
54
|
+
#
|
|
55
|
+
# The concurrence expression will execute each of its (direct) children
|
|
56
|
+
# in parallel threads.
|
|
57
|
+
#
|
|
58
|
+
# Thus,
|
|
59
|
+
#
|
|
60
|
+
# <concurrence>
|
|
61
|
+
# <participant ref="pa" />
|
|
62
|
+
# <participant ref="pb" />
|
|
63
|
+
# </concurrence>
|
|
64
|
+
#
|
|
65
|
+
# Participants pa and pb will be 'treated' in parallel (quasi
|
|
66
|
+
# simultaneously).
|
|
67
|
+
#
|
|
68
|
+
# The concurrence expressions accept many attributes, that can get
|
|
69
|
+
# combined. By default, the concurrence waits for all its children to
|
|
70
|
+
# reply and returns the workitem of the first child that replied.
|
|
71
|
+
# The attributes tune this behaviour.
|
|
72
|
+
#
|
|
73
|
+
# <em>count</em>
|
|
74
|
+
#
|
|
75
|
+
# <concurrence count="1">
|
|
76
|
+
# <participant ref="pa" />
|
|
77
|
+
# <participant ref="pb" />
|
|
78
|
+
# </concurrence>
|
|
79
|
+
#
|
|
80
|
+
# The concurrence will be over as soon as 'pa' or 'pb' replied, i.e.
|
|
81
|
+
# as soon as "1" child replied.
|
|
82
|
+
#
|
|
83
|
+
# <em>remaining</em>
|
|
84
|
+
#
|
|
85
|
+
# The attribute 'remaining' can take two values 'cancel' (the default) and
|
|
86
|
+
# 'forget'.
|
|
87
|
+
# Cancelled children are completely wiped away, forgotten ones continue
|
|
88
|
+
# to operate but their reply will simply get discarded.
|
|
89
|
+
#
|
|
90
|
+
# <em>over-if</em>
|
|
91
|
+
#
|
|
92
|
+
# 'over-if' accepts a 'boolean expression' (something replying 'true' or
|
|
93
|
+
# 'false'), if the expression evaluates to true, the concurrence will be
|
|
94
|
+
# over and the remaining children will get cancelled (the default) or
|
|
95
|
+
# forgotten.
|
|
96
|
+
#
|
|
97
|
+
# <em>merge</em>
|
|
98
|
+
#
|
|
99
|
+
# By default, the first child to reply to its parent 'concurrence'
|
|
100
|
+
# expression 'wins', i.e. its workitem is used for resuming the flow (after
|
|
101
|
+
# the concurrence).
|
|
102
|
+
#
|
|
103
|
+
# [first] The default : the first child to reply wins
|
|
104
|
+
# [last] The last child to reply wins
|
|
105
|
+
# [highest] The first 'defined' child (in the list of children) will win
|
|
106
|
+
# [lowest] The last 'defined' child (in the list of children) will win
|
|
107
|
+
#
|
|
108
|
+
# Thus, in that example
|
|
109
|
+
#
|
|
110
|
+
# <concurrence merge="lowest">
|
|
111
|
+
# <participant ref="pa" />
|
|
112
|
+
# <participant ref="pb" />
|
|
113
|
+
# </concurrence>
|
|
114
|
+
#
|
|
115
|
+
# when the concurrence is done, the workitem of 'pb' is used to resume the
|
|
116
|
+
# flow after the concurrence.
|
|
117
|
+
#
|
|
118
|
+
# <em>merge-type</em>
|
|
119
|
+
#
|
|
120
|
+
# [override] The default : no mix of values between the workitems do occur
|
|
121
|
+
# [mix] Priority is given to the 'winning' workitem but their values
|
|
122
|
+
# get mixed
|
|
123
|
+
# [isolate] the attributes of the workitem of each branch is placed
|
|
124
|
+
# in a field in the resulting workitem. For example, the
|
|
125
|
+
# attributes of the first branch will be stored under the
|
|
126
|
+
# field named '0' of the resulting workitem.
|
|
127
|
+
#
|
|
128
|
+
# The merge occurs are the top level of workitem attributes.
|
|
129
|
+
#
|
|
130
|
+
# More complex merge behaviour can be obtained by extending the
|
|
131
|
+
# GenericSyncExpression class. But the default sync options are already
|
|
132
|
+
# numerous and powerful by their combinations.
|
|
133
|
+
#
|
|
134
|
+
class ConcurrenceExpression < SequenceExpression
|
|
135
|
+
include ConditionMixin
|
|
136
|
+
|
|
137
|
+
names :concurrence
|
|
138
|
+
|
|
139
|
+
attr_accessor \
|
|
140
|
+
:sync_expression
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def apply (workitem)
|
|
144
|
+
|
|
145
|
+
sync = lookup_sym_attribute(
|
|
146
|
+
:sync, workitem, :default => :generic)
|
|
147
|
+
|
|
148
|
+
@sync_expression =
|
|
149
|
+
get_expression_map.get_sync_class(sync).new(self, workitem)
|
|
150
|
+
|
|
151
|
+
@children.each do |child|
|
|
152
|
+
@sync_expression.add_child child
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
store_itself
|
|
156
|
+
|
|
157
|
+
#concurrence = self
|
|
158
|
+
|
|
159
|
+
@children.each_with_index do |child, index|
|
|
160
|
+
|
|
161
|
+
get_expression_pool.apply(
|
|
162
|
+
child,
|
|
163
|
+
get_workitem(workitem, index))
|
|
164
|
+
|
|
165
|
+
#Thread.new do
|
|
166
|
+
# begin
|
|
167
|
+
# #ldebug { "apply() child : #{child.to_debug_s}" }
|
|
168
|
+
# concurrence.synchronize do
|
|
169
|
+
# get_expression_pool().apply(
|
|
170
|
+
# child,
|
|
171
|
+
# #workitem.dup)
|
|
172
|
+
# get_workitem(workitem, index))
|
|
173
|
+
# end
|
|
174
|
+
# rescue Exception => e
|
|
175
|
+
# lwarn do
|
|
176
|
+
# "apply() " +
|
|
177
|
+
# "caught exception in concurrent child " +
|
|
178
|
+
# child.to_debug_s + "\n" +
|
|
179
|
+
# OpenWFE::exception_to_s(e)
|
|
180
|
+
# end
|
|
181
|
+
# end
|
|
182
|
+
#end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
#@sync_expression.ready(self)
|
|
186
|
+
#
|
|
187
|
+
# this is insufficient, have to do that :
|
|
188
|
+
|
|
189
|
+
#synchronize do
|
|
190
|
+
#
|
|
191
|
+
# Making sure the freshest version of the concurrence
|
|
192
|
+
# expression is used.
|
|
193
|
+
# This is especially important when using pure persistence.
|
|
194
|
+
#
|
|
195
|
+
reloaded_self, _fei = get_expression_pool.fetch @fei
|
|
196
|
+
reloaded_self.sync_expression.ready reloaded_self
|
|
197
|
+
#end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def reply (workitem)
|
|
201
|
+
@sync_expression.reply(self, workitem)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
protected
|
|
205
|
+
|
|
206
|
+
def get_workitem (workitem, index)
|
|
207
|
+
workitem.dup
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
#
|
|
212
|
+
# This expression is a mix between a 'concurrence' and an 'iterator'.
|
|
213
|
+
# It understands the same attributes and behaves as an interator that
|
|
214
|
+
# forks its children concurrently.
|
|
215
|
+
#
|
|
216
|
+
# Some examples :
|
|
217
|
+
#
|
|
218
|
+
# <concurrent-iterator on-value="sales, logistics, lob2" to-field="p">
|
|
219
|
+
# <participant field-ref="p" />
|
|
220
|
+
# </concurrent-iterator>
|
|
221
|
+
#
|
|
222
|
+
# Within a Ruby process definition :
|
|
223
|
+
#
|
|
224
|
+
# sequence do
|
|
225
|
+
# set :field => f, :value => %w{ Alan, Bob, Clarence }
|
|
226
|
+
# #...
|
|
227
|
+
# concurrent_iterator :on_field => "f", :to_field => "p" do
|
|
228
|
+
# participant "${p}"
|
|
229
|
+
# end
|
|
230
|
+
# end
|
|
231
|
+
#
|
|
232
|
+
class ConcurrentIteratorExpression < ConcurrenceExpression
|
|
233
|
+
|
|
234
|
+
names :concurrent_iterator
|
|
235
|
+
|
|
236
|
+
#attr_accessor :template
|
|
237
|
+
|
|
238
|
+
uses_template
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def apply (workitem)
|
|
242
|
+
|
|
243
|
+
return reply_to_parent(workitem) \
|
|
244
|
+
if raw_children.length < 1
|
|
245
|
+
|
|
246
|
+
@workitems = []
|
|
247
|
+
|
|
248
|
+
iterator = Iterator.new self, workitem
|
|
249
|
+
|
|
250
|
+
return reply_to_parent(workitem) \
|
|
251
|
+
unless iterator.has_next?
|
|
252
|
+
|
|
253
|
+
while iterator.has_next?
|
|
254
|
+
|
|
255
|
+
wi = workitem.dup
|
|
256
|
+
|
|
257
|
+
@workitems << wi
|
|
258
|
+
|
|
259
|
+
vars = iterator.next wi
|
|
260
|
+
|
|
261
|
+
#rawexp = get_expression_pool.prepare_from_template(
|
|
262
|
+
# self, nil, iterator.index, template, vars)
|
|
263
|
+
#@children << rawexp.fei
|
|
264
|
+
|
|
265
|
+
get_expression_pool.tprepare_child(
|
|
266
|
+
self,
|
|
267
|
+
raw_children.first,
|
|
268
|
+
iterator.index,
|
|
269
|
+
true, # register child
|
|
270
|
+
vars)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
super
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
protected
|
|
277
|
+
|
|
278
|
+
def get_workitem (workitem, index)
|
|
279
|
+
|
|
280
|
+
@workitems[index]
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
#
|
|
285
|
+
# A base for sync expressions, currently empty.
|
|
286
|
+
# That may change.
|
|
287
|
+
#
|
|
288
|
+
class SyncExpression < ObjectWithMeta
|
|
289
|
+
|
|
290
|
+
def initialize
|
|
291
|
+
|
|
292
|
+
super
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def self.names (*exp_names)
|
|
296
|
+
|
|
297
|
+
exp_names = exp_names.collect do |n|
|
|
298
|
+
n.to_s
|
|
299
|
+
end
|
|
300
|
+
meta_def :expression_names do
|
|
301
|
+
exp_names
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
#
|
|
307
|
+
# The classical OpenWFE sync expression.
|
|
308
|
+
# Used by 'concurrence' and 'concurrent-iterator'
|
|
309
|
+
#
|
|
310
|
+
class GenericSyncExpression < SyncExpression
|
|
311
|
+
|
|
312
|
+
names :generic
|
|
313
|
+
|
|
314
|
+
attr_accessor \
|
|
315
|
+
:remaining_children,
|
|
316
|
+
:count,
|
|
317
|
+
:reply_count,
|
|
318
|
+
:cancel_remaining,
|
|
319
|
+
:unready_queue
|
|
320
|
+
|
|
321
|
+
def initialize (synchable, workitem)
|
|
322
|
+
|
|
323
|
+
super()
|
|
324
|
+
|
|
325
|
+
@remaining_children = []
|
|
326
|
+
@reply_count = 0
|
|
327
|
+
|
|
328
|
+
@count = determine_count(synchable, workitem)
|
|
329
|
+
@cancel_remaining = cancel_remaining?(synchable, workitem)
|
|
330
|
+
|
|
331
|
+
merge = synchable.lookup_sym_attribute(
|
|
332
|
+
:merge, workitem, :default => :first)
|
|
333
|
+
|
|
334
|
+
merge_type = synchable.lookup_sym_attribute(
|
|
335
|
+
:merge_type, workitem, :default => :mix)
|
|
336
|
+
|
|
337
|
+
synchable.ldebug { "new() merge_type is '#{merge_type}'" }
|
|
338
|
+
|
|
339
|
+
@merge_array = MergeArray.new synchable.fei, merge, merge_type
|
|
340
|
+
|
|
341
|
+
@unready_queue = []
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
#
|
|
345
|
+
# when all the children got applied concurrently, the concurrence
|
|
346
|
+
# calls this method to notify the sync expression that replies
|
|
347
|
+
# can be processed
|
|
348
|
+
#
|
|
349
|
+
def ready (synchable)
|
|
350
|
+
#synchable.synchronize do
|
|
351
|
+
|
|
352
|
+
synchable.ldebug do
|
|
353
|
+
"ready() called by #{synchable.fei.to_debug_s} " +
|
|
354
|
+
"#{@unready_queue.length} wi waiting"
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
queue = @unready_queue
|
|
358
|
+
@unready_queue = nil
|
|
359
|
+
synchable.store_itself
|
|
360
|
+
|
|
361
|
+
queue.each do |workitem|
|
|
362
|
+
break if do_reply(synchable, workitem)
|
|
363
|
+
#
|
|
364
|
+
# do_reply() will return 'true' as soon as the
|
|
365
|
+
# concurrence is over, if this is the case, the
|
|
366
|
+
# queue should not be treated anymore
|
|
367
|
+
end
|
|
368
|
+
#end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def add_child (child)
|
|
372
|
+
@remaining_children << child
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
def reply (synchable, workitem)
|
|
376
|
+
#synchable.synchronize do
|
|
377
|
+
|
|
378
|
+
if @unready_queue
|
|
379
|
+
|
|
380
|
+
@unready_queue << workitem
|
|
381
|
+
|
|
382
|
+
synchable.store_itself
|
|
383
|
+
|
|
384
|
+
synchable.ldebug do
|
|
385
|
+
"#{self.class}.reply() "+
|
|
386
|
+
"#{@unready_queue.length} wi waiting..."
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
else
|
|
390
|
+
do_reply synchable, workitem
|
|
391
|
+
end
|
|
392
|
+
#end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
protected
|
|
396
|
+
|
|
397
|
+
def do_reply (synchable, workitem)
|
|
398
|
+
|
|
399
|
+
synchable.ldebug do
|
|
400
|
+
"#{self.class}.do_reply() from " +
|
|
401
|
+
"#{workitem.last_expression_id.to_debug_s}"
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
@merge_array.push(synchable, workitem)
|
|
405
|
+
|
|
406
|
+
@reply_count = @reply_count + 1
|
|
407
|
+
|
|
408
|
+
@remaining_children.delete(workitem.last_expression_id)
|
|
409
|
+
|
|
410
|
+
#synchable.ldebug do
|
|
411
|
+
# "#{self.class}.do_reply() "+
|
|
412
|
+
# "remaining children : #{@remaining_children.length}"
|
|
413
|
+
#end
|
|
414
|
+
|
|
415
|
+
if @remaining_children.length <= 0
|
|
416
|
+
reply_to_parent(synchable)
|
|
417
|
+
return true
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
if @count > 0 and @reply_count >= @count
|
|
421
|
+
treat_remaining_children(synchable)
|
|
422
|
+
reply_to_parent(synchable)
|
|
423
|
+
return true
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
#
|
|
427
|
+
# over-if
|
|
428
|
+
|
|
429
|
+
conditional =
|
|
430
|
+
synchable.eval_condition("over-if", workitem, "over-unless")
|
|
431
|
+
|
|
432
|
+
if conditional
|
|
433
|
+
treat_remaining_children(synchable)
|
|
434
|
+
reply_to_parent(synchable)
|
|
435
|
+
return true
|
|
436
|
+
end
|
|
437
|
+
|
|
438
|
+
#
|
|
439
|
+
# not over, resuming
|
|
440
|
+
|
|
441
|
+
synchable.store_itself()
|
|
442
|
+
|
|
443
|
+
#synchable.ldebug do
|
|
444
|
+
# "#{self.class}.do_reply() not replying to parent "+
|
|
445
|
+
# "#{workitem.last_expression_id.to_debug_s}"
|
|
446
|
+
#end
|
|
447
|
+
|
|
448
|
+
false
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def reply_to_parent (synchable)
|
|
452
|
+
|
|
453
|
+
workitem = @merge_array.do_merge
|
|
454
|
+
|
|
455
|
+
synchable.reply_to_parent workitem
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
def treat_remaining_children (synchable)
|
|
459
|
+
|
|
460
|
+
expool = synchable.get_expression_pool
|
|
461
|
+
|
|
462
|
+
@remaining_children.each do |child|
|
|
463
|
+
|
|
464
|
+
synchable.ldebug do
|
|
465
|
+
"#{self.class}.treat_remainining_children() " +
|
|
466
|
+
"#{child.to_debug_s} " +
|
|
467
|
+
"(cancel ? #{@cancel_remaining})"
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
if @cancel_remaining
|
|
471
|
+
expool.cancel(child)
|
|
472
|
+
else
|
|
473
|
+
expool.forget(synchable, child)
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def cancel_remaining? (synchable_expression, workitem)
|
|
479
|
+
|
|
480
|
+
s = synchable_expression.lookup_sym_attribute(
|
|
481
|
+
:remaining, workitem, :default => :cancel)
|
|
482
|
+
|
|
483
|
+
(s == :cancel)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
def determine_count (synchable_expression, workitem)
|
|
487
|
+
|
|
488
|
+
c = synchable_expression.lookup_attribute :count, workitem
|
|
489
|
+
return -1 if not c
|
|
490
|
+
i = c.to_i
|
|
491
|
+
return -1 if i < 1
|
|
492
|
+
i
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
#
|
|
496
|
+
# This inner class is used to gather workitems (via push()) before
|
|
497
|
+
# the final merge
|
|
498
|
+
# This final merge is triggered by calling the do_merge() method
|
|
499
|
+
# which will return the resulting, merged workitem.
|
|
500
|
+
#
|
|
501
|
+
class MergeArray
|
|
502
|
+
include MergeMixin
|
|
503
|
+
|
|
504
|
+
attr_accessor \
|
|
505
|
+
:synchable_fei,
|
|
506
|
+
:workitem,
|
|
507
|
+
:workitems_by_arrival,
|
|
508
|
+
:workitems_by_altitude,
|
|
509
|
+
:merge,
|
|
510
|
+
:merge_type
|
|
511
|
+
|
|
512
|
+
def initialize (synchable_fei, merge, merge_type)
|
|
513
|
+
|
|
514
|
+
@synchable_fei = synchable_fei
|
|
515
|
+
|
|
516
|
+
@merge = merge
|
|
517
|
+
@merge_type = merge_type
|
|
518
|
+
|
|
519
|
+
ensure_merge_settings
|
|
520
|
+
|
|
521
|
+
@workitem = nil
|
|
522
|
+
|
|
523
|
+
if highest? or lowest?
|
|
524
|
+
@workitems_by_arrival = []
|
|
525
|
+
@workitems_by_altitude = []
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def push (synchable, wi)
|
|
530
|
+
|
|
531
|
+
#synchable.ldebug do
|
|
532
|
+
# "push() isolate? #{isolate?}"
|
|
533
|
+
#end
|
|
534
|
+
|
|
535
|
+
if isolate?
|
|
536
|
+
push_in_isolation wi
|
|
537
|
+
elsif last? or first?
|
|
538
|
+
push_by_position wi
|
|
539
|
+
else
|
|
540
|
+
push_by_arrival wi
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
def push_by_position (wi)
|
|
545
|
+
|
|
546
|
+
source, target = if first?
|
|
547
|
+
[ @workitem, wi ]
|
|
548
|
+
else
|
|
549
|
+
[ wi, @workitem ]
|
|
550
|
+
end
|
|
551
|
+
@workitem = merge_workitems target, source, override?
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
def push_in_isolation (wi)
|
|
555
|
+
|
|
556
|
+
unless @workitem
|
|
557
|
+
@workitem = wi.dup
|
|
558
|
+
att = @workitem.attributes
|
|
559
|
+
@workitem.attributes = {}
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
#key = synchable.children.index wi.last_expression_id
|
|
563
|
+
#key = wi.last_expression_id.child_id
|
|
564
|
+
key = get_child_id wi
|
|
565
|
+
|
|
566
|
+
@workitem.attributes[key.to_s] =
|
|
567
|
+
OpenWFE::fulldup(wi.attributes)
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
def push_by_arrival (wi)
|
|
571
|
+
|
|
572
|
+
#index = synchable.children.index wi.last_expression_id
|
|
573
|
+
#index = Integer(wi.last_expression_id.child_id)
|
|
574
|
+
index = Integer(get_child_id(wi))
|
|
575
|
+
|
|
576
|
+
@workitems_by_arrival << wi
|
|
577
|
+
@workitems_by_altitude[index] = wi
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
#
|
|
581
|
+
# merges the workitems stored here
|
|
582
|
+
#
|
|
583
|
+
def do_merge
|
|
584
|
+
|
|
585
|
+
return @workitem if @workitem
|
|
586
|
+
|
|
587
|
+
list = if first?
|
|
588
|
+
@workitems_by_arrival.reverse
|
|
589
|
+
elsif last?
|
|
590
|
+
@workitems_by_arrival
|
|
591
|
+
elsif highest?
|
|
592
|
+
@workitems_by_altitude.reverse
|
|
593
|
+
elsif lowest?
|
|
594
|
+
@workitems_by_altitude
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
result = nil
|
|
598
|
+
|
|
599
|
+
list.each do |wi|
|
|
600
|
+
next unless wi
|
|
601
|
+
result = merge_workitems result, wi, override?
|
|
602
|
+
end
|
|
603
|
+
|
|
604
|
+
#puts "___ result :"
|
|
605
|
+
#puts result.to_s
|
|
606
|
+
#puts
|
|
607
|
+
|
|
608
|
+
result
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
protected
|
|
612
|
+
|
|
613
|
+
def first?
|
|
614
|
+
@merge == :first
|
|
615
|
+
end
|
|
616
|
+
def last?
|
|
617
|
+
@merge == :last
|
|
618
|
+
end
|
|
619
|
+
def highest?
|
|
620
|
+
@merge == :highest
|
|
621
|
+
end
|
|
622
|
+
def lowest?
|
|
623
|
+
@merge == :lowest
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
def mix?
|
|
627
|
+
@merge_type == :mix
|
|
628
|
+
end
|
|
629
|
+
def override?
|
|
630
|
+
@merge_type == :override
|
|
631
|
+
end
|
|
632
|
+
def isolate?
|
|
633
|
+
@merge_type == :isolate
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
#
|
|
637
|
+
# Returns the child id of the expression that just
|
|
638
|
+
# replied with the given workitem.
|
|
639
|
+
#
|
|
640
|
+
def get_child_id (workitem)
|
|
641
|
+
|
|
642
|
+
return workitem.fei.child_id \
|
|
643
|
+
if workitem.fei.wfid == @synchable_fei.wfid
|
|
644
|
+
|
|
645
|
+
workitem.fei.last_sub_instance_id
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
#
|
|
649
|
+
# Making sure @merge and @merge_type are set to
|
|
650
|
+
# appropriate values.
|
|
651
|
+
#
|
|
652
|
+
def ensure_merge_settings
|
|
653
|
+
|
|
654
|
+
@merge_type = :mix unless override? or isolate?
|
|
655
|
+
@merge = :first unless last? or highest? or lowest?
|
|
656
|
+
end
|
|
657
|
+
end
|
|
658
|
+
|
|
659
|
+
end
|
|
660
|
+
|
|
661
|
+
end
|
|
662
|
+
|