ruote 2.2.0 → 2.3.0
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 +166 -1
- data/CREDITS.txt +36 -17
- data/LICENSE.txt +1 -1
- data/README.rdoc +1 -7
- data/Rakefile +38 -29
- data/TODO.txt +93 -52
- data/lib/ruote-fs.rb +3 -0
- data/lib/ruote.rb +5 -1
- data/lib/ruote/context.rb +140 -35
- data/lib/ruote/dashboard.rb +1247 -0
- data/lib/ruote/{engine → dboard}/process_error.rb +22 -2
- data/lib/ruote/dboard/process_status.rb +587 -0
- data/lib/ruote/engine.rb +6 -871
- data/lib/ruote/exp/command.rb +7 -2
- data/lib/ruote/exp/commanded.rb +2 -2
- data/lib/ruote/exp/condition.rb +38 -13
- data/lib/ruote/exp/fe_add_branches.rb +1 -1
- data/lib/ruote/exp/fe_apply.rb +1 -1
- data/lib/ruote/exp/fe_await.rb +357 -0
- data/lib/ruote/exp/fe_cancel_process.rb +17 -3
- data/lib/ruote/exp/fe_command.rb +8 -4
- data/lib/ruote/exp/fe_concurrence.rb +218 -18
- data/lib/ruote/exp/fe_concurrent_iterator.rb +71 -10
- data/lib/ruote/exp/fe_cron.rb +3 -10
- data/lib/ruote/exp/fe_cursor.rb +14 -4
- data/lib/ruote/exp/fe_define.rb +3 -1
- data/lib/ruote/exp/fe_echo.rb +1 -1
- data/lib/ruote/exp/fe_equals.rb +1 -1
- data/lib/ruote/exp/fe_error.rb +1 -1
- data/lib/ruote/exp/fe_filter.rb +163 -4
- data/lib/ruote/exp/fe_forget.rb +21 -4
- data/lib/ruote/exp/fe_given.rb +1 -1
- data/lib/ruote/exp/fe_if.rb +1 -1
- data/lib/ruote/exp/fe_inc.rb +102 -35
- data/lib/ruote/exp/fe_iterator.rb +47 -12
- data/lib/ruote/exp/fe_listen.rb +96 -11
- data/lib/ruote/exp/fe_lose.rb +31 -4
- data/lib/ruote/exp/fe_noop.rb +1 -1
- data/lib/ruote/exp/fe_on_error.rb +109 -0
- data/lib/ruote/exp/fe_once.rb +10 -19
- data/lib/ruote/exp/fe_participant.rb +90 -28
- data/lib/ruote/exp/fe_read.rb +69 -0
- data/lib/ruote/exp/fe_redo.rb +3 -2
- data/lib/ruote/exp/fe_ref.rb +57 -27
- data/lib/ruote/exp/fe_registerp.rb +1 -3
- data/lib/ruote/exp/fe_reserve.rb +1 -1
- data/lib/ruote/exp/fe_restore.rb +6 -6
- data/lib/ruote/exp/fe_save.rb +12 -19
- data/lib/ruote/exp/fe_sequence.rb +38 -2
- data/lib/ruote/exp/fe_set.rb +143 -40
- data/lib/ruote/exp/{fe_let.rb → fe_stall.rb} +7 -38
- data/lib/ruote/exp/fe_subprocess.rb +8 -2
- data/lib/ruote/exp/fe_that.rb +1 -1
- data/lib/ruote/exp/fe_undo.rb +40 -4
- data/lib/ruote/exp/fe_unregisterp.rb +1 -3
- data/lib/ruote/exp/fe_wait.rb +12 -25
- data/lib/ruote/exp/{flowexpression.rb → flow_expression.rb} +375 -229
- data/lib/ruote/exp/iterator.rb +2 -2
- data/lib/ruote/exp/merge.rb +78 -17
- data/lib/ruote/exp/ro_attributes.rb +46 -36
- data/lib/ruote/exp/ro_filters.rb +34 -8
- data/lib/ruote/exp/ro_on_x.rb +431 -0
- data/lib/ruote/exp/ro_persist.rb +19 -7
- data/lib/ruote/exp/ro_timers.rb +123 -0
- data/lib/ruote/exp/ro_variables.rb +90 -29
- data/lib/ruote/fei.rb +57 -3
- data/lib/ruote/fs.rb +3 -0
- data/lib/ruote/id/mnemo_wfid_generator.rb +30 -7
- data/lib/ruote/id/wfid_generator.rb +17 -38
- data/lib/ruote/log/default_history.rb +23 -9
- data/lib/ruote/log/fancy_printing.rb +265 -0
- data/lib/ruote/log/storage_history.rb +23 -13
- data/lib/ruote/log/wait_logger.rb +224 -17
- data/lib/ruote/observer.rb +82 -0
- data/lib/ruote/part/block_participant.rb +65 -28
- data/lib/ruote/part/code_participant.rb +81 -0
- data/lib/ruote/part/engine_participant.rb +7 -2
- data/lib/ruote/part/local_participant.rb +221 -21
- data/lib/ruote/part/no_op_participant.rb +1 -1
- data/lib/ruote/part/null_participant.rb +1 -1
- data/lib/ruote/part/participant.rb +50 -0
- data/lib/ruote/part/rev_participant.rb +178 -0
- data/lib/ruote/part/smtp_participant.rb +2 -2
- data/lib/ruote/part/storage_participant.rb +228 -60
- data/lib/ruote/part/template.rb +1 -1
- data/lib/ruote/participant.rb +2 -0
- data/lib/ruote/reader.rb +205 -68
- data/lib/ruote/reader/json.rb +49 -0
- data/lib/ruote/reader/radial.rb +303 -0
- data/lib/ruote/reader/ruby_dsl.rb +44 -9
- data/lib/ruote/reader/xml.rb +11 -8
- data/lib/ruote/receiver/base.rb +98 -45
- data/lib/ruote/storage/base.rb +104 -35
- data/lib/ruote/storage/composite_storage.rb +50 -60
- data/lib/ruote/storage/fs_storage.rb +25 -34
- data/lib/ruote/storage/hash_storage.rb +38 -36
- data/lib/ruote/svc/dispatch_pool.rb +104 -35
- data/lib/ruote/svc/dollar_sub.rb +10 -8
- data/lib/ruote/svc/error_handler.rb +108 -52
- data/lib/ruote/svc/expression_map.rb +3 -3
- data/lib/ruote/svc/participant_list.rb +160 -55
- data/lib/ruote/svc/tracker.rb +31 -31
- data/lib/ruote/svc/treechecker.rb +28 -16
- data/lib/ruote/tree_dot.rb +1 -1
- data/lib/ruote/util/deep.rb +143 -0
- data/lib/ruote/util/filter.rb +125 -18
- data/lib/ruote/util/hashdot.rb +15 -13
- data/lib/ruote/util/look.rb +1 -1
- data/lib/ruote/util/lookup.rb +60 -22
- data/lib/ruote/util/misc.rb +63 -18
- data/lib/ruote/util/mpatch.rb +53 -0
- data/lib/ruote/util/ometa.rb +1 -2
- data/lib/ruote/util/process_observer.rb +177 -0
- data/lib/ruote/util/subprocess.rb +1 -1
- data/lib/ruote/util/time.rb +2 -2
- data/lib/ruote/util/tree.rb +64 -2
- data/lib/ruote/version.rb +3 -2
- data/lib/ruote/worker.rb +421 -92
- data/lib/ruote/workitem.rb +157 -22
- data/ruote.gemspec +15 -9
- data/test/bm/ci.rb +0 -2
- data/test/bm/ici.rb +0 -2
- data/test/bm/load_26c.rb +0 -3
- data/test/bm/mega.rb +0 -2
- data/test/functional/base.rb +57 -43
- data/test/functional/concurrent_base.rb +16 -13
- data/test/functional/ct_0_concurrence.rb +7 -11
- data/test/functional/ct_1_iterator.rb +9 -11
- data/test/functional/ct_2_cancel.rb +28 -17
- data/test/functional/eft_0_flow_expression.rb +35 -0
- data/test/functional/eft_10_cancel_process.rb +1 -1
- data/test/functional/eft_11_wait.rb +13 -13
- data/test/functional/eft_12_listen.rb +199 -66
- data/test/functional/eft_13_iterator.rb +95 -29
- data/test/functional/eft_14_cursor.rb +74 -24
- data/test/functional/eft_15_loop.rb +7 -7
- data/test/functional/eft_16_if.rb +1 -1
- data/test/functional/eft_17_equals.rb +1 -1
- data/test/functional/eft_18_concurrent_iterator.rb +156 -68
- data/test/functional/eft_19_reserve.rb +15 -15
- data/test/functional/eft_1_echo.rb +1 -1
- data/test/functional/eft_20_save.rb +51 -9
- data/test/functional/eft_21_restore.rb +1 -1
- data/test/functional/eft_22_noop.rb +1 -1
- data/test/functional/eft_23_apply.rb +1 -1
- data/test/functional/eft_24_add_branches.rb +7 -8
- data/test/functional/eft_25_command.rb +1 -1
- data/test/functional/eft_26_error.rb +11 -11
- data/test/functional/eft_27_inc.rb +111 -67
- data/test/functional/eft_28_once.rb +16 -16
- data/test/functional/eft_29_cron.rb +9 -9
- data/test/functional/eft_2_sequence.rb +23 -4
- data/test/functional/eft_30_ref.rb +36 -24
- data/test/functional/eft_31_registerp.rb +24 -24
- data/test/functional/eft_32_lose.rb +46 -20
- data/test/functional/eft_34_given.rb +1 -1
- data/test/functional/eft_35_filter.rb +161 -7
- data/test/functional/eft_36_read.rb +97 -0
- data/test/functional/{eft_0_process_definition.rb → eft_37_process_definition.rb} +4 -4
- data/test/functional/eft_38_on_error.rb +195 -0
- data/test/functional/eft_39_stall.rb +35 -0
- data/test/functional/eft_3_participant.rb +77 -22
- data/test/functional/eft_40_await.rb +297 -0
- data/test/functional/eft_4_set.rb +110 -11
- data/test/functional/eft_5_subprocess.rb +27 -5
- data/test/functional/eft_6_concurrence.rb +299 -60
- data/test/functional/eft_7_forget.rb +24 -22
- data/test/functional/eft_8_undo.rb +52 -15
- data/test/functional/eft_9_redo.rb +18 -20
- data/test/functional/ft_0_worker.rb +122 -13
- data/test/functional/ft_10_dollar.rb +77 -16
- data/test/functional/ft_11_recursion.rb +9 -9
- data/test/functional/ft_12_launchitem.rb +7 -9
- data/test/functional/ft_13_variables.rb +125 -22
- data/test/functional/ft_14_re_apply.rb +112 -56
- data/test/functional/ft_15_timeout.rb +64 -33
- data/test/functional/ft_16_participant_params.rb +59 -6
- data/test/functional/ft_17_conditional.rb +68 -2
- data/test/functional/ft_18_kill.rb +48 -30
- data/test/functional/ft_19_participant_code.rb +67 -0
- data/test/functional/ft_1_process_status.rb +222 -150
- data/test/functional/ft_20_storage_participant.rb +445 -44
- data/test/functional/ft_21_forget.rb +21 -26
- data/test/functional/ft_22_process_definitions.rb +8 -6
- data/test/functional/ft_23_load_defs.rb +29 -5
- data/test/functional/ft_24_block_participant.rb +199 -20
- data/test/functional/ft_25_receiver.rb +98 -46
- data/test/functional/ft_26_participant_rtimeout.rb +34 -26
- data/test/functional/ft_27_var_indirection.rb +40 -5
- data/test/functional/ft_28_null_noop_participants.rb +5 -5
- data/test/functional/ft_29_part_template.rb +2 -2
- data/test/functional/ft_2_errors.rb +106 -74
- data/test/functional/ft_30_smtp_participant.rb +7 -7
- data/test/functional/ft_31_part_blocking.rb +11 -11
- data/test/functional/ft_32_scope.rb +50 -0
- data/test/functional/ft_33_participant_subprocess_priority.rb +3 -3
- data/test/functional/ft_34_cursor_rewind.rb +14 -14
- data/test/functional/ft_35_add_service.rb +67 -9
- data/test/functional/ft_36_storage_history.rb +92 -24
- data/test/functional/ft_37_default_history.rb +35 -23
- data/test/functional/ft_38_participant_more.rb +189 -32
- data/test/functional/ft_39_wait_for.rb +25 -25
- data/test/functional/ft_3_participant_registration.rb +235 -107
- data/test/functional/ft_40_wait_logger.rb +105 -18
- data/test/functional/ft_41_participants.rb +13 -12
- data/test/functional/ft_42_storage_copy.rb +12 -12
- data/test/functional/ft_43_participant_on_reply.rb +85 -11
- data/test/functional/ft_44_var_participant.rb +5 -5
- data/test/functional/ft_45_participant_accept.rb +3 -3
- data/test/functional/ft_46_launch_single.rb +17 -17
- data/test/functional/ft_47_wfids.rb +41 -0
- data/test/functional/ft_48_lose.rb +19 -25
- data/test/functional/ft_49_engine_on_error.rb +54 -70
- data/test/functional/ft_4_cancel.rb +84 -26
- data/test/functional/ft_50_engine_config.rb +4 -4
- data/test/functional/ft_51_misc.rb +12 -12
- data/test/functional/ft_52_case.rb +17 -17
- data/test/functional/ft_53_engine_on_terminate.rb +18 -21
- data/test/functional/ft_54_patterns.rb +18 -16
- data/test/functional/ft_55_engine_participant.rb +55 -55
- data/test/functional/ft_56_filter_attribute.rb +90 -52
- data/test/functional/ft_57_rev_participant.rb +252 -0
- data/test/functional/ft_58_workitem.rb +150 -0
- data/test/functional/ft_59_pause.rb +329 -0
- data/test/functional/ft_5_on_error.rb +430 -77
- data/test/functional/ft_60_code_participant.rb +65 -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_63_participants_221.rb +458 -0
- data/test/functional/ft_64_stash.rb +41 -0
- data/test/functional/ft_65_timers.rb +313 -0
- data/test/functional/ft_66_flank.rb +133 -0
- data/test/functional/ft_67_radial_misc.rb +34 -0
- data/test/functional/ft_68_reput.rb +72 -0
- data/test/functional/ft_69_worker_info.rb +56 -0
- data/test/functional/ft_6_on_cancel.rb +189 -36
- data/test/functional/ft_70_take_and_discard_attributes.rb +94 -0
- data/test/functional/ft_71_retries.rb +144 -0
- data/test/functional/ft_72_on_terminate.rb +60 -0
- data/test/functional/ft_73_raise_msg.rb +107 -0
- data/test/functional/ft_74_respark.rb +106 -0
- data/test/functional/ft_75_context.rb +66 -0
- data/test/functional/ft_76_observer.rb +53 -0
- data/test/functional/ft_77_process_observer.rb +157 -0
- data/test/functional/ft_78_part_participant.rb +37 -0
- data/test/functional/ft_7_tags.rb +238 -50
- data/test/functional/ft_8_participant_consumption.rb +27 -21
- data/test/functional/ft_9_subprocesses.rb +48 -18
- data/test/functional/restart_base.rb +4 -6
- data/test/functional/rt_0_wait.rb +10 -10
- data/test/functional/rt_1_listen.rb +6 -6
- data/test/functional/rt_2_errors.rb +12 -12
- data/test/functional/rt_3_once.rb +17 -12
- data/test/functional/rt_4_cron.rb +17 -17
- data/test/functional/rt_5_timeout.rb +13 -13
- data/test/functional/signals.rb +103 -0
- data/test/functional/storage.rb +730 -0
- data/test/functional/storage_helper.rb +48 -35
- data/test/functional/test.rb +6 -2
- data/test/misc/idle.rb +21 -0
- data/test/misc/light.rb +29 -0
- data/test/path_helper.rb +1 -1
- data/test/test.rb +2 -5
- data/test/test_helper.rb +13 -0
- data/test/unit/test.rb +1 -4
- data/test/unit/ut_0_ruby_reader.rb +25 -9
- data/test/unit/ut_10_participants.rb +47 -0
- data/test/unit/ut_11_lookup.rb +59 -2
- data/test/unit/ut_12_wait_logger.rb +123 -0
- data/test/unit/ut_14_is_uri.rb +1 -1
- data/test/unit/ut_15_util.rb +1 -1
- data/test/unit/ut_16_reader.rb +136 -14
- data/test/unit/ut_17_merge.rb +155 -0
- data/test/unit/ut_19_part_template.rb +1 -1
- data/test/unit/ut_1_fei.rb +11 -2
- data/test/unit/ut_20_composite_storage.rb +27 -1
- data/test/unit/{ut_21_participant_list.rb → ut_21_svc_participant_list.rb} +2 -3
- data/test/unit/ut_22_filter.rb +231 -10
- data/test/unit/ut_23_svc_tracker.rb +48 -0
- data/test/unit/ut_24_radial_reader.rb +458 -0
- data/test/unit/ut_25_process_status.rb +143 -0
- data/test/unit/ut_26_deep.rb +131 -0
- data/test/unit/ut_2_dashboard.rb +114 -0
- data/test/unit/ut_3_worker.rb +54 -0
- data/test/unit/ut_4_expmap.rb +1 -1
- data/test/unit/ut_5_tree.rb +23 -23
- data/test/unit/ut_6_condition.rb +71 -29
- data/test/unit/ut_7_workitem.rb +18 -4
- data/test/unit/ut_8_tree_to_dot.rb +1 -1
- data/test/unit/ut_9_xml_reader.rb +1 -1
- metadata +142 -63
- data/jruby_issue.txt +0 -32
- data/lib/ruote/engine/process_status.rb +0 -403
- data/lib/ruote/log/pretty.rb +0 -165
- data/lib/ruote/log/test_logger.rb +0 -204
- data/lib/ruote/util/serializer.rb +0 -103
- data/phil.txt +0 -14
- data/test/functional/eft_33_let.rb +0 -31
- data/test/functional/ft_19_alias.rb +0 -33
- data/test/functional/ft_47_wfid_generator.rb +0 -54
- data/test/unit/storage.rb +0 -403
- data/test/unit/storages.rb +0 -37
- data/test/unit/ut_13_serializer.rb +0 -65
- data/test/unit/ut_18_engine.rb +0 -47
- data/test/unit/ut_3_wait_logger.rb +0 -39
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
2
|
+
# Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -183,7 +183,13 @@ module Ruote::Exp
|
|
|
183
183
|
|
|
184
184
|
pos, subtree = Ruote.lookup_subprocess(self, ref)
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
fs, vs = compile_atts.partition { |k, v| k.match(/^f(ield)?:./) }
|
|
187
|
+
|
|
188
|
+
fields = h.applied_workitem['fields']
|
|
189
|
+
fs.each { |k, v| Ruote.set(fields, k.split(':', 2).last, v) }
|
|
190
|
+
|
|
191
|
+
vars = Hash[vs.collect { |k, v| [ k.split(':', 2).last, v ] }]
|
|
192
|
+
|
|
187
193
|
vars.merge!('tree' => tree_children.first)
|
|
188
194
|
# NOTE : we're taking the first child here...
|
|
189
195
|
|
data/lib/ruote/exp/fe_that.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
2
|
+
# Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
data/lib/ruote/exp/fe_undo.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
2
|
+
# Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -44,16 +44,52 @@ module Ruote::Exp
|
|
|
44
44
|
#
|
|
45
45
|
# cancel :ref => 'invoicing_stage'
|
|
46
46
|
#
|
|
47
|
+
# == a bit shorter
|
|
48
|
+
#
|
|
49
|
+
# It's OK to shorten
|
|
50
|
+
#
|
|
51
|
+
# cancel :ref => 'invoicing_stage'
|
|
52
|
+
#
|
|
53
|
+
# to
|
|
54
|
+
#
|
|
55
|
+
# cancel 'invoicing_stage'
|
|
56
|
+
#
|
|
57
|
+
# == kill
|
|
58
|
+
#
|
|
59
|
+
# kill :ref => 'invoicing stage'
|
|
60
|
+
#
|
|
61
|
+
# will cancel the target expression and bypass any on_cancel handler set for
|
|
62
|
+
# it.
|
|
63
|
+
#
|
|
64
|
+
# concurrence do
|
|
65
|
+
# sequence :tag => 'x', :on_cancel => 'y' do
|
|
66
|
+
# # ...
|
|
67
|
+
# end
|
|
68
|
+
# sequence do
|
|
69
|
+
# # ...
|
|
70
|
+
# kill 'x'
|
|
71
|
+
# end
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
74
|
+
# In this example the :on_cancel => 'y' will get ignored if kill 'x' kicks
|
|
75
|
+
# in.
|
|
76
|
+
#
|
|
47
77
|
class UndoExpression < FlowExpression
|
|
48
78
|
|
|
49
|
-
names :undo, :cancel
|
|
79
|
+
names :undo, :cancel, :kill
|
|
50
80
|
|
|
51
81
|
def apply
|
|
52
82
|
|
|
53
83
|
ref = attribute(:ref) || attribute_text
|
|
54
|
-
|
|
84
|
+
ref = ref.strip if ref
|
|
85
|
+
|
|
86
|
+
tag = (ref && ref != '') ? lookup_variable(ref) : nil
|
|
55
87
|
|
|
56
|
-
@context.storage.put_msg(
|
|
88
|
+
@context.storage.put_msg(
|
|
89
|
+
'cancel',
|
|
90
|
+
'fei' => tag,
|
|
91
|
+
'flavour' => self.name == 'kill' ? 'kill' : nil
|
|
92
|
+
) if Ruote.is_a_fei?(tag)
|
|
57
93
|
|
|
58
94
|
reply_to_parent(h.applied_workitem)
|
|
59
95
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
2
|
+
# Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -27,8 +27,6 @@ require 'ruote/exp/fe_registerp'
|
|
|
27
27
|
|
|
28
28
|
module Ruote::Exp
|
|
29
29
|
|
|
30
|
-
#
|
|
31
|
-
# (Since ruote 2.1.12)
|
|
32
30
|
#
|
|
33
31
|
# Unregisters a participant.
|
|
34
32
|
#
|
data/lib/ruote/exp/fe_wait.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
2
|
+
# Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -56,27 +56,20 @@ module Ruote::Exp
|
|
|
56
56
|
h.for = attribute(:for) || attribute_text
|
|
57
57
|
h.until = attribute(:until)
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
h.at = h.for
|
|
60
|
+
h.at = h.until if h.at == ''
|
|
61
61
|
|
|
62
|
-
h.
|
|
62
|
+
return reply_to_parent(h.applied_workitem) unless h.at
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
h.schedule_id = @context.storage.put_schedule(
|
|
65
|
+
'at',
|
|
66
|
+
h.fei,
|
|
67
|
+
h.at,
|
|
68
|
+
'action' => 'reply',
|
|
69
|
+
'fei' => h.fei,
|
|
70
|
+
'workitem' => h.applied_workitem)
|
|
65
71
|
|
|
66
|
-
|
|
67
|
-
'at',
|
|
68
|
-
h.fei,
|
|
69
|
-
h.at,
|
|
70
|
-
'action' => 'reply',
|
|
71
|
-
'fei' => h.fei,
|
|
72
|
-
'workitem' => h.applied_workitem)
|
|
73
|
-
|
|
74
|
-
persist_or_raise
|
|
75
|
-
|
|
76
|
-
else
|
|
77
|
-
|
|
78
|
-
reply_to_parent(h.applied_workitem)
|
|
79
|
-
end
|
|
72
|
+
persist_or_raise
|
|
80
73
|
end
|
|
81
74
|
|
|
82
75
|
#--
|
|
@@ -84,12 +77,6 @@ module Ruote::Exp
|
|
|
84
77
|
#def reply (workitem)
|
|
85
78
|
#end
|
|
86
79
|
#++
|
|
87
|
-
|
|
88
|
-
def cancel(flavour)
|
|
89
|
-
|
|
90
|
-
@context.storage.delete_schedule(h.schedule_id)
|
|
91
|
-
reply_to_parent(h.applied_workitem)
|
|
92
|
-
end
|
|
93
80
|
end
|
|
94
81
|
end
|
|
95
82
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
2
|
+
# Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -52,20 +52,50 @@ module Ruote::Exp
|
|
|
52
52
|
#
|
|
53
53
|
# Each node is an expression...
|
|
54
54
|
#
|
|
55
|
+
#
|
|
56
|
+
# == the states of an expression
|
|
57
|
+
#
|
|
58
|
+
# === nil
|
|
59
|
+
# the normal state
|
|
60
|
+
#
|
|
61
|
+
# === 'cancelling'
|
|
62
|
+
# the expression and its children are getting cancelled
|
|
63
|
+
#
|
|
64
|
+
# === 'dying'
|
|
65
|
+
# the expression and its children are getting killed
|
|
66
|
+
#
|
|
67
|
+
# === 'failed'
|
|
68
|
+
# the expression has finishing
|
|
69
|
+
#
|
|
70
|
+
# === 'failing'
|
|
71
|
+
# the expression just failed and it's cancelling its children
|
|
72
|
+
#
|
|
73
|
+
# === 'timing_out'
|
|
74
|
+
# the expression just timedout and it's cancelling its children
|
|
75
|
+
#
|
|
76
|
+
# === 'paused'
|
|
77
|
+
# the expression is paused, it will store downstream messages and play
|
|
78
|
+
# them only when a 'resume' message comes from upstream.
|
|
79
|
+
#
|
|
55
80
|
class FlowExpression
|
|
56
81
|
|
|
57
82
|
include Ruote::WithH
|
|
58
83
|
include Ruote::WithMeta
|
|
59
84
|
|
|
60
|
-
require 'ruote/exp/ro_persist'
|
|
61
85
|
require 'ruote/exp/ro_attributes'
|
|
62
|
-
require 'ruote/exp/ro_variables'
|
|
63
86
|
require 'ruote/exp/ro_filters'
|
|
87
|
+
require 'ruote/exp/ro_on_x'
|
|
88
|
+
require 'ruote/exp/ro_persist'
|
|
89
|
+
require 'ruote/exp/ro_timers'
|
|
90
|
+
require 'ruote/exp/ro_variables'
|
|
64
91
|
|
|
65
92
|
COMMON_ATT_KEYS = %w[
|
|
66
|
-
if unless
|
|
93
|
+
if unless
|
|
94
|
+
forget lose flank
|
|
95
|
+
timeout timers
|
|
96
|
+
on_error on_cancel on_timeout
|
|
97
|
+
]
|
|
67
98
|
|
|
68
|
-
attr_reader :context
|
|
69
99
|
attr_reader :h
|
|
70
100
|
|
|
71
101
|
h_reader :variables
|
|
@@ -79,6 +109,17 @@ module Ruote::Exp
|
|
|
79
109
|
h_reader :on_error
|
|
80
110
|
h_reader :on_cancel
|
|
81
111
|
h_reader :on_timeout
|
|
112
|
+
h_reader :on_terminate
|
|
113
|
+
|
|
114
|
+
attr_reader :context
|
|
115
|
+
|
|
116
|
+
# Mostly used when the expression is returned via Ruote::Engine#ps(wfid) or
|
|
117
|
+
# Ruote::Engine#processes(). If an error occurred for this flow expression,
|
|
118
|
+
# #ps will set this error field so that it yields the ProcessError.
|
|
119
|
+
#
|
|
120
|
+
# So, for short, usually, this attribute yields nil.
|
|
121
|
+
#
|
|
122
|
+
attr_accessor :error
|
|
82
123
|
|
|
83
124
|
def initialize(context, h)
|
|
84
125
|
|
|
@@ -99,13 +140,13 @@ module Ruote::Exp
|
|
|
99
140
|
h.on_cancel ||= attribute(:on_cancel)
|
|
100
141
|
h.on_error ||= attribute(:on_error)
|
|
101
142
|
h.on_timeout ||= attribute(:on_timeout)
|
|
143
|
+
h.on_terminate ||= attribute(:on_terminate)
|
|
102
144
|
end
|
|
103
145
|
|
|
104
146
|
def h=(hash)
|
|
147
|
+
|
|
105
148
|
@h = hash
|
|
106
|
-
class << h
|
|
107
|
-
include Ruote::HashDot
|
|
108
|
-
end
|
|
149
|
+
class << @h; include Ruote::HashDot; end
|
|
109
150
|
end
|
|
110
151
|
|
|
111
152
|
# Returns the Ruote::FlowExpressionId for this expression.
|
|
@@ -115,12 +156,22 @@ module Ruote::Exp
|
|
|
115
156
|
Ruote::FlowExpressionId.new(h.fei)
|
|
116
157
|
end
|
|
117
158
|
|
|
159
|
+
# Returns the workflow instance id of the workflow this expression
|
|
160
|
+
# belongs to.
|
|
161
|
+
#
|
|
162
|
+
def wfid
|
|
163
|
+
|
|
164
|
+
h.fei['wfid']
|
|
165
|
+
end
|
|
166
|
+
|
|
118
167
|
# Returns the Ruote::FlowExpressionIf of the parent expression, or nil
|
|
119
168
|
# if there is no parent expression.
|
|
120
169
|
#
|
|
121
170
|
def parent_id
|
|
122
171
|
|
|
123
|
-
h.parent_id ?
|
|
172
|
+
h.parent_id ?
|
|
173
|
+
Ruote::FlowExpressionId.new(h.parent_id) :
|
|
174
|
+
nil
|
|
124
175
|
end
|
|
125
176
|
|
|
126
177
|
# Fetches the parent expression, or returns nil if there is no parent
|
|
@@ -128,7 +179,34 @@ module Ruote::Exp
|
|
|
128
179
|
#
|
|
129
180
|
def parent
|
|
130
181
|
|
|
131
|
-
|
|
182
|
+
h.parent_id ?
|
|
183
|
+
Ruote::Exp::FlowExpression.fetch(@context, h.parent_id) :
|
|
184
|
+
nil
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Returns the root expression of this expression.
|
|
188
|
+
#
|
|
189
|
+
# The result is an instance of Ruote::FlowExpression or nil if the
|
|
190
|
+
# parent cannot be found.
|
|
191
|
+
#
|
|
192
|
+
def root
|
|
193
|
+
|
|
194
|
+
current = @h
|
|
195
|
+
exps = @context.storage.find_expressions(h.fei['wfid'])
|
|
196
|
+
|
|
197
|
+
while current && current['parent_id']
|
|
198
|
+
current = exps.find { |e| e['fei'] == current['parent_id'] }
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
current ? Ruote::Exp::FlowExpression.from_h(@context, current) : nil
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# Returns the fei of the root expression of this expression.
|
|
205
|
+
# The result is an instance of Ruote::FlowExpressionId.
|
|
206
|
+
#
|
|
207
|
+
def root_id
|
|
208
|
+
|
|
209
|
+
root.fei
|
|
132
210
|
end
|
|
133
211
|
|
|
134
212
|
# Turns this FlowExpression instance into a Hash (well, just hands back
|
|
@@ -139,10 +217,19 @@ module Ruote::Exp
|
|
|
139
217
|
@h
|
|
140
218
|
end
|
|
141
219
|
|
|
220
|
+
# Returns a one-off Ruote::Workitem instance (the applied workitem).
|
|
221
|
+
#
|
|
222
|
+
def applied_workitem
|
|
223
|
+
|
|
224
|
+
@awi ||= Ruote::Workitem.new(h.applied_workitem)
|
|
225
|
+
end
|
|
226
|
+
|
|
142
227
|
# Instantiates expression back from hash.
|
|
143
228
|
#
|
|
144
229
|
def self.from_h(context, h)
|
|
145
230
|
|
|
231
|
+
return self.new(nil, h) unless context
|
|
232
|
+
|
|
146
233
|
exp_class = context.expmap.expression_class(h['name'])
|
|
147
234
|
|
|
148
235
|
exp_class.new(context, h)
|
|
@@ -182,8 +269,6 @@ module Ruote::Exp
|
|
|
182
269
|
fei = msg['fei']
|
|
183
270
|
action = msg['action']
|
|
184
271
|
|
|
185
|
-
p msg unless fei
|
|
186
|
-
|
|
187
272
|
if action == 'reply' && fei['engine_id'] != context.engine_id
|
|
188
273
|
#
|
|
189
274
|
# the reply has to go to another engine, let's locate the
|
|
@@ -206,14 +291,26 @@ module Ruote::Exp
|
|
|
206
291
|
|
|
207
292
|
fexp = nil
|
|
208
293
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
294
|
+
n = context.storage.class.name.match(/Couch/) ? 3 : 1
|
|
295
|
+
#
|
|
296
|
+
n.times do |i|
|
|
297
|
+
if fexp = fetch(context, msg['fei']); break; end
|
|
298
|
+
sleep 0.028 unless i == (n - 1)
|
|
213
299
|
end
|
|
214
|
-
#
|
|
300
|
+
#
|
|
301
|
+
# Simplify that once ruote-couch behaves
|
|
302
|
+
|
|
303
|
+
fexp.do(action, msg) if fexp
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# Wraps a call to "apply", "reply", etc... Makes sure to set @msg
|
|
307
|
+
# with a deep copy of the msg before.
|
|
308
|
+
#
|
|
309
|
+
def do(action, msg)
|
|
310
|
+
|
|
311
|
+
@msg = Ruote.fulldup(msg)
|
|
215
312
|
|
|
216
|
-
|
|
313
|
+
send("do_#{action}", msg)
|
|
217
314
|
end
|
|
218
315
|
|
|
219
316
|
# Called by the worker when it has just created this FlowExpression and
|
|
@@ -221,34 +318,51 @@ module Ruote::Exp
|
|
|
221
318
|
#
|
|
222
319
|
def do_apply(msg)
|
|
223
320
|
|
|
224
|
-
|
|
321
|
+
unless Condition.apply?(attribute(:if), attribute(:unless))
|
|
322
|
+
|
|
323
|
+
return do_reply_to_parent(h.applied_workitem)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
pi = h.parent_id
|
|
327
|
+
reply_immediately = false
|
|
225
328
|
|
|
226
|
-
if
|
|
329
|
+
if attribute(:scope).to_s == 'true'
|
|
227
330
|
|
|
228
|
-
|
|
331
|
+
h.variables ||= {}
|
|
229
332
|
end
|
|
230
333
|
|
|
231
334
|
if attribute(:forget).to_s == 'true'
|
|
232
335
|
|
|
233
|
-
pi = h.parent_id
|
|
234
|
-
wi = Ruote.fulldup(h.applied_workitem)
|
|
235
|
-
|
|
236
336
|
h.variables = compile_variables
|
|
237
337
|
h.parent_id = nil
|
|
238
338
|
h.forgotten = true
|
|
239
339
|
|
|
240
|
-
|
|
241
|
-
# reply to parent immediately (if there is a parent)
|
|
340
|
+
reply_immediately = true
|
|
242
341
|
|
|
243
342
|
elsif attribute(:lose).to_s == 'true'
|
|
244
343
|
|
|
245
344
|
h.lost = true
|
|
345
|
+
|
|
346
|
+
elsif msg['flanking'] or (attribute(:flank).to_s == 'true')
|
|
347
|
+
|
|
348
|
+
h.flanking = true
|
|
349
|
+
|
|
350
|
+
reply_immediately = true
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
if reply_immediately and pi
|
|
354
|
+
|
|
355
|
+
@context.storage.put_msg(
|
|
356
|
+
'reply',
|
|
357
|
+
'fei' => pi,
|
|
358
|
+
'workitem' => Ruote.fulldup(h.applied_workitem),
|
|
359
|
+
'flanking' => h.flanking)
|
|
246
360
|
end
|
|
247
361
|
|
|
248
362
|
filter
|
|
249
363
|
|
|
250
364
|
consider_tag
|
|
251
|
-
|
|
365
|
+
consider_timers
|
|
252
366
|
|
|
253
367
|
apply
|
|
254
368
|
end
|
|
@@ -257,50 +371,97 @@ module Ruote::Exp
|
|
|
257
371
|
# parent expression to take over (it will end up calling the #reply of
|
|
258
372
|
# the parent expression).
|
|
259
373
|
#
|
|
374
|
+
# Expression implementations are free to override this method.
|
|
375
|
+
# The common behaviour is in #do_reply_to_parent.
|
|
376
|
+
#
|
|
260
377
|
def reply_to_parent(workitem, delete=true)
|
|
261
378
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if h.tagname
|
|
379
|
+
do_reply_to_parent(workitem, delete)
|
|
380
|
+
end
|
|
265
381
|
|
|
266
|
-
|
|
382
|
+
# The essence of the reply_to_parent job...
|
|
383
|
+
#
|
|
384
|
+
def do_reply_to_parent(workitem, delete=true)
|
|
267
385
|
|
|
268
|
-
|
|
386
|
+
# propagate the cancel "flavour" back, so that one can know
|
|
387
|
+
# why a branch got cancelled.
|
|
269
388
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
389
|
+
flavour = if @msg.nil?
|
|
390
|
+
nil
|
|
391
|
+
elsif @msg['action'] == 'cancel'
|
|
392
|
+
@msg['flavour'] || 'cancel'
|
|
393
|
+
elsif h.state.nil?
|
|
394
|
+
nil
|
|
395
|
+
else
|
|
396
|
+
@msg['flavour']
|
|
275
397
|
end
|
|
276
398
|
|
|
277
|
-
|
|
399
|
+
# deal with the timers and the schedules
|
|
278
400
|
|
|
279
|
-
|
|
401
|
+
%w[ timeout_schedule_id job_id ].each do |sid|
|
|
402
|
+
@context.storage.delete_schedule(h[sid]) if h[sid]
|
|
280
403
|
end
|
|
404
|
+
#
|
|
405
|
+
# legacy schedule ids, to be removed for ruote 2.4.0
|
|
406
|
+
|
|
407
|
+
@context.storage.delete_schedule(h.schedule_id) if h.schedule_id
|
|
408
|
+
#
|
|
409
|
+
# time-driven exps like cron, wait and once now all use h.schedule_id
|
|
410
|
+
|
|
411
|
+
h.timers.each do |schedule_id, action|
|
|
412
|
+
@context.storage.delete_schedule(schedule_id)
|
|
413
|
+
end if h.timers
|
|
414
|
+
|
|
415
|
+
# cancel flanking expressions if any
|
|
416
|
+
|
|
417
|
+
cancel_flanks(h.state == 'dying' ? 'kill' : nil)
|
|
281
418
|
|
|
282
|
-
|
|
419
|
+
# trigger or vanilla reply
|
|
420
|
+
|
|
421
|
+
if h.state == 'failing' # on_error is implicit (#do_fail got called)
|
|
283
422
|
|
|
284
423
|
trigger('on_error', workitem)
|
|
285
424
|
|
|
286
|
-
elsif h.state == 'cancelling'
|
|
425
|
+
elsif h.state == 'cancelling' && h.on_cancel
|
|
287
426
|
|
|
288
427
|
trigger('on_cancel', workitem)
|
|
289
428
|
|
|
290
|
-
elsif h.state == 'cancelling'
|
|
429
|
+
elsif h.state == 'cancelling' && h.on_re_apply
|
|
291
430
|
|
|
292
431
|
trigger('on_re_apply', workitem)
|
|
293
432
|
|
|
294
|
-
elsif h.state == 'timing_out'
|
|
433
|
+
elsif h.state == 'timing_out' && h.on_timeout
|
|
295
434
|
|
|
296
435
|
trigger('on_timeout', workitem)
|
|
297
436
|
|
|
298
|
-
elsif h.
|
|
437
|
+
elsif h.state == nil && h.on_reply
|
|
438
|
+
|
|
439
|
+
trigger('on_reply', workitem)
|
|
299
440
|
|
|
441
|
+
elsif (h.lost || h.flanking) && h.state.nil?
|
|
442
|
+
#
|
|
300
443
|
# do not reply, sit here (and wait for cancellation probably)
|
|
301
444
|
|
|
445
|
+
do_persist
|
|
446
|
+
|
|
447
|
+
elsif h.trigger && workitem['fields']["__#{h.trigger}__"]
|
|
448
|
+
#
|
|
449
|
+
# the "second take"
|
|
450
|
+
|
|
451
|
+
trigger(h.trigger, workitem)
|
|
452
|
+
|
|
302
453
|
else # vanilla reply
|
|
303
454
|
|
|
455
|
+
filter(workitem) if h.state.nil?
|
|
456
|
+
|
|
457
|
+
f = h.state.nil? && attribute(:vars_to_f)
|
|
458
|
+
Ruote.set(workitem['fields'], f, h.variables) if f
|
|
459
|
+
|
|
460
|
+
workitem['sub_wf_name'] = @h.applied_workitem['sub_wf_name']
|
|
461
|
+
workitem['sub_wf_revision'] = @h.applied_workitem['sub_wf_revision']
|
|
462
|
+
|
|
463
|
+
leave_tag(workitem) if h.tagname
|
|
464
|
+
|
|
304
465
|
(do_unpersist || return) if delete
|
|
305
466
|
# remove expression from storage
|
|
306
467
|
|
|
@@ -310,14 +471,30 @@ module Ruote::Exp
|
|
|
310
471
|
'reply',
|
|
311
472
|
'fei' => h.parent_id,
|
|
312
473
|
'workitem' => workitem.merge!('fei' => h.fei),
|
|
313
|
-
'updated_tree' => h.updated_tree
|
|
474
|
+
'updated_tree' => h.updated_tree, # nil most of the time
|
|
475
|
+
'flavour' => flavour)
|
|
476
|
+
|
|
314
477
|
else
|
|
315
478
|
|
|
316
479
|
@context.storage.put_msg(
|
|
317
480
|
h.forgotten ? 'ceased' : 'terminated',
|
|
318
481
|
'wfid' => h.fei['wfid'],
|
|
319
482
|
'fei' => h.fei,
|
|
320
|
-
'workitem' => workitem
|
|
483
|
+
'workitem' => workitem,
|
|
484
|
+
'variables' => h.variables,
|
|
485
|
+
'flavour' => flavour)
|
|
486
|
+
|
|
487
|
+
if h.state.nil? && h.on_terminate == 'regenerate' && ! h.forgotten
|
|
488
|
+
|
|
489
|
+
@context.storage.put_msg(
|
|
490
|
+
'regenerate',
|
|
491
|
+
'wfid' => h.fei['wfid'],
|
|
492
|
+
'tree' => h.original_tree,
|
|
493
|
+
'workitem' => workitem,
|
|
494
|
+
'variables' => h.variables,
|
|
495
|
+
'flavour' => flavour)
|
|
496
|
+
#'stash' =>
|
|
497
|
+
end
|
|
321
498
|
end
|
|
322
499
|
end
|
|
323
500
|
end
|
|
@@ -326,22 +503,37 @@ module Ruote::Exp
|
|
|
326
503
|
#
|
|
327
504
|
def do_reply(msg)
|
|
328
505
|
|
|
329
|
-
@msg = Ruote.fulldup(msg)
|
|
330
|
-
# keeping the message, for 'retry' in collision cases
|
|
331
|
-
|
|
332
506
|
workitem = msg['workitem']
|
|
333
507
|
fei = workitem['fei']
|
|
334
508
|
|
|
509
|
+
removed = h.children.delete(fei)
|
|
510
|
+
# accept without any check ?
|
|
511
|
+
|
|
512
|
+
if msg['flanking']
|
|
513
|
+
|
|
514
|
+
(h.flanks ||= []) << fei
|
|
515
|
+
|
|
516
|
+
if (not removed) # then it's a timer
|
|
517
|
+
|
|
518
|
+
do_persist
|
|
519
|
+
return
|
|
520
|
+
end
|
|
521
|
+
end
|
|
522
|
+
|
|
335
523
|
if ut = msg['updated_tree']
|
|
524
|
+
|
|
336
525
|
ct = tree.dup
|
|
337
526
|
ct.last[Ruote::FlowExpressionId.child_id(fei)] = ut
|
|
338
527
|
update_tree(ct)
|
|
339
528
|
end
|
|
340
529
|
|
|
341
|
-
h.
|
|
342
|
-
# accept without any check ?
|
|
530
|
+
if h.state == 'paused'
|
|
343
531
|
|
|
344
|
-
|
|
532
|
+
(h['paused_replies'] ||= []) << msg
|
|
533
|
+
|
|
534
|
+
do_persist
|
|
535
|
+
|
|
536
|
+
elsif h.state != nil # failing or timing out ...
|
|
345
537
|
|
|
346
538
|
if h.children.size < 1
|
|
347
539
|
reply_to_parent(workitem)
|
|
@@ -371,8 +563,6 @@ module Ruote::Exp
|
|
|
371
563
|
#
|
|
372
564
|
def do_cancel(msg)
|
|
373
565
|
|
|
374
|
-
@msg = Ruote.fulldup(msg)
|
|
375
|
-
|
|
376
566
|
flavour = msg['flavour']
|
|
377
567
|
|
|
378
568
|
return if h.state == 'cancelling' && flavour != 'kill'
|
|
@@ -381,42 +571,53 @@ module Ruote::Exp
|
|
|
381
571
|
return if h.state == 'failed' && flavour == 'timeout'
|
|
382
572
|
# do not timeout expressions that are "in error" (failed)
|
|
383
573
|
|
|
384
|
-
@msg = Ruote.fulldup(msg)
|
|
385
|
-
|
|
386
574
|
h.state = case flavour
|
|
387
575
|
when 'kill' then 'dying'
|
|
388
576
|
when 'timeout' then 'timing_out'
|
|
389
577
|
else 'cancelling'
|
|
390
578
|
end
|
|
391
579
|
|
|
392
|
-
h.
|
|
393
|
-
|
|
394
|
-
|
|
580
|
+
if h.state == 'timing_out'
|
|
581
|
+
|
|
582
|
+
h.applied_workitem['fields']['__timed_out__'] = [
|
|
583
|
+
h.fei, Ruote.now_to_utc_s, tree.first, compile_atts
|
|
584
|
+
]
|
|
395
585
|
|
|
396
|
-
|
|
586
|
+
elsif h.state == 'cancelling'
|
|
397
587
|
|
|
398
588
|
if t = msg['on_cancel']
|
|
399
589
|
|
|
400
590
|
h.on_cancel = t
|
|
401
591
|
|
|
402
|
-
elsif
|
|
592
|
+
elsif ra_opts = msg['re_apply']
|
|
403
593
|
|
|
404
|
-
|
|
594
|
+
ra_opts = {} if ra_opts == true
|
|
595
|
+
ra_opts['tree'] ||= tree
|
|
405
596
|
|
|
406
|
-
h.on_re_apply =
|
|
407
|
-
|
|
408
|
-
if fs = hra['fields']
|
|
409
|
-
h.applied_workitem['fields'] = fs
|
|
410
|
-
end
|
|
411
|
-
if mfs = hra['merge_in_fields']
|
|
412
|
-
h.applied_workitem['fields'].merge!(mfs)
|
|
413
|
-
end
|
|
597
|
+
h.on_re_apply = ra_opts
|
|
414
598
|
end
|
|
415
599
|
end
|
|
416
600
|
|
|
417
601
|
cancel(flavour)
|
|
418
602
|
end
|
|
419
603
|
|
|
604
|
+
# Emits a cancel message for each flanking expression (if any).
|
|
605
|
+
#
|
|
606
|
+
def cancel_flanks(flavour)
|
|
607
|
+
|
|
608
|
+
return unless h.flanks
|
|
609
|
+
|
|
610
|
+
h.flanks.each do |flank_fei|
|
|
611
|
+
|
|
612
|
+
@context.storage.put_msg(
|
|
613
|
+
'cancel',
|
|
614
|
+
'fei' => flank_fei,
|
|
615
|
+
'parent_id' => h.fei,
|
|
616
|
+
# indicating that this is a "cancel child", well...
|
|
617
|
+
'flavour' => flavour)
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
420
621
|
# This default implementation cancels all the [registered] children
|
|
421
622
|
# of this expression.
|
|
422
623
|
#
|
|
@@ -434,56 +635,84 @@ module Ruote::Exp
|
|
|
434
635
|
# if the do_persist returns false, it means it failed, implying this
|
|
435
636
|
# expression is stale, let's return, thus discarding this cancel message
|
|
436
637
|
|
|
437
|
-
children.each do |
|
|
638
|
+
children.each do |child_fei|
|
|
438
639
|
#
|
|
439
640
|
# let's send a cancel message to each of the children
|
|
440
641
|
#
|
|
441
642
|
# maybe some of them are gone or have not yet been applied, anyway,
|
|
442
|
-
# the
|
|
643
|
+
# the messages are sent
|
|
443
644
|
|
|
444
645
|
@context.storage.put_msg(
|
|
445
646
|
'cancel',
|
|
446
|
-
'fei' =>
|
|
647
|
+
'fei' => child_fei,
|
|
447
648
|
'parent_id' => h.fei, # indicating that this is a "cancel child"
|
|
448
649
|
'flavour' => flavour)
|
|
449
650
|
end
|
|
450
|
-
|
|
451
|
-
#if ! children.find { |i| Ruote::Exp::FlowExpression.fetch(@context, i) }
|
|
452
|
-
# #
|
|
453
|
-
# # since none of the children could be found in the storage right now,
|
|
454
|
-
# # it could mean that all children are already done or it could mean
|
|
455
|
-
# # that they are not yet applied...
|
|
456
|
-
# #
|
|
457
|
-
# # just to be sure let's send a new cancel message to this expression
|
|
458
|
-
# #
|
|
459
|
-
# # it's very important, since if there is no child to cancel the parent
|
|
460
|
-
# # the flow might get stuck here
|
|
461
|
-
# @context.storage.put_msg(
|
|
462
|
-
# 'cancel',
|
|
463
|
-
# 'fei' => h.fei,
|
|
464
|
-
# 'flavour' => flavour)
|
|
465
|
-
#end
|
|
466
651
|
end
|
|
467
652
|
|
|
468
653
|
# Called when handling an on_error, will place itself in a 'failing' state
|
|
469
654
|
# and cancel the children (when the reply from the children comes back,
|
|
470
|
-
# the
|
|
655
|
+
# the on_error will get triggered).
|
|
471
656
|
#
|
|
472
657
|
def do_fail(msg)
|
|
473
658
|
|
|
474
|
-
@msg = Ruote.fulldup(msg)
|
|
475
|
-
|
|
476
659
|
@h['state'] = 'failing'
|
|
477
660
|
@h['applied_workitem'] = msg['workitem']
|
|
478
661
|
|
|
479
662
|
if h.children.size < 1
|
|
663
|
+
|
|
480
664
|
reply_to_parent(@h['applied_workitem'])
|
|
665
|
+
|
|
481
666
|
else
|
|
667
|
+
|
|
668
|
+
flavour = msg['immediate'] ? 'kill' : nil
|
|
669
|
+
|
|
482
670
|
persist_or_raise
|
|
483
|
-
|
|
671
|
+
|
|
672
|
+
h.children.each do |i|
|
|
673
|
+
@context.storage.put_msg('cancel', 'fei' => i, 'flavour' => flavour)
|
|
674
|
+
end
|
|
484
675
|
end
|
|
485
676
|
end
|
|
486
677
|
|
|
678
|
+
# Expression received a "pause" message. Will put the expression in the
|
|
679
|
+
# "paused" state and then pass the message to the children.
|
|
680
|
+
#
|
|
681
|
+
# If the expression is in a non-nil state (failed, timed_out, ...), the
|
|
682
|
+
# message will be ignored.
|
|
683
|
+
#
|
|
684
|
+
def do_pause(msg)
|
|
685
|
+
|
|
686
|
+
return if h.state != nil
|
|
687
|
+
|
|
688
|
+
h['state'] = 'paused'
|
|
689
|
+
|
|
690
|
+
do_persist || return
|
|
691
|
+
|
|
692
|
+
h.children.each { |i|
|
|
693
|
+
@context.storage.put_msg('pause', 'fei' => i)
|
|
694
|
+
} unless msg['breakpoint']
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
# Will "unpause" the expression (if it was paused), and trigger any
|
|
698
|
+
# 'paused_replies' (replies that came while the expression was paused).
|
|
699
|
+
#
|
|
700
|
+
def do_resume(msg)
|
|
701
|
+
|
|
702
|
+
return if h.state != 'paused'
|
|
703
|
+
|
|
704
|
+
h['state'] = nil
|
|
705
|
+
replies = h.delete('paused_replies') || []
|
|
706
|
+
|
|
707
|
+
do_persist || return
|
|
708
|
+
|
|
709
|
+
h.children.each { |i| @context.storage.put_msg('resume', 'fei' => i) }
|
|
710
|
+
# resume children
|
|
711
|
+
|
|
712
|
+
replies.each { |m| @context.storage.put_msg(m.delete('action'), m) }
|
|
713
|
+
# trigger replies
|
|
714
|
+
end
|
|
715
|
+
|
|
487
716
|
#--
|
|
488
717
|
# misc
|
|
489
718
|
#++
|
|
@@ -524,77 +753,14 @@ module Ruote::Exp
|
|
|
524
753
|
#
|
|
525
754
|
def ancestor?(fei)
|
|
526
755
|
|
|
756
|
+
fei = fei.to_h if fei.respond_to?(:to_h)
|
|
757
|
+
|
|
527
758
|
return false unless h.parent_id
|
|
528
759
|
return true if h.parent_id == fei
|
|
529
760
|
|
|
530
761
|
parent.ancestor?(fei)
|
|
531
762
|
end
|
|
532
763
|
|
|
533
|
-
# Looks up "on_error" attribute
|
|
534
|
-
#
|
|
535
|
-
def lookup_on_error
|
|
536
|
-
|
|
537
|
-
if h.on_error
|
|
538
|
-
|
|
539
|
-
self
|
|
540
|
-
|
|
541
|
-
elsif h.parent_id
|
|
542
|
-
|
|
543
|
-
par = parent
|
|
544
|
-
# :( get_parent would probably be a better name for #parent
|
|
545
|
-
|
|
546
|
-
#if par.nil? && ($DEBUG || ARGV.include?('-d'))
|
|
547
|
-
# puts "~~"
|
|
548
|
-
# puts "parent gone for"
|
|
549
|
-
# puts "fei #{Ruote.sid(h.fei)}"
|
|
550
|
-
# puts "tree #{tree.inspect}"
|
|
551
|
-
# puts "replying to #{Ruote.sid(h.parent_id)}"
|
|
552
|
-
# puts "~~"
|
|
553
|
-
#end
|
|
554
|
-
# is sometimes helpful during debug sessions
|
|
555
|
-
|
|
556
|
-
par ? par.lookup_on_error : nil
|
|
557
|
-
|
|
558
|
-
else
|
|
559
|
-
|
|
560
|
-
nil
|
|
561
|
-
end
|
|
562
|
-
end
|
|
563
|
-
|
|
564
|
-
# Looks up parent with on_error attribute and triggers it
|
|
565
|
-
#
|
|
566
|
-
def handle_on_error(msg, error)
|
|
567
|
-
|
|
568
|
-
return false if h.state == 'failing'
|
|
569
|
-
|
|
570
|
-
oe_parent = lookup_on_error
|
|
571
|
-
|
|
572
|
-
return false unless oe_parent
|
|
573
|
-
# no parent with on_error attribute found
|
|
574
|
-
|
|
575
|
-
handler = oe_parent.on_error.to_s
|
|
576
|
-
|
|
577
|
-
return false if handler == ''
|
|
578
|
-
# empty on_error handler nullifies ancestor's on_error
|
|
579
|
-
|
|
580
|
-
workitem = msg['workitem']
|
|
581
|
-
|
|
582
|
-
workitem['fields']['__error__'] = {
|
|
583
|
-
'fei' => fei,
|
|
584
|
-
'at' => Ruote.now_to_utc_s,
|
|
585
|
-
'class' => error.class.to_s,
|
|
586
|
-
'message' => error.message,
|
|
587
|
-
'trace' => error.backtrace
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
@context.storage.put_msg(
|
|
591
|
-
'fail',
|
|
592
|
-
'fei' => oe_parent.h.fei,
|
|
593
|
-
'workitem' => workitem)
|
|
594
|
-
|
|
595
|
-
true # yes, error is being handled.
|
|
596
|
-
end
|
|
597
|
-
|
|
598
764
|
#--
|
|
599
765
|
# TREE
|
|
600
766
|
#++
|
|
@@ -603,6 +769,7 @@ module Ruote::Exp
|
|
|
603
769
|
# if it got updated.
|
|
604
770
|
#
|
|
605
771
|
def tree
|
|
772
|
+
|
|
606
773
|
h.updated_tree || h.original_tree
|
|
607
774
|
end
|
|
608
775
|
|
|
@@ -623,6 +790,7 @@ module Ruote::Exp
|
|
|
623
790
|
# seq.do_persist
|
|
624
791
|
#
|
|
625
792
|
def update_tree(t=nil)
|
|
793
|
+
|
|
626
794
|
h.updated_tree = t || Ruote.fulldup(h.original_tree)
|
|
627
795
|
end
|
|
628
796
|
|
|
@@ -728,102 +896,80 @@ module Ruote::Exp
|
|
|
728
896
|
#
|
|
729
897
|
def consider_tag
|
|
730
898
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
set_variable(h.tagname, h.fei)
|
|
899
|
+
tag = attribute(:tag)
|
|
734
900
|
|
|
735
|
-
|
|
901
|
+
return unless tag
|
|
736
902
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
'tag' => h.tagname,
|
|
740
|
-
'fei' => h.fei,
|
|
741
|
-
'workitem' => h.applied_workitem)
|
|
742
|
-
end
|
|
743
|
-
end
|
|
744
|
-
|
|
745
|
-
# Called by do_apply. Overriden in ParticipantExpression and RefExpression.
|
|
746
|
-
#
|
|
747
|
-
def consider_timeout
|
|
903
|
+
h.tagname = tag
|
|
904
|
+
h.full_tagname = applied_workitem.tags.join('/')
|
|
748
905
|
|
|
749
|
-
|
|
750
|
-
|
|
906
|
+
return if h.trigger
|
|
907
|
+
#
|
|
908
|
+
# do not consider tags when the tree is applied for an
|
|
909
|
+
# on_x trigger
|
|
751
910
|
|
|
752
|
-
|
|
753
|
-
# (ParticipantExpression).
|
|
754
|
-
#
|
|
755
|
-
def do_schedule_timeout(timeout)
|
|
911
|
+
h.full_tagname = (applied_workitem.tags + [ tag ]).join('/')
|
|
756
912
|
|
|
757
|
-
|
|
913
|
+
set_variable(h.tagname, h.fei)
|
|
914
|
+
set_variable('/' + h.full_tagname, h.fei)
|
|
758
915
|
|
|
759
|
-
|
|
916
|
+
applied_workitem.send(:add_tag, h.tagname)
|
|
760
917
|
|
|
761
|
-
|
|
762
|
-
'
|
|
763
|
-
h.
|
|
764
|
-
|
|
765
|
-
'action' => 'cancel',
|
|
918
|
+
@context.storage.put_msg(
|
|
919
|
+
'entered_tag',
|
|
920
|
+
'tag' => h.tagname,
|
|
921
|
+
'full_tag' => h.full_tagname,
|
|
766
922
|
'fei' => h.fei,
|
|
767
|
-
'
|
|
923
|
+
'workitem' => h.applied_workitem)
|
|
768
924
|
end
|
|
769
925
|
|
|
770
|
-
#
|
|
926
|
+
# Called when the expression is about to reply to its parent and wants
|
|
927
|
+
# to get rid of its tags.
|
|
771
928
|
#
|
|
772
|
-
def
|
|
773
|
-
|
|
774
|
-
# at first, nuke self
|
|
775
|
-
|
|
776
|
-
r = try_unpersist
|
|
929
|
+
def leave_tag(workitem)
|
|
777
930
|
|
|
778
|
-
|
|
779
|
-
"failed to remove exp to supplant "+
|
|
780
|
-
"#{Ruote.to_storage_id(h.fei)} #{tree.first}"
|
|
781
|
-
) if r.respond_to?(:keys)
|
|
931
|
+
unset_variable(h.tagname)
|
|
782
932
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
if t = opts['trigger']
|
|
786
|
-
tree[1]['_triggered'] = t.to_s
|
|
787
|
-
end
|
|
933
|
+
Ruote::Workitem.new(workitem).send(:remove_tag, h.tagname)
|
|
788
934
|
|
|
789
935
|
@context.storage.put_msg(
|
|
790
|
-
'
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
'variables' => h.variables
|
|
796
|
-
}.merge!(opts))
|
|
797
|
-
end
|
|
798
|
-
|
|
799
|
-
# 'on_{error|timeout|cancel|re_apply}' triggering
|
|
800
|
-
#
|
|
801
|
-
def trigger(on, workitem)
|
|
802
|
-
|
|
803
|
-
hon = h[on]
|
|
804
|
-
|
|
805
|
-
t = hon.is_a?(String) ? [ hon, {}, [] ] : hon
|
|
936
|
+
'left_tag',
|
|
937
|
+
'tag' => h.tagname,
|
|
938
|
+
'full_tag' => h.full_tagname,
|
|
939
|
+
'fei' => h.fei,
|
|
940
|
+
'workitem' => workitem)
|
|
806
941
|
|
|
807
|
-
|
|
942
|
+
return unless h.full_tagname # for backward compatibility
|
|
808
943
|
|
|
809
|
-
|
|
944
|
+
r = root
|
|
810
945
|
|
|
811
|
-
|
|
946
|
+
return unless r && r.variables # might happen
|
|
812
947
|
|
|
813
|
-
|
|
948
|
+
r.variables.delete(h.full_tagname)
|
|
814
949
|
|
|
815
|
-
|
|
816
|
-
reply_to_parent(workitem)
|
|
950
|
+
state = case (h.trigger || h.state)
|
|
817
951
|
|
|
818
|
-
|
|
819
|
-
|
|
952
|
+
when 'on_cancel' then 'cancelled'
|
|
953
|
+
when 'on_error' then 'failed'
|
|
954
|
+
when 'on_timeout' then 'timed out'
|
|
955
|
+
when 'on_re_apply' then nil
|
|
820
956
|
|
|
821
|
-
|
|
957
|
+
when 'cancelling' then 'cancelled'
|
|
958
|
+
when 'dying' then 'killed'
|
|
822
959
|
|
|
823
|
-
|
|
960
|
+
else nil
|
|
824
961
|
end
|
|
825
962
|
|
|
826
|
-
|
|
963
|
+
(r.variables['__past_tags__'] ||= []) << [
|
|
964
|
+
h.full_tagname,
|
|
965
|
+
fei.sid,
|
|
966
|
+
state,
|
|
967
|
+
Ruote.now_to_utc_s,
|
|
968
|
+
Ruote.fulldup(h.variables)
|
|
969
|
+
# not fullduping here triggers a segfault at some point with YAJL
|
|
970
|
+
]
|
|
971
|
+
|
|
972
|
+
r.do_persist unless r.fei == self.fei
|
|
827
973
|
end
|
|
828
974
|
end
|
|
829
975
|
end
|