ruote-maestrodev 2.2.1
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/CHANGELOG.txt +290 -0
- data/CREDITS.txt +99 -0
- data/LICENSE.txt +21 -0
- data/README.rdoc +88 -0
- data/Rakefile +108 -0
- data/TODO.txt +488 -0
- data/lib/ruote.rb +7 -0
- data/lib/ruote/context.rb +194 -0
- data/lib/ruote/engine.rb +1062 -0
- data/lib/ruote/engine/process_error.rb +122 -0
- data/lib/ruote/engine/process_status.rb +448 -0
- data/lib/ruote/exp/command.rb +87 -0
- data/lib/ruote/exp/commanded.rb +69 -0
- data/lib/ruote/exp/condition.rb +227 -0
- data/lib/ruote/exp/fe_add_branches.rb +138 -0
- data/lib/ruote/exp/fe_apply.rb +154 -0
- data/lib/ruote/exp/fe_cancel_process.rb +78 -0
- data/lib/ruote/exp/fe_command.rb +156 -0
- data/lib/ruote/exp/fe_concurrence.rb +321 -0
- data/lib/ruote/exp/fe_concurrent_iterator.rb +219 -0
- data/lib/ruote/exp/fe_cron.rb +141 -0
- data/lib/ruote/exp/fe_cursor.rb +324 -0
- data/lib/ruote/exp/fe_define.rb +112 -0
- data/lib/ruote/exp/fe_echo.rb +60 -0
- data/lib/ruote/exp/fe_equals.rb +115 -0
- data/lib/ruote/exp/fe_error.rb +82 -0
- data/lib/ruote/exp/fe_filter.rb +648 -0
- data/lib/ruote/exp/fe_forget.rb +88 -0
- data/lib/ruote/exp/fe_given.rb +154 -0
- data/lib/ruote/exp/fe_if.rb +127 -0
- data/lib/ruote/exp/fe_inc.rb +205 -0
- data/lib/ruote/exp/fe_iterator.rb +234 -0
- data/lib/ruote/exp/fe_let.rb +75 -0
- data/lib/ruote/exp/fe_listen.rb +304 -0
- data/lib/ruote/exp/fe_lose.rb +110 -0
- data/lib/ruote/exp/fe_noop.rb +45 -0
- data/lib/ruote/exp/fe_once.rb +215 -0
- data/lib/ruote/exp/fe_participant.rb +287 -0
- data/lib/ruote/exp/fe_read.rb +69 -0
- data/lib/ruote/exp/fe_redo.rb +82 -0
- data/lib/ruote/exp/fe_ref.rb +152 -0
- data/lib/ruote/exp/fe_registerp.rb +110 -0
- data/lib/ruote/exp/fe_reserve.rb +126 -0
- data/lib/ruote/exp/fe_restore.rb +102 -0
- data/lib/ruote/exp/fe_save.rb +72 -0
- data/lib/ruote/exp/fe_sequence.rb +59 -0
- data/lib/ruote/exp/fe_set.rb +154 -0
- data/lib/ruote/exp/fe_subprocess.rb +211 -0
- data/lib/ruote/exp/fe_that.rb +92 -0
- data/lib/ruote/exp/fe_undo.rb +67 -0
- data/lib/ruote/exp/fe_unregisterp.rb +69 -0
- data/lib/ruote/exp/fe_wait.rb +95 -0
- data/lib/ruote/exp/flowexpression.rb +886 -0
- data/lib/ruote/exp/iterator.rb +81 -0
- data/lib/ruote/exp/merge.rb +118 -0
- data/lib/ruote/exp/ro_attributes.rb +212 -0
- data/lib/ruote/exp/ro_filters.rb +136 -0
- data/lib/ruote/exp/ro_persist.rb +154 -0
- data/lib/ruote/exp/ro_variables.rb +189 -0
- data/lib/ruote/exp/ro_vf.rb +68 -0
- data/lib/ruote/fei.rb +260 -0
- data/lib/ruote/id/mnemo_wfid_generator.rb +43 -0
- data/lib/ruote/id/wfid_generator.rb +81 -0
- data/lib/ruote/log/default_history.rb +122 -0
- data/lib/ruote/log/pretty.rb +176 -0
- data/lib/ruote/log/storage_history.rb +159 -0
- data/lib/ruote/log/test_logger.rb +208 -0
- data/lib/ruote/log/wait_logger.rb +64 -0
- data/lib/ruote/part/block_participant.rb +137 -0
- data/lib/ruote/part/code_participant.rb +81 -0
- data/lib/ruote/part/engine_participant.rb +189 -0
- data/lib/ruote/part/local_participant.rb +138 -0
- data/lib/ruote/part/no_op_participant.rb +60 -0
- data/lib/ruote/part/null_participant.rb +54 -0
- data/lib/ruote/part/rev_participant.rb +169 -0
- data/lib/ruote/part/smtp_participant.rb +116 -0
- data/lib/ruote/part/storage_participant.rb +392 -0
- data/lib/ruote/part/template.rb +84 -0
- data/lib/ruote/participant.rb +7 -0
- data/lib/ruote/reader.rb +278 -0
- data/lib/ruote/reader/json.rb +49 -0
- data/lib/ruote/reader/radial.rb +290 -0
- data/lib/ruote/reader/ruby_dsl.rb +186 -0
- data/lib/ruote/reader/xml.rb +99 -0
- data/lib/ruote/receiver/base.rb +212 -0
- data/lib/ruote/storage/base.rb +364 -0
- data/lib/ruote/storage/composite_storage.rb +121 -0
- data/lib/ruote/storage/fs_storage.rb +139 -0
- data/lib/ruote/storage/hash_storage.rb +211 -0
- data/lib/ruote/svc/dispatch_pool.rb +158 -0
- data/lib/ruote/svc/dollar_sub.rb +298 -0
- data/lib/ruote/svc/error_handler.rb +138 -0
- data/lib/ruote/svc/expression_map.rb +97 -0
- data/lib/ruote/svc/participant_list.rb +397 -0
- data/lib/ruote/svc/tracker.rb +172 -0
- data/lib/ruote/svc/treechecker.rb +141 -0
- data/lib/ruote/tree_dot.rb +85 -0
- data/lib/ruote/util/filter.rb +525 -0
- data/lib/ruote/util/hashdot.rb +79 -0
- data/lib/ruote/util/look.rb +128 -0
- data/lib/ruote/util/lookup.rb +127 -0
- data/lib/ruote/util/misc.rb +167 -0
- data/lib/ruote/util/ometa.rb +71 -0
- data/lib/ruote/util/serializer.rb +103 -0
- data/lib/ruote/util/subprocess.rb +88 -0
- data/lib/ruote/util/time.rb +100 -0
- data/lib/ruote/util/tree.rb +58 -0
- data/lib/ruote/version.rb +29 -0
- data/lib/ruote/worker.rb +386 -0
- data/lib/ruote/workitem.rb +394 -0
- data/phil.txt +14 -0
- data/ruote.gemspec +44 -0
- data/test/bm/ci.rb +55 -0
- data/test/bm/ici.rb +71 -0
- data/test/bm/juuman.rb +54 -0
- data/test/bm/launch_bench.rb +37 -0
- data/test/bm/load_26c.rb +97 -0
- data/test/bm/mega.rb +64 -0
- data/test/bm/seq_thousand.rb +31 -0
- data/test/bm/t.rb +35 -0
- data/test/functional/base.rb +247 -0
- data/test/functional/concurrent_base.rb +98 -0
- data/test/functional/crunner.rb +31 -0
- data/test/functional/ct_0_concurrence.rb +65 -0
- data/test/functional/ct_1_iterator.rb +67 -0
- data/test/functional/ct_2_cancel.rb +81 -0
- data/test/functional/eft_0_process_definition.rb +65 -0
- data/test/functional/eft_10_cancel_process.rb +46 -0
- data/test/functional/eft_11_wait.rb +109 -0
- data/test/functional/eft_12_listen.rb +500 -0
- data/test/functional/eft_13_iterator.rb +342 -0
- data/test/functional/eft_14_cursor.rb +456 -0
- data/test/functional/eft_15_loop.rb +69 -0
- data/test/functional/eft_16_if.rb +183 -0
- data/test/functional/eft_17_equals.rb +55 -0
- data/test/functional/eft_18_concurrent_iterator.rb +410 -0
- data/test/functional/eft_19_reserve.rb +136 -0
- data/test/functional/eft_1_echo.rb +68 -0
- data/test/functional/eft_20_save.rb +116 -0
- data/test/functional/eft_21_restore.rb +61 -0
- data/test/functional/eft_22_noop.rb +28 -0
- data/test/functional/eft_23_apply.rb +168 -0
- data/test/functional/eft_24_add_branches.rb +98 -0
- data/test/functional/eft_25_command.rb +28 -0
- data/test/functional/eft_26_error.rb +77 -0
- data/test/functional/eft_27_inc.rb +280 -0
- data/test/functional/eft_28_once.rb +135 -0
- data/test/functional/eft_29_cron.rb +64 -0
- data/test/functional/eft_2_sequence.rb +58 -0
- data/test/functional/eft_30_ref.rb +155 -0
- data/test/functional/eft_31_registerp.rb +130 -0
- data/test/functional/eft_32_lose.rb +93 -0
- data/test/functional/eft_33_let.rb +31 -0
- data/test/functional/eft_34_given.rb +123 -0
- data/test/functional/eft_35_filter.rb +375 -0
- data/test/functional/eft_36_read.rb +95 -0
- data/test/functional/eft_3_participant.rb +149 -0
- data/test/functional/eft_4_set.rb +296 -0
- data/test/functional/eft_5_subprocess.rb +163 -0
- data/test/functional/eft_6_concurrence.rb +304 -0
- data/test/functional/eft_7_forget.rb +61 -0
- data/test/functional/eft_8_undo.rb +114 -0
- data/test/functional/eft_9_redo.rb +138 -0
- data/test/functional/ft_0_worker.rb +65 -0
- data/test/functional/ft_10_dollar.rb +304 -0
- data/test/functional/ft_11_recursion.rb +109 -0
- data/test/functional/ft_12_launchitem.rb +43 -0
- data/test/functional/ft_13_variables.rb +151 -0
- data/test/functional/ft_14_re_apply.rb +324 -0
- data/test/functional/ft_15_timeout.rb +226 -0
- data/test/functional/ft_16_participant_params.rb +98 -0
- data/test/functional/ft_17_conditional.rb +102 -0
- data/test/functional/ft_18_kill.rb +138 -0
- data/test/functional/ft_19_participant_code.rb +67 -0
- data/test/functional/ft_1_process_status.rb +796 -0
- data/test/functional/ft_20_storage_participant.rb +543 -0
- data/test/functional/ft_21_forget.rb +153 -0
- data/test/functional/ft_22_process_definitions.rb +90 -0
- data/test/functional/ft_23_load_defs.rb +79 -0
- data/test/functional/ft_24_block_participant.rb +235 -0
- data/test/functional/ft_25_receiver.rb +207 -0
- data/test/functional/ft_26_participant_rtimeout.rb +179 -0
- data/test/functional/ft_27_var_indirection.rb +128 -0
- data/test/functional/ft_28_null_noop_participants.rb +51 -0
- data/test/functional/ft_29_part_template.rb +60 -0
- data/test/functional/ft_2_errors.rb +380 -0
- data/test/functional/ft_30_smtp_participant.rb +122 -0
- data/test/functional/ft_31_part_blocking.rb +72 -0
- data/test/functional/ft_33_participant_subprocess_priority.rb +32 -0
- data/test/functional/ft_34_cursor_rewind.rb +101 -0
- data/test/functional/ft_35_add_service.rb +56 -0
- data/test/functional/ft_36_storage_history.rb +150 -0
- data/test/functional/ft_37_default_history.rb +109 -0
- data/test/functional/ft_38_participant_more.rb +193 -0
- data/test/functional/ft_39_wait_for.rb +136 -0
- data/test/functional/ft_3_participant_registration.rb +574 -0
- data/test/functional/ft_40_wait_logger.rb +62 -0
- data/test/functional/ft_41_participants.rb +91 -0
- data/test/functional/ft_42_storage_copy.rb +71 -0
- data/test/functional/ft_43_participant_on_reply.rb +87 -0
- data/test/functional/ft_44_var_participant.rb +35 -0
- data/test/functional/ft_45_participant_accept.rb +64 -0
- data/test/functional/ft_46_launch_single.rb +83 -0
- data/test/functional/ft_47_wfid_generator.rb +54 -0
- data/test/functional/ft_48_lose.rb +112 -0
- data/test/functional/ft_49_engine_on_error.rb +201 -0
- data/test/functional/ft_4_cancel.rb +132 -0
- data/test/functional/ft_50_engine_config.rb +22 -0
- data/test/functional/ft_51_misc.rb +67 -0
- data/test/functional/ft_52_case.rb +134 -0
- data/test/functional/ft_53_engine_on_terminate.rb +95 -0
- data/test/functional/ft_54_patterns.rb +104 -0
- data/test/functional/ft_55_engine_participant.rb +303 -0
- data/test/functional/ft_56_filter_attribute.rb +259 -0
- data/test/functional/ft_57_rev_participant.rb +252 -0
- data/test/functional/ft_58_workitem.rb +69 -0
- data/test/functional/ft_59_pause.rb +343 -0
- data/test/functional/ft_5_on_error.rb +384 -0
- data/test/functional/ft_60_code_participant.rb +45 -0
- data/test/functional/ft_61_trailing_fields.rb +34 -0
- data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
- data/test/functional/ft_6_on_cancel.rb +221 -0
- data/test/functional/ft_7_tags.rb +177 -0
- data/test/functional/ft_8_participant_consumption.rb +124 -0
- data/test/functional/ft_9_subprocesses.rb +146 -0
- data/test/functional/restart_base.rb +34 -0
- data/test/functional/rt_0_wait.rb +55 -0
- data/test/functional/rt_1_listen.rb +56 -0
- data/test/functional/rt_2_errors.rb +56 -0
- data/test/functional/rt_3_once.rb +70 -0
- data/test/functional/rt_4_cron.rb +64 -0
- data/test/functional/rt_5_timeout.rb +60 -0
- data/test/functional/rtest.rb +8 -0
- data/test/functional/storage_helper.rb +93 -0
- data/test/functional/test.rb +44 -0
- data/test/functional/vertical.rb +46 -0
- data/test/path_helper.rb +15 -0
- data/test/test.rb +13 -0
- data/test/test_helper.rb +28 -0
- data/test/unit/storage.rb +428 -0
- data/test/unit/storages.rb +37 -0
- data/test/unit/test.rb +28 -0
- data/test/unit/ut_0_ruby_reader.rb +223 -0
- data/test/unit/ut_11_lookup.rb +122 -0
- data/test/unit/ut_13_serializer.rb +65 -0
- data/test/unit/ut_14_is_uri.rb +28 -0
- data/test/unit/ut_15_util.rb +57 -0
- data/test/unit/ut_16_reader.rb +225 -0
- data/test/unit/ut_18_engine.rb +47 -0
- data/test/unit/ut_19_part_template.rb +86 -0
- data/test/unit/ut_1_fei.rb +165 -0
- data/test/unit/ut_20_composite_storage.rb +74 -0
- data/test/unit/ut_21_svc_participant_list.rb +46 -0
- data/test/unit/ut_22_filter.rb +1094 -0
- data/test/unit/ut_23_svc_tracker.rb +48 -0
- data/test/unit/ut_24_radial_reader.rb +332 -0
- data/test/unit/ut_25_merge.rb +113 -0
- data/test/unit/ut_3_wait_logger.rb +39 -0
- data/test/unit/ut_4_expmap.rb +20 -0
- data/test/unit/ut_5_tree.rb +54 -0
- data/test/unit/ut_6_condition.rb +303 -0
- data/test/unit/ut_7_workitem.rb +99 -0
- data/test/unit/ut_8_tree_to_dot.rb +72 -0
- data/test/unit/ut_9_xml_reader.rb +61 -0
- metadata +504 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Singapore.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'ruote/util/subprocess'
|
26
|
+
require 'ruote/part/local_participant'
|
27
|
+
|
28
|
+
|
29
|
+
module Ruote
|
30
|
+
|
31
|
+
#
|
32
|
+
# A participant for pushing the execution of [segments of] processes to
|
33
|
+
# other engines.
|
34
|
+
#
|
35
|
+
# It works by giving the participant the connection information to the storage
|
36
|
+
# of the other engine.
|
37
|
+
#
|
38
|
+
# For instance :
|
39
|
+
#
|
40
|
+
# engine0 =
|
41
|
+
# Ruote::Engine.new(
|
42
|
+
# Ruote::Worker.new(
|
43
|
+
# Ruote::FsStorage.new('work0', 'engine_id' => 'engine0')))
|
44
|
+
# engine1 =
|
45
|
+
# Ruote::Engine.new(
|
46
|
+
# Ruote::Worker.new(
|
47
|
+
# Ruote::FsStorage.new('work1', 'engine_id' => 'engine1')))
|
48
|
+
#
|
49
|
+
# engine0.register_participant('engine1',
|
50
|
+
# Ruote::EngineParticipant,
|
51
|
+
# 'storage_class' => Ruote::FsStorage,
|
52
|
+
# 'storage_path' => 'ruote/storage/fs_storage',
|
53
|
+
# 'storage_args' => 'work1')
|
54
|
+
# engine1.register_participant('engine0',
|
55
|
+
# Ruote::EngineParticipant,
|
56
|
+
# 'storage_class' => Ruote::FsStorage,
|
57
|
+
# 'storage_path' => 'ruote/storage/fs_storage',
|
58
|
+
# 'storage_args' => 'work0')
|
59
|
+
#
|
60
|
+
# In this example, two engines are created (note that their 'engine_id' is
|
61
|
+
# explicitely set (else it would default to 'engine')). Each engine is then
|
62
|
+
# registered as participant in the other engine. The registration parameters
|
63
|
+
# detail the class and the arguments to the storage of the target engine.
|
64
|
+
#
|
65
|
+
# This example is a bit dry / flat. A real world example would perhaps detail
|
66
|
+
# a 'master' engine connected to 'departmental' engines, something more
|
67
|
+
# hierarchical.
|
68
|
+
#
|
69
|
+
# The example also binds reciprocally engines. If the delegated processes
|
70
|
+
# are always 'forgotten', one could imagine not binding the source engine
|
71
|
+
# as a participant in the target engine (not need to answer back).
|
72
|
+
#
|
73
|
+
# There are then two variants for calling a subprocess
|
74
|
+
#
|
75
|
+
# subprocess :ref => 'subprocess_name', :engine => 'engine1'
|
76
|
+
# # or
|
77
|
+
# participant :ref => 'engine1', :pdef => 'subprocess_name'
|
78
|
+
#
|
79
|
+
# It's OK to go for the shorter versions :
|
80
|
+
#
|
81
|
+
# subprocess_name :engine => 'engine1'
|
82
|
+
# # or
|
83
|
+
# participant 'engine1', :pdef => 'subprocess_name'
|
84
|
+
# engine1 :pdef => 'subprocess_name'
|
85
|
+
#
|
86
|
+
# The subprocess is defined in the current process, or it's given via its
|
87
|
+
# URL. The third variant is a subprocess bound as an engine variable.
|
88
|
+
#
|
89
|
+
# engine.variables['variant_3'] = Ruote.process_definition do
|
90
|
+
# participant 'hello_world_3'
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# pdef = Ruote.process_definition do
|
94
|
+
# sequence do
|
95
|
+
# engine1 :pdef => 'variant_1'
|
96
|
+
# engine1 :pdef => 'http://pdefs.example.com/variant_2.rb'
|
97
|
+
# engine1 :pdef => 'variant_3'
|
98
|
+
# end
|
99
|
+
# define 'variant_1' do
|
100
|
+
# participant 'hello_world_1'
|
101
|
+
# end
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
class EngineParticipant
|
105
|
+
|
106
|
+
include LocalParticipant
|
107
|
+
|
108
|
+
def initialize(opts)
|
109
|
+
|
110
|
+
if pa = opts['storage_path']
|
111
|
+
require pa
|
112
|
+
end
|
113
|
+
|
114
|
+
kl = opts['storage_class']
|
115
|
+
|
116
|
+
raise(ArgumentError.new("missing 'storage_class' parameter")) unless kl
|
117
|
+
|
118
|
+
args = opts['storage_args']
|
119
|
+
args = args.is_a?(Hash) ? [ args ] : Array(args)
|
120
|
+
args << {} unless args.last.is_a?(Hash)
|
121
|
+
args.last['preserve_configuration'] = true
|
122
|
+
|
123
|
+
@storage = Ruote.constantize(kl).new(*args)
|
124
|
+
end
|
125
|
+
|
126
|
+
def consume(workitem)
|
127
|
+
|
128
|
+
wi = workitem.to_h
|
129
|
+
fexp = Ruote::Exp::FlowExpression.fetch(@context, wi['fei'])
|
130
|
+
params = wi['fields'].delete('params')
|
131
|
+
|
132
|
+
forget = (fexp.attribute(:forget).to_s == 'true')
|
133
|
+
|
134
|
+
@storage.put_msg(
|
135
|
+
'launch',
|
136
|
+
'wfid' => wi['fei']['wfid'],
|
137
|
+
'parent_id' => forget ? nil : wi['fei'],
|
138
|
+
'tree' => determine_tree(fexp, params),
|
139
|
+
'workitem' => wi,
|
140
|
+
'variables' => fexp.compile_variables)
|
141
|
+
|
142
|
+
fexp.unpersist if forget
|
143
|
+
#
|
144
|
+
# special behaviour here in case of :forget => true :
|
145
|
+
# parent_id of remote expression is set to nil and local expression
|
146
|
+
# is unpersisted immediately
|
147
|
+
end
|
148
|
+
|
149
|
+
def cancel(fei, flavour)
|
150
|
+
|
151
|
+
exps = @storage.get_many('expressions', /^0![^!]+!#{fei.wfid}$/)
|
152
|
+
|
153
|
+
return true if exps.size < 1
|
154
|
+
# participant expression will reply to its parent
|
155
|
+
|
156
|
+
@storage.put_msg(
|
157
|
+
'cancel',
|
158
|
+
'fei' => exps.first['fei'],
|
159
|
+
'flavour' => flavour)
|
160
|
+
|
161
|
+
false
|
162
|
+
# participant expression will NOT reply to its parent
|
163
|
+
end
|
164
|
+
|
165
|
+
def reply(fei, workitem)
|
166
|
+
|
167
|
+
@storage.put_msg(
|
168
|
+
'reply',
|
169
|
+
'fei' => fei,
|
170
|
+
'workitem' => workitem)
|
171
|
+
end
|
172
|
+
|
173
|
+
protected
|
174
|
+
|
175
|
+
def determine_tree(fexp, params)
|
176
|
+
|
177
|
+
pdef = params['def'] || params['pdef'] || params['tree']
|
178
|
+
|
179
|
+
tree = Ruote.lookup_subprocess(fexp, pdef)
|
180
|
+
|
181
|
+
raise(
|
182
|
+
"couldn't find process definition behind '#{pdef}'"
|
183
|
+
) unless tree
|
184
|
+
|
185
|
+
tree.last
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
@@ -0,0 +1,138 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'ruote/receiver/base'
|
26
|
+
|
27
|
+
|
28
|
+
module Ruote
|
29
|
+
|
30
|
+
#
|
31
|
+
# Provides methods for 'local' participants.
|
32
|
+
#
|
33
|
+
# Assumes the class that includes this module has a #context method
|
34
|
+
# that points to the worker or engine ruote context.
|
35
|
+
#
|
36
|
+
# It's "local" because it has access to the ruote storage.
|
37
|
+
#
|
38
|
+
module LocalParticipant
|
39
|
+
|
40
|
+
include ReceiverMixin
|
41
|
+
# the reply_to_engine method is there
|
42
|
+
|
43
|
+
attr_accessor :context
|
44
|
+
|
45
|
+
# Use this method to re_dispatch the workitem.
|
46
|
+
#
|
47
|
+
# It takes two options :in and :at for "later re_dispatch".
|
48
|
+
#
|
49
|
+
# Look at the unschedule_re_dispatch method for an example of
|
50
|
+
# participant implementation that uses re_dispatch.
|
51
|
+
#
|
52
|
+
# Without one of those options, the method is a "reject".
|
53
|
+
#
|
54
|
+
def re_dispatch(workitem, opts={})
|
55
|
+
|
56
|
+
msg = {
|
57
|
+
'action' => 'dispatch',
|
58
|
+
'fei' => workitem.h.fei,
|
59
|
+
'workitem' => workitem.h,
|
60
|
+
'participant_name' => workitem.participant_name,
|
61
|
+
'rejected' => true
|
62
|
+
}
|
63
|
+
|
64
|
+
if t = opts[:in] || opts[:at]
|
65
|
+
|
66
|
+
sched_id = @context.storage.put_schedule('at', workitem.h.fei, t, msg)
|
67
|
+
|
68
|
+
fexp = fetch_flow_expression(workitem)
|
69
|
+
fexp.h['re_dispatch_sched_id'] = sched_id
|
70
|
+
fexp.try_persist
|
71
|
+
|
72
|
+
else
|
73
|
+
|
74
|
+
@context.storage.put_msg('dispatch', msg)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Cancels the scheduled re_dispatch, if any.
|
79
|
+
#
|
80
|
+
# An example or 'retrying participant' :
|
81
|
+
#
|
82
|
+
# class RetryParticipant
|
83
|
+
# include Ruote::LocalParticipant
|
84
|
+
#
|
85
|
+
# def initialize(opts)
|
86
|
+
# @opts = opts
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# def consume(workitem)
|
90
|
+
# begin
|
91
|
+
# do_the_job
|
92
|
+
# reply(workitem)
|
93
|
+
# rescue
|
94
|
+
# re_dispatch(workitem, :in => @opts['delay'] || '1s')
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# def cancel(fei, flavour)
|
99
|
+
# unschedule_re_dispatch(fei)
|
100
|
+
# end
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# Note how unschedule_re_dispatch is used in the cancel method. Warning,
|
104
|
+
# this example could loop forever...
|
105
|
+
#
|
106
|
+
def unschedule_re_dispatch(fei)
|
107
|
+
|
108
|
+
fexp = Ruote::Exp::FlowExpression.fetch(
|
109
|
+
@context, Ruote::FlowExpressionId.extract_h(fei))
|
110
|
+
|
111
|
+
if s = fexp.h['re_dispatch_sched_id']
|
112
|
+
@context.storage.delete_schedule(s)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# This reject method replaces the workitem in the [internal] message queue
|
117
|
+
# of the ruote engine (since it's a local participant, it has access to
|
118
|
+
# the storage and it's thus easy).
|
119
|
+
# The idea is that another worker will pick up the workitem and
|
120
|
+
# do the participant dispatching.
|
121
|
+
#
|
122
|
+
# This is an advanced technique. It was requested by people who
|
123
|
+
# want to have multiple workers and have only certain worker/participants
|
124
|
+
# do the handling.
|
125
|
+
# Using reject is not the best method, it's probably better to implement
|
126
|
+
# this by re-opening the Ruote::Worker class and changing the
|
127
|
+
# cannot_handle(msg) method.
|
128
|
+
#
|
129
|
+
# reject could be useful anyway, not sure now, but one could imagine
|
130
|
+
# scenarii where some participants reject workitems temporarily (while
|
131
|
+
# the same participant on another worker would accept it).
|
132
|
+
#
|
133
|
+
# Well, here it is, use with care.
|
134
|
+
#
|
135
|
+
alias :reject :re_dispatch
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
require 'ruote/part/local_participant'
|
27
|
+
|
28
|
+
|
29
|
+
module Ruote
|
30
|
+
|
31
|
+
#
|
32
|
+
# A participant that simply replies immediately to the engine.
|
33
|
+
#
|
34
|
+
# For testing purposes, but could be useful when used in conjunction with
|
35
|
+
# 'listen'.
|
36
|
+
#
|
37
|
+
class NoOpParticipant
|
38
|
+
|
39
|
+
include LocalParticipant
|
40
|
+
|
41
|
+
def initialize(opts=nil)
|
42
|
+
|
43
|
+
@items = {}
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# No operation : simply replies immediately to the engine.
|
48
|
+
#
|
49
|
+
def consume(workitem)
|
50
|
+
|
51
|
+
reply_to_engine(workitem)
|
52
|
+
end
|
53
|
+
|
54
|
+
def cancel(fei, flavour)
|
55
|
+
|
56
|
+
# nothing to do
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
require 'ruote/part/local_participant'
|
26
|
+
|
27
|
+
|
28
|
+
module Ruote
|
29
|
+
|
30
|
+
#
|
31
|
+
# A /dev/null participant, simply discards the workitems it receives,
|
32
|
+
# without doing anything.
|
33
|
+
#
|
34
|
+
# For testing purposes only.
|
35
|
+
#
|
36
|
+
class NullParticipant
|
37
|
+
|
38
|
+
include LocalParticipant
|
39
|
+
|
40
|
+
def initialize(opts=nil)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Does nothing, discards the workitem it receives.
|
44
|
+
#
|
45
|
+
def consume(workitem)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Does nothing.
|
49
|
+
#
|
50
|
+
def cancel(fei, flavour)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,169 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to deal
|
6
|
+
# in the Software without restriction, including without limitation the rights
|
7
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
# copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
# THE SOFTWARE.
|
21
|
+
#
|
22
|
+
# Made in Japan.
|
23
|
+
#++
|
24
|
+
|
25
|
+
|
26
|
+
require 'open-uri'
|
27
|
+
|
28
|
+
require 'ruote/part/local_participant'
|
29
|
+
|
30
|
+
|
31
|
+
module Ruote
|
32
|
+
|
33
|
+
#
|
34
|
+
# This participant was born out of a suggestion from Jan Topiński in
|
35
|
+
# http://groups.google.com/group/openwferu-users/browse_thread/thread/be20a5d861556fd8
|
36
|
+
#
|
37
|
+
# This participant is a gateway to code placed in a directory.
|
38
|
+
#
|
39
|
+
# engine.register do
|
40
|
+
# toto, Ruote::RevParticipant, :dir => 'participants/toto/'
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# Then in the participants/toto/ dir :
|
44
|
+
#
|
45
|
+
# /my_workflow__0.1__toto_0.6.rb
|
46
|
+
# # participant toto, workflow 'my_workflow' with revision '0.1'
|
47
|
+
# /my_workflow__toto.rb
|
48
|
+
# # participant toto, workflow 'my_workflow' any revision
|
49
|
+
# /toto_0.6.rb
|
50
|
+
# # participant toto with rev '0.6', any workflow
|
51
|
+
# /toto.rb
|
52
|
+
# # participant toto, any rev, any workflow
|
53
|
+
# # ...
|
54
|
+
#
|
55
|
+
# The scheme goes like :
|
56
|
+
#
|
57
|
+
# /wf-name__wf-revision__participant-name__p-revision.rb
|
58
|
+
#
|
59
|
+
# The files themselves look like :
|
60
|
+
#
|
61
|
+
# def consume(workitem)
|
62
|
+
# workitem.fields['kilroy'] = 'was here'
|
63
|
+
# reply_to_engine(workitem)
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# The file directly contains the classical participant methods defined at the
|
67
|
+
# top level. #cancel, #accept?, #on_reply and of course #consume are OK.
|
68
|
+
#
|
69
|
+
#
|
70
|
+
# Maybe, look at the tests for more clues :
|
71
|
+
#
|
72
|
+
# https://github.com/jmettraux/ruote/blob/master/test/functional/ft_57_rev_participant.rb
|
73
|
+
#
|
74
|
+
# *Note* : It's probably not the best participant in a distributed context, it
|
75
|
+
# grabs the code to execute from a directory. If you use it in a distributed
|
76
|
+
# context, you'll have to make sure to synchronize the directory to each host
|
77
|
+
# running a worker.
|
78
|
+
#
|
79
|
+
# *Warning* : this participant trusts the code it deals with, there is no
|
80
|
+
# security check.
|
81
|
+
#
|
82
|
+
class RevParticipant
|
83
|
+
|
84
|
+
include LocalParticipant
|
85
|
+
|
86
|
+
# TODO : how to deal with >= and ~> ?
|
87
|
+
|
88
|
+
def initialize(opts=nil)
|
89
|
+
|
90
|
+
@dir = opts['dir']
|
91
|
+
|
92
|
+
raise ArgumentError.new(
|
93
|
+
"missing option :dir for #{self.class}"
|
94
|
+
) unless @dir
|
95
|
+
end
|
96
|
+
|
97
|
+
def consume(workitem)
|
98
|
+
|
99
|
+
lookup_code(workitem).consume(workitem)
|
100
|
+
end
|
101
|
+
|
102
|
+
def cancel(fei, flavour)
|
103
|
+
|
104
|
+
lookup_code(fei).cancel(fei, flavour)
|
105
|
+
end
|
106
|
+
|
107
|
+
#--
|
108
|
+
#def accept?(workitem)
|
109
|
+
# part = lookup_code(workitem)
|
110
|
+
# part.respond_to?(:accept?) ? part.accept?(workitem) : true
|
111
|
+
#end
|
112
|
+
#
|
113
|
+
# Can't do this at this level, since it isn't the rev_participant's
|
114
|
+
# own accept?, it has to go in lookup_code
|
115
|
+
#++
|
116
|
+
|
117
|
+
def on_reply(workitem)
|
118
|
+
|
119
|
+
part = lookup_code(workitem)
|
120
|
+
part.on_reply(workitem) if part.respond_to?(:on_reply)
|
121
|
+
end
|
122
|
+
|
123
|
+
def rtimeout(workitem)
|
124
|
+
|
125
|
+
part = lookup_code(workitem)
|
126
|
+
|
127
|
+
part.respond_to?(:rtimeout) ? part.rtimeout(workitem) : nil
|
128
|
+
end
|
129
|
+
|
130
|
+
protected
|
131
|
+
|
132
|
+
# Maybe "lookup_real_participant_code" would be a better name...
|
133
|
+
#
|
134
|
+
def lookup_code(wi_or_fei)
|
135
|
+
|
136
|
+
wi = wi_or_fei.is_a?(Ruote::Workitem) ? wi_or_fei : workitem(wi_or_fei)
|
137
|
+
|
138
|
+
rev = wi.params['revision'] || wi.params['rev']
|
139
|
+
|
140
|
+
[
|
141
|
+
[ wi.wf_name, wi.wf_revision, wi.participant_name, rev ],
|
142
|
+
[ wi.wf_name, wi.wf_revision, wi.participant_name ],
|
143
|
+
[ wi.wf_name, '', wi.participant_name ],
|
144
|
+
[ wi.participant_name, rev ],
|
145
|
+
[ wi.participant_name ],
|
146
|
+
].each do |fname|
|
147
|
+
|
148
|
+
fname = File.join(@dir, "#{fname.compact.join('__')}.rb")
|
149
|
+
next unless File.exist?(fname)
|
150
|
+
|
151
|
+
cpart = Class.new
|
152
|
+
cpart.send(:include, Ruote::LocalParticipant)
|
153
|
+
cpart.module_eval(File.read(fname))
|
154
|
+
part = cpart.new
|
155
|
+
part.context = @context
|
156
|
+
|
157
|
+
next if part.respond_to?(:accept?) and (not part.accept?(wi))
|
158
|
+
|
159
|
+
return part
|
160
|
+
end
|
161
|
+
|
162
|
+
raise ArgumentError.new(
|
163
|
+
"couldn't find code for participant #{wi.participant_name} " +
|
164
|
+
"in dir #{@dir}"
|
165
|
+
)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|