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,269 @@
|
|
|
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/filter'
|
|
43
|
+
require 'openwfe/expressions/timeout'
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# The participant expression, in its own file
|
|
48
|
+
#
|
|
49
|
+
|
|
50
|
+
module OpenWFE
|
|
51
|
+
|
|
52
|
+
#
|
|
53
|
+
# Participants sit at the edge between the engine and the external
|
|
54
|
+
# world. The participant expression transmit the workitem applied
|
|
55
|
+
# to it to the Participant instance it looks up in the participant map
|
|
56
|
+
# tied to the engine.
|
|
57
|
+
#
|
|
58
|
+
# direct reference to participant alpha :
|
|
59
|
+
#
|
|
60
|
+
# <participant ref="alpha" />
|
|
61
|
+
#
|
|
62
|
+
# the name of the participant is the value found in
|
|
63
|
+
# the field 'target' :
|
|
64
|
+
#
|
|
65
|
+
# <participant field-ref="target" />
|
|
66
|
+
# <participant ref="${f:target}" />
|
|
67
|
+
#
|
|
68
|
+
# the name of the participant is the value found in
|
|
69
|
+
# the variable 'target' :
|
|
70
|
+
#
|
|
71
|
+
# <participant variable-ref="target" />
|
|
72
|
+
# <participant ref="${target}" />
|
|
73
|
+
#
|
|
74
|
+
# direct reference to participant 'alpha'
|
|
75
|
+
# if a subprocess named 'alpha' has been defined, the
|
|
76
|
+
# subprocess will be called instead :
|
|
77
|
+
#
|
|
78
|
+
# <alpha />
|
|
79
|
+
#
|
|
80
|
+
# The Participant expressions includes the FilterMixin and thus
|
|
81
|
+
# understands and applies the "filter" attribute.
|
|
82
|
+
#
|
|
83
|
+
# Since OpenWFEru 0.9.9, the attributes of the participant expression are
|
|
84
|
+
# set inside a hash field named 'params' just available to the participant.
|
|
85
|
+
# Thus in
|
|
86
|
+
#
|
|
87
|
+
# <participant ref="toto" task="play golf" location="Minami Center" />
|
|
88
|
+
#
|
|
89
|
+
# participant 'toto' will receive a workitem with a field named 'params'
|
|
90
|
+
# containing the hash
|
|
91
|
+
# { "ref"=>"toto", "task"=>"play golf", "location"=>"Minami Center" }.
|
|
92
|
+
#
|
|
93
|
+
# When the workitem gets back from the participant, the field 'params' is
|
|
94
|
+
# deleted.
|
|
95
|
+
#
|
|
96
|
+
# The participant expressions include the TimeoutMixin, it means that
|
|
97
|
+
# a timeout can be stated :
|
|
98
|
+
#
|
|
99
|
+
# <participant ref="toto" timeout="2w1d" />
|
|
100
|
+
#
|
|
101
|
+
# If after 2 weeks and 1 day (15 days), participant "toto" hasn't replied,
|
|
102
|
+
# the workitem will get cancelled and the flow will resume (behind the
|
|
103
|
+
# scene, participant "toto", will receive a CancelItem instance bearing
|
|
104
|
+
# the same FlowExpressionId as the initial workitem and the participant
|
|
105
|
+
# implementation is responsible for the cancel application).
|
|
106
|
+
#
|
|
107
|
+
# The participant expression accepts an optional 'if' (or 'unless')
|
|
108
|
+
# attribute. It's used for conditional execution of the participant :
|
|
109
|
+
#
|
|
110
|
+
# participant :ref => "toto", :if => "${weather} == raining"
|
|
111
|
+
# # the participant toto will receive a workitem only if
|
|
112
|
+
# # it's raining
|
|
113
|
+
#
|
|
114
|
+
# boss :unless => "#{f:matter} == 'very trivial'"
|
|
115
|
+
# # the boss will not participate in the proces if the matter
|
|
116
|
+
# # is 'very trivial'
|
|
117
|
+
#
|
|
118
|
+
class ParticipantExpression < FlowExpression
|
|
119
|
+
include FilterMixin
|
|
120
|
+
include TimeoutMixin
|
|
121
|
+
include ConditionMixin
|
|
122
|
+
|
|
123
|
+
names :participant
|
|
124
|
+
|
|
125
|
+
attr_accessor :participant_name
|
|
126
|
+
attr_accessor :applied_workitem
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def apply (workitem)
|
|
130
|
+
|
|
131
|
+
conditional = eval_condition :if, workitem, :unless
|
|
132
|
+
|
|
133
|
+
return super_reply_to_parent(workitem) \
|
|
134
|
+
if conditional == false
|
|
135
|
+
#
|
|
136
|
+
# skip expression
|
|
137
|
+
# <participant ref="x" if="y" /> (where y evals to false)
|
|
138
|
+
|
|
139
|
+
@participant_name = lookup_ref workitem
|
|
140
|
+
|
|
141
|
+
@participant_name = fetch_text_content workitem \
|
|
142
|
+
unless @participant_name
|
|
143
|
+
|
|
144
|
+
participant =
|
|
145
|
+
get_participant_map.lookup_participant @participant_name
|
|
146
|
+
|
|
147
|
+
raise "No participant named '#{@participant_name}'" \
|
|
148
|
+
unless participant
|
|
149
|
+
|
|
150
|
+
remove_timedout_flag workitem
|
|
151
|
+
|
|
152
|
+
@applied_workitem = workitem.dup
|
|
153
|
+
|
|
154
|
+
schedule_timeout
|
|
155
|
+
|
|
156
|
+
filter_in workitem
|
|
157
|
+
|
|
158
|
+
store_itself
|
|
159
|
+
|
|
160
|
+
workitem.params = lookup_attributes workitem
|
|
161
|
+
|
|
162
|
+
#
|
|
163
|
+
# threading AFTER the store_itself()
|
|
164
|
+
#
|
|
165
|
+
Thread.new do
|
|
166
|
+
begin
|
|
167
|
+
|
|
168
|
+
# these two pmap calls were combined, but with the :reply
|
|
169
|
+
# notification in reply_to_parent() it feels more
|
|
170
|
+
# elegant like that
|
|
171
|
+
|
|
172
|
+
get_participant_map.dispatch(
|
|
173
|
+
participant, @participant_name, workitem)
|
|
174
|
+
|
|
175
|
+
get_participant_map.onotify(
|
|
176
|
+
@participant_name, :apply, workitem)
|
|
177
|
+
|
|
178
|
+
rescue Exception => e
|
|
179
|
+
|
|
180
|
+
get_expression_pool.notify_error(
|
|
181
|
+
e, fei, :do_apply, workitem)
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
alias :super_reply_to_parent :reply_to_parent
|
|
187
|
+
|
|
188
|
+
def reply_to_parent (workitem)
|
|
189
|
+
|
|
190
|
+
get_participant_map.onotify @participant_name, :reply, workitem
|
|
191
|
+
#
|
|
192
|
+
# for 'listen' expressions waiting for replies
|
|
193
|
+
|
|
194
|
+
unschedule_timeout()
|
|
195
|
+
|
|
196
|
+
workitem.attributes.delete "params"
|
|
197
|
+
|
|
198
|
+
filter_out workitem
|
|
199
|
+
|
|
200
|
+
super workitem
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
#
|
|
204
|
+
# The cancel() method of a ParticipantExpression is particular : it
|
|
205
|
+
# will emit a CancelItem instance towards the participant itself
|
|
206
|
+
# to notify it of the cancellation.
|
|
207
|
+
#
|
|
208
|
+
def cancel
|
|
209
|
+
|
|
210
|
+
unschedule_timeout
|
|
211
|
+
|
|
212
|
+
cancel_participant
|
|
213
|
+
|
|
214
|
+
@applied_workitem
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
#
|
|
218
|
+
# Upon timeout, the ParticipantExpression will cancel itself and
|
|
219
|
+
# the flow will resume.
|
|
220
|
+
#
|
|
221
|
+
def trigger (scheduler)
|
|
222
|
+
|
|
223
|
+
linfo { "trigger() timeout requested for #{@fei.to_debug_s}" }
|
|
224
|
+
|
|
225
|
+
begin
|
|
226
|
+
|
|
227
|
+
#@scheduler_job_id = nil
|
|
228
|
+
#
|
|
229
|
+
# so that cancel won't unschedule without need
|
|
230
|
+
|
|
231
|
+
cancel_participant
|
|
232
|
+
|
|
233
|
+
set_timedout_flag @applied_workitem
|
|
234
|
+
|
|
235
|
+
reply_to_parent @applied_workitem
|
|
236
|
+
|
|
237
|
+
rescue
|
|
238
|
+
|
|
239
|
+
lerror do
|
|
240
|
+
"trigger() problem while timing out\n"+
|
|
241
|
+
OpenWFE::exception_to_s($!)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
protected
|
|
247
|
+
|
|
248
|
+
#
|
|
249
|
+
# Have to cancel the workitem on the participant side
|
|
250
|
+
#
|
|
251
|
+
def cancel_participant
|
|
252
|
+
|
|
253
|
+
return unless @applied_workitem
|
|
254
|
+
#
|
|
255
|
+
# if there is an applied workitem, it means there
|
|
256
|
+
# is a participant to cancel...
|
|
257
|
+
|
|
258
|
+
participant = \
|
|
259
|
+
get_participant_map.lookup_participant(@participant_name)
|
|
260
|
+
|
|
261
|
+
cancelitem = CancelItem.new(@applied_workitem)
|
|
262
|
+
|
|
263
|
+
get_participant_map.dispatch(
|
|
264
|
+
participant, @participant_name, cancelitem)
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
end
|
|
269
|
+
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (c) 2007-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 'thread'
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
module OpenWFE
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# The 'reserve' expression ensures that its nested child expression
|
|
47
|
+
# executes while a reserved mutex is set.
|
|
48
|
+
#
|
|
49
|
+
# Thus
|
|
50
|
+
#
|
|
51
|
+
# concurrence do
|
|
52
|
+
# reserve :mutex => :m0 do
|
|
53
|
+
# sequence do
|
|
54
|
+
# participant :alpha
|
|
55
|
+
# participant :bravo
|
|
56
|
+
# end
|
|
57
|
+
# end
|
|
58
|
+
# reserve :mutex => :m0 do
|
|
59
|
+
# participant :charly
|
|
60
|
+
# end
|
|
61
|
+
# participant :delta
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
# The sequence will not but run while the participant charly is active
|
|
65
|
+
# and vice versa. The participant delta is not concerned.
|
|
66
|
+
#
|
|
67
|
+
# The mutex is a regular variable name, thus a mutex named "//toto" could
|
|
68
|
+
# be used to prevent segments of totally different process instances from
|
|
69
|
+
# running.
|
|
70
|
+
#
|
|
71
|
+
class ReserveExpression < FlowExpression
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
# A mutex for the whole class, it's meant to prevent 'reserve'
|
|
75
|
+
# from reserving a workflow mutex simultaneaously.
|
|
76
|
+
#
|
|
77
|
+
#@@mutex = Mutex.new
|
|
78
|
+
|
|
79
|
+
names :reserve
|
|
80
|
+
|
|
81
|
+
#
|
|
82
|
+
# The name of the mutex this expressions uses.
|
|
83
|
+
# It's a variable name, that means it can be prefixed with
|
|
84
|
+
# {nothing} (local scope), '/' (process scope) and '//' (engine /
|
|
85
|
+
# global scope).
|
|
86
|
+
#
|
|
87
|
+
attr_accessor :mutex_name
|
|
88
|
+
|
|
89
|
+
#
|
|
90
|
+
# An instance variable for storing the applied workitem if the 'reserve'
|
|
91
|
+
# cannot be entered immediately.
|
|
92
|
+
#
|
|
93
|
+
attr_accessor :applied_workitem
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def apply (workitem)
|
|
97
|
+
|
|
98
|
+
return reply_to_parent(workitem) \
|
|
99
|
+
if @children.size < 1
|
|
100
|
+
|
|
101
|
+
@mutex_name = lookup_string_attribute :mutex, workitem
|
|
102
|
+
|
|
103
|
+
#FlowMutex.synchronize do
|
|
104
|
+
|
|
105
|
+
mutex = lookup_variable(@mutex_name) || FlowMutex.new(@mutex_name)
|
|
106
|
+
|
|
107
|
+
mutex.register self, workitem
|
|
108
|
+
#end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def reply (workitem)
|
|
112
|
+
|
|
113
|
+
lookup_variable(@mutex_name).release self
|
|
114
|
+
|
|
115
|
+
reply_to_parent workitem
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#
|
|
119
|
+
# Called by the FlowMutex to enter the 'reserved/critical' section.
|
|
120
|
+
#
|
|
121
|
+
def enter (workitem=nil)
|
|
122
|
+
|
|
123
|
+
get_expression_pool.apply(
|
|
124
|
+
@children[0], workitem || @applied_workitem)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
#
|
|
129
|
+
# A FlowMutex is a process variable (thus serializable) that keeps
|
|
130
|
+
# track of the expressions in a critical section (1!) or waiting for
|
|
131
|
+
# entering it.
|
|
132
|
+
#
|
|
133
|
+
#--
|
|
134
|
+
# The current syncrhonization scheme is 1 thread mutex for all the
|
|
135
|
+
# FlowMutex. Shouldn't be too costly and the operations under sync are
|
|
136
|
+
# quite tiny.
|
|
137
|
+
#++
|
|
138
|
+
#
|
|
139
|
+
class FlowMutex
|
|
140
|
+
|
|
141
|
+
#--
|
|
142
|
+
# Granularity level ? "big rock". Only one FlowMutex operation
|
|
143
|
+
# a a time for the whole business process engine...
|
|
144
|
+
#
|
|
145
|
+
#@@class_mutex = Mutex.new
|
|
146
|
+
#++
|
|
147
|
+
|
|
148
|
+
attr_accessor :mutex_name
|
|
149
|
+
attr_accessor :feis
|
|
150
|
+
|
|
151
|
+
def initialize (mutex_name)
|
|
152
|
+
|
|
153
|
+
@mutex_name = mutex_name
|
|
154
|
+
@feis = []
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def register (fexp, workitem)
|
|
158
|
+
|
|
159
|
+
@feis << fexp.fei
|
|
160
|
+
|
|
161
|
+
fexp.set_variable @mutex_name, self
|
|
162
|
+
|
|
163
|
+
if @feis.size == 1
|
|
164
|
+
#
|
|
165
|
+
# immediately let the expression enter the critical section
|
|
166
|
+
#
|
|
167
|
+
fexp.store_itself
|
|
168
|
+
fexp.enter workitem
|
|
169
|
+
else
|
|
170
|
+
#
|
|
171
|
+
# later...
|
|
172
|
+
#
|
|
173
|
+
fexp.applied_workitem = workitem
|
|
174
|
+
fexp.store_itself
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def release (releaser)
|
|
179
|
+
|
|
180
|
+
next_fei = nil
|
|
181
|
+
|
|
182
|
+
#@@class_mutex.synchronize do
|
|
183
|
+
|
|
184
|
+
current_fei = @feis.delete_at 0
|
|
185
|
+
|
|
186
|
+
releaser.set_variable @mutex_name, self
|
|
187
|
+
|
|
188
|
+
log.warn "release() BAD! c:#{current_fei} r:#{releaser.fei}" \
|
|
189
|
+
if releaser.fei != current_fei
|
|
190
|
+
|
|
191
|
+
next_fei = @feis.first
|
|
192
|
+
#end
|
|
193
|
+
|
|
194
|
+
return unless next_fei
|
|
195
|
+
|
|
196
|
+
releaser.get_expression_pool.fetch_expression(next_fei).enter
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
#--
|
|
200
|
+
# Used by the ReserveExpression when looking up for a FlowMutex
|
|
201
|
+
# and registering into it.
|
|
202
|
+
#
|
|
203
|
+
#def self.synchronize (&block)
|
|
204
|
+
# @@class_mutex.synchronize do
|
|
205
|
+
# block.call
|
|
206
|
+
# end
|
|
207
|
+
#end
|
|
208
|
+
#++
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
end
|
|
212
|
+
|