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,112 @@
|
|
|
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
|
+
module OpenWFE
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# The methods of the engine for updating live expressions
|
|
44
|
+
# (in flight modifications of process instances)
|
|
45
|
+
#
|
|
46
|
+
module UpdateExpMethods
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Use only when doing "process gardening".
|
|
50
|
+
#
|
|
51
|
+
# This method updates an expression, the 'data' parameter is expected
|
|
52
|
+
# to be a hash. If the expression is an Environment, the variables
|
|
53
|
+
# will be merged with the ones found in the data param.
|
|
54
|
+
# If the expression is not an Environment, the data will be merged
|
|
55
|
+
# into the 'applied_workitem' if any.
|
|
56
|
+
#
|
|
57
|
+
# If the merge is not possible, an exception will be raised.
|
|
58
|
+
#
|
|
59
|
+
def update_expression_data (fei, data)
|
|
60
|
+
|
|
61
|
+
fexp = fetch_exp fei
|
|
62
|
+
|
|
63
|
+
original = if fexp.is_a?(Environment)
|
|
64
|
+
|
|
65
|
+
fexp.variables
|
|
66
|
+
else
|
|
67
|
+
|
|
68
|
+
fexp.applied_workitem.attributes
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
original.merge! data
|
|
72
|
+
|
|
73
|
+
get_expression_pool.update fexp
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# A variant of update_expression() that directly replaces
|
|
78
|
+
# the raw representation stored within a RawExpression.
|
|
79
|
+
#
|
|
80
|
+
# Useful for modifying [not yet reached] segments of processes.
|
|
81
|
+
#
|
|
82
|
+
def update_raw_expression (fei, representation)
|
|
83
|
+
|
|
84
|
+
fexp = fetch_exp fei
|
|
85
|
+
|
|
86
|
+
raise "cannot update already applied expression" \
|
|
87
|
+
unless fexp.is_a?(RawExpression)
|
|
88
|
+
|
|
89
|
+
fexp.raw_representation = representation
|
|
90
|
+
fexp.raw_rep_updated = true
|
|
91
|
+
|
|
92
|
+
get_expression_pool.update fexp
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#
|
|
96
|
+
# Replaces an expression in the pool with a newer version of it.
|
|
97
|
+
#
|
|
98
|
+
# (useful when fixing processes on the fly)
|
|
99
|
+
#
|
|
100
|
+
def update_expression (fexp)
|
|
101
|
+
|
|
102
|
+
fexp.application_context = application_context
|
|
103
|
+
|
|
104
|
+
fexp.raw_rep_updated = true
|
|
105
|
+
|
|
106
|
+
get_expression_pool.update fexp
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
|
|
@@ -0,0 +1,51 @@
|
|
|
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
|
+
|
|
34
|
+
#
|
|
35
|
+
# Made in Japan
|
|
36
|
+
#
|
|
37
|
+
# john.mettraux@openwfe.org
|
|
38
|
+
#
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
module OpenWFE
|
|
42
|
+
|
|
43
|
+
#
|
|
44
|
+
# The exception thrown at launch time, when there are parameter missing
|
|
45
|
+
# or whose value isn't matching what is required.
|
|
46
|
+
#
|
|
47
|
+
class ParameterException < Exception
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
@@ -0,0 +1,476 @@
|
|
|
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 'find'
|
|
41
|
+
require 'fileutils'
|
|
42
|
+
|
|
43
|
+
require 'openwfe/service'
|
|
44
|
+
require 'openwfe/omixins'
|
|
45
|
+
require 'openwfe/rudefinitions'
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
module OpenWFE
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# Encapsulating process error information.
|
|
52
|
+
#
|
|
53
|
+
# Instances of this class may be used to replay_at_error
|
|
54
|
+
#
|
|
55
|
+
class ProcessError
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# When did the error occur.
|
|
59
|
+
#
|
|
60
|
+
attr_reader :date
|
|
61
|
+
|
|
62
|
+
#
|
|
63
|
+
# The FlowExpressionId instance uniquely pointing at the expression
|
|
64
|
+
# which 'failed'.
|
|
65
|
+
#
|
|
66
|
+
attr_reader :fei
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
# Generally something like :apply or :reply
|
|
70
|
+
#
|
|
71
|
+
attr_reader :message
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
# The workitem accompanying the message (apply(workitem) /
|
|
75
|
+
# reply (workitem)).
|
|
76
|
+
#
|
|
77
|
+
attr_reader :workitem
|
|
78
|
+
|
|
79
|
+
#
|
|
80
|
+
# The String stack trace of the error.
|
|
81
|
+
#
|
|
82
|
+
attr_reader :stacktrace
|
|
83
|
+
|
|
84
|
+
#
|
|
85
|
+
# The error class (String) of the top level error
|
|
86
|
+
#
|
|
87
|
+
attr_reader :error_class
|
|
88
|
+
|
|
89
|
+
def initialize (*args)
|
|
90
|
+
|
|
91
|
+
@date = Time.new
|
|
92
|
+
@fei, @message, @workitem, @error_class, @stacktrace = args
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#
|
|
96
|
+
# Returns the parent workflow instance id (process id) of this
|
|
97
|
+
# ProcessError instance.
|
|
98
|
+
#
|
|
99
|
+
def wfid
|
|
100
|
+
@fei.parent_wfid
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
alias :parent_wfid :wfid
|
|
104
|
+
|
|
105
|
+
#
|
|
106
|
+
# Produces a human readable version of the information in the
|
|
107
|
+
# ProcessError instance.
|
|
108
|
+
#
|
|
109
|
+
def to_s
|
|
110
|
+
s = ""
|
|
111
|
+
s << "-- #{self.class.name} --\n"
|
|
112
|
+
s << " date : #{@date}\n"
|
|
113
|
+
s << " fei : #{@fei}\n"
|
|
114
|
+
s << " message : #{@message}\n"
|
|
115
|
+
s << " workitem : ...\n"
|
|
116
|
+
s << " error_class : #{@error_class}\n"
|
|
117
|
+
s << " stacktrace : #{@stacktrace[0, 80]}\n"
|
|
118
|
+
s
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
#
|
|
122
|
+
# Returns a hash
|
|
123
|
+
#
|
|
124
|
+
def hash
|
|
125
|
+
to_s.hash
|
|
126
|
+
#
|
|
127
|
+
# a bit costly but as it's only used by resume_process()...
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
#
|
|
131
|
+
# Returns true if the other instance is a ProcessError and is the
|
|
132
|
+
# same error as this one.
|
|
133
|
+
#
|
|
134
|
+
def == (other)
|
|
135
|
+
return false unless other.is_a?(ProcessError)
|
|
136
|
+
return to_s == other.to_s
|
|
137
|
+
#
|
|
138
|
+
# a bit costly but as it's only used by resume_process()...
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
#
|
|
143
|
+
# This is a base class for all error journal, don't instantiate,
|
|
144
|
+
# work rather with InMemoryErrorJournal (only for testing envs though),
|
|
145
|
+
# or YamlErrorJournal.
|
|
146
|
+
#
|
|
147
|
+
class ErrorJournal < Service
|
|
148
|
+
include OwfeServiceLocator
|
|
149
|
+
include FeiMixin
|
|
150
|
+
|
|
151
|
+
def initialize (service_name, application_context)
|
|
152
|
+
|
|
153
|
+
super
|
|
154
|
+
|
|
155
|
+
get_expression_pool.add_observer :error do |event, *args|
|
|
156
|
+
#
|
|
157
|
+
# logs each error occurring in the expression pool
|
|
158
|
+
|
|
159
|
+
begin
|
|
160
|
+
|
|
161
|
+
record_error(ProcessError.new(*args))
|
|
162
|
+
|
|
163
|
+
rescue Exception => e
|
|
164
|
+
lwarn { "*** process error : \n" + args.join("\n") }
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
get_expression_pool.add_observer :terminate do |event, *args|
|
|
169
|
+
#
|
|
170
|
+
# removes error log when a process terminates
|
|
171
|
+
|
|
172
|
+
fei = args[0].fei
|
|
173
|
+
|
|
174
|
+
remove_error_log fei.wfid \
|
|
175
|
+
if fei.is_in_parent_process?
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
#
|
|
180
|
+
# Returns true if the given wfid (or fei) (process instance id)
|
|
181
|
+
# has had errors.
|
|
182
|
+
#
|
|
183
|
+
def has_errors? (wfid)
|
|
184
|
+
|
|
185
|
+
get_error_log(wfid).size > 0
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
#--
|
|
189
|
+
#
|
|
190
|
+
# Commented out : has no real value
|
|
191
|
+
#
|
|
192
|
+
# Replays the given process instance (wfid or fei) at its last
|
|
193
|
+
# recorded error.
|
|
194
|
+
#
|
|
195
|
+
# There is an optional 'offset' parameter. Its default value is '0'.
|
|
196
|
+
# Which means that the replay will occur at the last error.
|
|
197
|
+
#
|
|
198
|
+
# ejournal.replay_at_last_error('20070630-hiwakuzara', 1)
|
|
199
|
+
#
|
|
200
|
+
# Will replay a given process instance at its 1 to last error.
|
|
201
|
+
#
|
|
202
|
+
#def replay_at_last_error (wfid, offset=0)
|
|
203
|
+
# wfid = extract_wfid(wfid)
|
|
204
|
+
# log = get_error_log(wfid)
|
|
205
|
+
# index = (-1 - offset)
|
|
206
|
+
# error = log[index]
|
|
207
|
+
# raise "no error for process '#{wfid}' at offset #{offset}" \
|
|
208
|
+
# unless error
|
|
209
|
+
# replay_at_error error
|
|
210
|
+
#end
|
|
211
|
+
#++
|
|
212
|
+
|
|
213
|
+
#--
|
|
214
|
+
#
|
|
215
|
+
# Moved to the engine itself.
|
|
216
|
+
#
|
|
217
|
+
# Replays at a specific error (fetched with read_error_log()).
|
|
218
|
+
#
|
|
219
|
+
#def replay_at_error (error)
|
|
220
|
+
# get_expression_pool.queue_work(
|
|
221
|
+
# error.message,
|
|
222
|
+
# error.fei,
|
|
223
|
+
# error.workitem)
|
|
224
|
+
#end
|
|
225
|
+
#++
|
|
226
|
+
|
|
227
|
+
#
|
|
228
|
+
# A utility method : given a list of errors, will make sure that for
|
|
229
|
+
# each flow expression only one expression (the most recent) will get
|
|
230
|
+
# listed.
|
|
231
|
+
# Returns a list of errors, from the oldest to the most recent.
|
|
232
|
+
#
|
|
233
|
+
# Could be useful when considering a process where multiple replay
|
|
234
|
+
# attempts failed.
|
|
235
|
+
#
|
|
236
|
+
def ErrorJournal.reduce_error_list (errors)
|
|
237
|
+
|
|
238
|
+
h = {}
|
|
239
|
+
|
|
240
|
+
errors.each do |e|
|
|
241
|
+
h[e.fei] = e
|
|
242
|
+
#
|
|
243
|
+
# last errors do override previous errors for the
|
|
244
|
+
# same fei
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
h.values.sort do |error_a, error_b|
|
|
248
|
+
error_a.date <=> error_b.date
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
#
|
|
254
|
+
# Stores all the errors in a hash... For testing purposes only, like
|
|
255
|
+
# the InMemoryExpressionStorage.
|
|
256
|
+
#
|
|
257
|
+
class InMemoryErrorJournal < ErrorJournal
|
|
258
|
+
|
|
259
|
+
def initialize (service_name, application_context)
|
|
260
|
+
|
|
261
|
+
super
|
|
262
|
+
|
|
263
|
+
@per_processes = {}
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
#
|
|
267
|
+
# Returns a list (older first) of the errors for a process
|
|
268
|
+
# instance identified by its fei or wfid.
|
|
269
|
+
#
|
|
270
|
+
# Will return an empty list if there a no errors for the process
|
|
271
|
+
# instances.
|
|
272
|
+
#
|
|
273
|
+
def get_error_log (wfid)
|
|
274
|
+
|
|
275
|
+
wfid = extract_wfid wfid, true
|
|
276
|
+
@per_processes[wfid] or []
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
#
|
|
280
|
+
# Removes the error log for a process instance.
|
|
281
|
+
#
|
|
282
|
+
def remove_error_log (wfid)
|
|
283
|
+
|
|
284
|
+
wfid = extract_wfid wfid, true
|
|
285
|
+
@per_processes.delete(wfid)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
#
|
|
289
|
+
# Removes a list of errors from the error journal.
|
|
290
|
+
#
|
|
291
|
+
# The 'errors' parameter may be a single error (instead of an array).
|
|
292
|
+
#
|
|
293
|
+
def remove_errors (wfid, errors)
|
|
294
|
+
|
|
295
|
+
errors = Array(errors)
|
|
296
|
+
|
|
297
|
+
log = get_error_log wfid
|
|
298
|
+
|
|
299
|
+
errors.each do |e|
|
|
300
|
+
log.delete e
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
#
|
|
305
|
+
# Reads all the error logs currently stored.
|
|
306
|
+
# Returns a hash wfid --> error list.
|
|
307
|
+
#
|
|
308
|
+
def get_error_logs
|
|
309
|
+
|
|
310
|
+
@per_processes
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
protected
|
|
314
|
+
|
|
315
|
+
def record_error (error)
|
|
316
|
+
|
|
317
|
+
(@per_processes[error.wfid] ||= []) << error
|
|
318
|
+
# not that unreadable after all...
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
#
|
|
323
|
+
# A Journal that only keep track of error in process execution.
|
|
324
|
+
#
|
|
325
|
+
class YamlErrorJournal < ErrorJournal
|
|
326
|
+
|
|
327
|
+
attr_reader :workdir
|
|
328
|
+
|
|
329
|
+
def initialize (service_name, application_context)
|
|
330
|
+
|
|
331
|
+
require 'openwfe/storage/yamlcustom'
|
|
332
|
+
# making sure this file has been required at this point
|
|
333
|
+
# this yamlcustom thing prevents the whole OpenWFE ecosystem
|
|
334
|
+
# to get serialized :)
|
|
335
|
+
|
|
336
|
+
super
|
|
337
|
+
|
|
338
|
+
@workdir = get_work_directory + "/ejournal"
|
|
339
|
+
|
|
340
|
+
FileUtils.makedirs(@workdir) unless File.exist?(@workdir)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
#
|
|
344
|
+
# Returns a list (older first) of the errors for a process
|
|
345
|
+
# instance identified by its fei or wfid.
|
|
346
|
+
#
|
|
347
|
+
# Will return an empty list if there a no errors for the process
|
|
348
|
+
# instances.
|
|
349
|
+
#
|
|
350
|
+
def get_error_log (wfid)
|
|
351
|
+
|
|
352
|
+
path = get_path wfid
|
|
353
|
+
|
|
354
|
+
return [] unless File.exist?(path)
|
|
355
|
+
|
|
356
|
+
read_error_log_from path
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
#
|
|
360
|
+
# Copies the error log of a process instance to a give path (and
|
|
361
|
+
# filename).
|
|
362
|
+
#
|
|
363
|
+
# Could be useful when one has to perform replay operations and wants
|
|
364
|
+
# to keep a copy of the original error[s].
|
|
365
|
+
#
|
|
366
|
+
def copy_error_log_to (wfid, path)
|
|
367
|
+
|
|
368
|
+
original_path = get_path wfid
|
|
369
|
+
FileUtils.copy_file original_path, path
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
#
|
|
373
|
+
# Reads an error log from a specific file (possibly as copied over
|
|
374
|
+
# via copy_error_log_to()).
|
|
375
|
+
#
|
|
376
|
+
def read_error_log_from (path)
|
|
377
|
+
|
|
378
|
+
raise "no error log file at #{path}" unless File.exist?(path)
|
|
379
|
+
|
|
380
|
+
File.open(path) do |f|
|
|
381
|
+
s = YAML.load_stream f
|
|
382
|
+
s.documents
|
|
383
|
+
end
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
#
|
|
387
|
+
# Removes the error log of a specific process instance.
|
|
388
|
+
# Could be a good idea after a succesful replay operation.
|
|
389
|
+
#
|
|
390
|
+
# 'wfid' may be either a workflow instance id (String) either
|
|
391
|
+
# a FlowExpressionId instance.
|
|
392
|
+
#
|
|
393
|
+
def remove_error_log (wfid)
|
|
394
|
+
|
|
395
|
+
path = get_path wfid
|
|
396
|
+
|
|
397
|
+
File.delete(path) if File.exist?(path)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
#
|
|
401
|
+
# Removes a list of errors from this error journal.
|
|
402
|
+
#
|
|
403
|
+
def remove_errors (wfid, errors)
|
|
404
|
+
|
|
405
|
+
errors = Array(errors)
|
|
406
|
+
|
|
407
|
+
# load all errors
|
|
408
|
+
|
|
409
|
+
log = get_error_log wfid
|
|
410
|
+
|
|
411
|
+
# remove the given errors
|
|
412
|
+
|
|
413
|
+
errors.each do |e|
|
|
414
|
+
log.delete e
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# rewrite error file
|
|
418
|
+
|
|
419
|
+
path = get_path wfid
|
|
420
|
+
|
|
421
|
+
if log.size > 0
|
|
422
|
+
|
|
423
|
+
File.open(path, "w") do |f|
|
|
424
|
+
log.each do |e|
|
|
425
|
+
f.puts e.to_yaml
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
else
|
|
429
|
+
|
|
430
|
+
File.delete path
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
#
|
|
435
|
+
# Reads all the error logs currently stored.
|
|
436
|
+
# Returns a hash wfid --> error list.
|
|
437
|
+
#
|
|
438
|
+
def get_error_logs
|
|
439
|
+
|
|
440
|
+
result = {}
|
|
441
|
+
|
|
442
|
+
Find.find(@workdir) do |path|
|
|
443
|
+
next unless path.endswith(".ejournal")
|
|
444
|
+
wfid = path[0..-9]
|
|
445
|
+
log = read_error_log wfid
|
|
446
|
+
result[wfid] = log
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
result
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
protected
|
|
453
|
+
|
|
454
|
+
#
|
|
455
|
+
# logs the error as a yaml string in an error log file
|
|
456
|
+
# (there is one error log file per workflow instance).
|
|
457
|
+
#
|
|
458
|
+
def record_error (error)
|
|
459
|
+
|
|
460
|
+
path = get_path error.fei
|
|
461
|
+
|
|
462
|
+
File.open(path, "a+") do |f|
|
|
463
|
+
f.puts error.to_yaml
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
#
|
|
468
|
+
# Returns the path to the error log file of a specific process
|
|
469
|
+
# instance.
|
|
470
|
+
#
|
|
471
|
+
def get_path (fei_or_wfid)
|
|
472
|
+
|
|
473
|
+
@workdir + "/" + extract_wfid(fei_or_wfid, true) + ".ejournal"
|
|
474
|
+
end
|
|
475
|
+
end
|
|
476
|
+
end
|