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
data/lib/ruote/exp/iterator.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
|
|
@@ -42,7 +42,7 @@ module Ruote::Exp
|
|
|
42
42
|
|
|
43
43
|
if count = attribute(:times) || attribute(:branches)
|
|
44
44
|
|
|
45
|
-
list = ((
|
|
45
|
+
list = ((0...count.to_i).to_a rescue nil)
|
|
46
46
|
|
|
47
47
|
if list
|
|
48
48
|
h.times_iterator = true
|
data/lib/ruote/exp/merge.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
|
|
@@ -30,43 +30,104 @@ module Ruote::Exp
|
|
|
30
30
|
#
|
|
31
31
|
module MergeMixin
|
|
32
32
|
|
|
33
|
+
# Given a list of workitems and a merge_type, will merge according to
|
|
34
|
+
# the merge type.
|
|
33
35
|
#
|
|
36
|
+
# The return value is the merged workitem.
|
|
37
|
+
#
|
|
38
|
+
def merge_workitems(workitems, merge_type)
|
|
39
|
+
|
|
40
|
+
workitems.inject(nil) do |t, wi|
|
|
41
|
+
merge_workitem(workitems.index(wi), t, wi, merge_type)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
34
45
|
# Merge workitem 'source' into workitem 'target'.
|
|
35
46
|
#
|
|
36
47
|
# If type is 'override', the source will prevail and be returned.
|
|
37
48
|
#
|
|
38
|
-
# If type is 'mix', the source fields will be
|
|
49
|
+
# If type is 'mix', the source fields will be merged into the target fields.
|
|
39
50
|
#
|
|
40
51
|
# If type is 'isolate', the source fields will be placed in a separte field
|
|
41
52
|
# in the target workitem. The name of this field is the child_id of the
|
|
42
53
|
# source workitem (a string from '0' to '99999' and beyond)
|
|
43
54
|
#
|
|
44
|
-
|
|
55
|
+
# The 'concat' type merges hashes and concats arrays. The 'union' type
|
|
56
|
+
# behaves much like 'concat', but it makes sure to remove duplicates.
|
|
57
|
+
#
|
|
58
|
+
# Warning: 'union' will remove duplicates that were present _before_ the
|
|
59
|
+
# merge.
|
|
60
|
+
#
|
|
61
|
+
def merge_workitem(index, target, source, merge_type)
|
|
45
62
|
|
|
46
|
-
return source if
|
|
63
|
+
return source if merge_type == 'override'
|
|
47
64
|
|
|
48
65
|
if target == nil
|
|
49
|
-
|
|
66
|
+
|
|
67
|
+
case merge_type
|
|
68
|
+
|
|
69
|
+
#when 'mix'
|
|
70
|
+
# do nothing
|
|
71
|
+
|
|
72
|
+
when 'stack'
|
|
73
|
+
source['fields'] = { 'stack' => [ source['fields'] ] }
|
|
74
|
+
|
|
50
75
|
when 'isolate'
|
|
51
76
|
source['fields'] = { index.to_s => source['fields'] }
|
|
77
|
+
|
|
78
|
+
#when 'union', 'concat'
|
|
79
|
+
# do nothing
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
source
|
|
83
|
+
|
|
84
|
+
else
|
|
85
|
+
|
|
86
|
+
case merge_type
|
|
87
|
+
|
|
88
|
+
when 'mix'
|
|
89
|
+
|
|
90
|
+
target['fields'].merge!(source['fields'])
|
|
91
|
+
|
|
52
92
|
when 'stack'
|
|
53
|
-
|
|
93
|
+
|
|
94
|
+
target['fields']['stack'] << source['fields']
|
|
95
|
+
target['fields']['stack_attributes'] = compile_atts
|
|
96
|
+
|
|
97
|
+
when 'isolate'
|
|
98
|
+
|
|
99
|
+
target['fields'][index.to_s] = source['fields']
|
|
100
|
+
|
|
101
|
+
when 'union', 'concat', 'deep'
|
|
102
|
+
|
|
103
|
+
source['fields'].each do |k, sv|
|
|
104
|
+
|
|
105
|
+
tv = target['fields'][k]
|
|
106
|
+
|
|
107
|
+
if sv.is_a?(Array) and tv.is_a?(Array)
|
|
108
|
+
tv.concat(sv)
|
|
109
|
+
tv.uniq! if merge_type == 'union'
|
|
110
|
+
elsif sv.is_a?(Hash) and tv.is_a?(Hash)
|
|
111
|
+
merge_type == 'deep' ? deep_merge!(tv, sv) : tv.merge!(sv)
|
|
112
|
+
else
|
|
113
|
+
target['fields'][k] = sv
|
|
114
|
+
end
|
|
115
|
+
end
|
|
54
116
|
end
|
|
117
|
+
|
|
118
|
+
target
|
|
55
119
|
end
|
|
120
|
+
end
|
|
56
121
|
|
|
57
|
-
|
|
122
|
+
protected
|
|
58
123
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
when 'stack'
|
|
63
|
-
target['fields']['stack'] << source['fields']
|
|
64
|
-
target['fields']['stack_attributes'] = expand_atts
|
|
65
|
-
else # 'isolate'
|
|
66
|
-
target['fields'][index.to_s] = source['fields']
|
|
67
|
-
end
|
|
124
|
+
# Inspired by the one found in ActiveSupport, though not strictly equivalent.
|
|
125
|
+
#
|
|
126
|
+
def deep_merge!(target, source)
|
|
68
127
|
|
|
69
|
-
target
|
|
128
|
+
target.merge!(source) do |k, o, n|
|
|
129
|
+
o.is_a?(Hash) && n.is_a?(Hash) ? deep_merge!(o, n) : n
|
|
130
|
+
end
|
|
70
131
|
end
|
|
71
132
|
end
|
|
72
133
|
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
|
|
@@ -60,7 +60,7 @@ module Ruote::Exp
|
|
|
60
60
|
elsif escape
|
|
61
61
|
v
|
|
62
62
|
else
|
|
63
|
-
|
|
63
|
+
dsub(v, workitem)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
v = v.to_s if v and string
|
|
@@ -72,19 +72,11 @@ module Ruote::Exp
|
|
|
72
72
|
# in the array list 'values'. If not, the default value is returned.
|
|
73
73
|
# By default, the default value is the first element of 'values'.
|
|
74
74
|
#
|
|
75
|
-
def att(
|
|
75
|
+
def att(keys, values, opts={})
|
|
76
76
|
|
|
77
77
|
default = opts[:default] || values.first
|
|
78
78
|
|
|
79
|
-
val = attribute(key)
|
|
80
|
-
val = val.to_s if val
|
|
81
|
-
|
|
82
|
-
#raise(
|
|
83
|
-
# ArgumentError.new("attribute '#{key}' missing in #{tree}")
|
|
84
|
-
#) if opts[:mandatory] && val == nil
|
|
85
|
-
#raise(
|
|
86
|
-
# ArgumentError.new("attribute '#{key}' has invalid value in #{tree}")
|
|
87
|
-
#) if opts[:enforce] && (not values.include?(val))
|
|
79
|
+
val = Array(keys).collect { |key| attribute(key) }.compact.first.to_s
|
|
88
80
|
|
|
89
81
|
values.include?(val) ? val : default
|
|
90
82
|
end
|
|
@@ -115,24 +107,8 @@ module Ruote::Exp
|
|
|
115
107
|
#
|
|
116
108
|
def compile_atts(opts={})
|
|
117
109
|
|
|
118
|
-
attributes.keys.
|
|
119
|
-
r[k] = attribute(k, h.applied_workitem, opts)
|
|
120
|
-
r
|
|
121
|
-
}
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# Like compile_atts, but the keys are expanded as well.
|
|
125
|
-
#
|
|
126
|
-
# Useful for things like
|
|
127
|
-
#
|
|
128
|
-
# set "f:${v:field_name}" => "${v:that_variable}"
|
|
129
|
-
#
|
|
130
|
-
def expand_atts(opts={})
|
|
131
|
-
|
|
132
|
-
attributes.keys.inject({}) { |r, k|
|
|
133
|
-
kk = @context.dollar_sub.s(k, self, h.applied_workitem)
|
|
134
|
-
r[kk] = attribute(k, h.applied_workitem, opts)
|
|
135
|
-
r
|
|
110
|
+
attributes.keys.each_with_object({}) { |k, r|
|
|
111
|
+
r[dsub(k)] = attribute(k, h.applied_workitem, opts)
|
|
136
112
|
}
|
|
137
113
|
end
|
|
138
114
|
|
|
@@ -154,15 +130,51 @@ module Ruote::Exp
|
|
|
154
130
|
|
|
155
131
|
text = attributes.keys.find { |k| attributes[k] == nil }
|
|
156
132
|
|
|
157
|
-
|
|
133
|
+
dsub(text.to_s, workitem)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Equivalent to #attribute_text, but will return nil if there
|
|
137
|
+
# is no attribute whose values is nil.
|
|
138
|
+
#
|
|
139
|
+
def att_text(workitem=h.applied_workitem)
|
|
140
|
+
|
|
141
|
+
text = attributes.keys.find { |k| attributes[k] == nil }
|
|
142
|
+
|
|
143
|
+
text ? dsub(text.to_s, workitem) : nil
|
|
158
144
|
end
|
|
159
145
|
|
|
160
146
|
protected
|
|
161
147
|
|
|
148
|
+
# dollar substitution for expressions.
|
|
149
|
+
#
|
|
150
|
+
def dsub(o, wi=h.applied_workitem)
|
|
151
|
+
|
|
152
|
+
case o
|
|
153
|
+
when String; @context.dollar_sub.s(o, self, wi)
|
|
154
|
+
when Array; o.collect { |e| dsub(e, wi) }
|
|
155
|
+
when Hash; o.remap { |(k, v), h| h[dsub(k, wi)] = dsub(v, wi) }
|
|
156
|
+
else o
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# 'tos' meaning 'many "to"'
|
|
161
|
+
#
|
|
162
162
|
def determine_tos
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
to_v = attribute(:to_v) || attribute(:to_var) || attribute(:to_variable)
|
|
165
|
+
to_f = attribute(:to_f) || attribute(:to_fld) || attribute(:to_field)
|
|
166
|
+
|
|
167
|
+
if to = attribute(:to)
|
|
168
|
+
pre, key = to.split(':')
|
|
169
|
+
pre, key = [ 'f', pre ] if key == nil
|
|
170
|
+
if pre.match(/^f/)
|
|
171
|
+
to_f = key
|
|
172
|
+
else
|
|
173
|
+
to_v = key
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
[ to_v, to_f ]
|
|
166
178
|
end
|
|
167
179
|
|
|
168
180
|
# Val and Value (Sense and Sensibility ?)
|
|
@@ -188,9 +200,7 @@ module Ruote::Exp
|
|
|
188
200
|
elsif k = has_att(*flds)
|
|
189
201
|
|
|
190
202
|
k = attribute(k, h.applied_workitem, att_options)
|
|
191
|
-
h.applied_workitem['fields']
|
|
192
|
-
|
|
193
|
-
# TODO : what about leveraging workitem#lookup ?
|
|
203
|
+
Ruote.lookup(h.applied_workitem['fields'], k)
|
|
194
204
|
|
|
195
205
|
else
|
|
196
206
|
|
data/lib/ruote/exp/ro_filters.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
|
|
@@ -76,7 +76,13 @@ module Ruote::Exp
|
|
|
76
76
|
|
|
77
77
|
workitem['fields'] =
|
|
78
78
|
Ruote.filter(
|
|
79
|
-
filter,
|
|
79
|
+
filter,
|
|
80
|
+
workitem['fields'],
|
|
81
|
+
:double_tilde =>
|
|
82
|
+
h.fields_pre_filter || h.applied_workitem['fields'])
|
|
83
|
+
|
|
84
|
+
workitem['fields'].delete('params')
|
|
85
|
+
# take and discard tend to copy it over, so let's remove it
|
|
80
86
|
end
|
|
81
87
|
end
|
|
82
88
|
|
|
@@ -85,21 +91,41 @@ module Ruote::Exp
|
|
|
85
91
|
#
|
|
86
92
|
# Returns nil, if there is no filter. Raises an ArgumentError if the
|
|
87
93
|
# filter is not usable. Returns the instantiated participant if the
|
|
88
|
-
# filter points to
|
|
94
|
+
# filter points to a participant filter.
|
|
89
95
|
#
|
|
90
96
|
def lookup_filter(workitem)
|
|
91
97
|
|
|
92
98
|
f = attribute(:filter)
|
|
93
99
|
|
|
100
|
+
if f.nil? and workitem
|
|
101
|
+
|
|
102
|
+
reply = if t = attribute(:take)
|
|
103
|
+
Array(t).collect { |tt| { 'field' => tt, 'take' => true } }
|
|
104
|
+
elsif d = attribute(:discard)
|
|
105
|
+
if d == true
|
|
106
|
+
[ { 'field' => /.+/, 'discard' => 'all' } ]
|
|
107
|
+
else
|
|
108
|
+
Array(d).collect { |dd| { 'field' => dd, 'discard' => true } }
|
|
109
|
+
end
|
|
110
|
+
else
|
|
111
|
+
nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
f = { 'reply' => reply } if reply
|
|
115
|
+
end
|
|
116
|
+
|
|
94
117
|
return nil unless f
|
|
118
|
+
# no filter
|
|
95
119
|
|
|
96
|
-
|
|
120
|
+
if f.is_a?(Hash)
|
|
121
|
+
f['in'] = [] unless f['in'] or f['apply']
|
|
122
|
+
f['out'] = [] unless f['out'] or f['reply']
|
|
123
|
+
end
|
|
124
|
+
# empty ins and outs for a sucessful narrowing
|
|
97
125
|
|
|
98
|
-
|
|
99
|
-
"found no filter corresponding to '#{f}'"
|
|
100
|
-
) unless f
|
|
126
|
+
3.times { f = narrow_filter(f, workitem) }
|
|
101
127
|
|
|
102
|
-
f
|
|
128
|
+
f or raise ArgumentError.new("found no filter corresponding to '#{f}'")
|
|
103
129
|
end
|
|
104
130
|
|
|
105
131
|
# Called successively to dig for the filter (Array or Participant).
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2005-2012, 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
|
+
module Ruote::Exp
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# 're-opening' the FlowExpression class to add methods and classes about
|
|
30
|
+
# on_error, on_cancel, on_timeout, ...
|
|
31
|
+
#
|
|
32
|
+
class FlowExpression
|
|
33
|
+
|
|
34
|
+
# Given this expression and an error, deflates the error into a hash
|
|
35
|
+
# (serializable).
|
|
36
|
+
#
|
|
37
|
+
def deflate(err)
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
'fei' => h.fei,
|
|
41
|
+
'at' => Ruote.now_to_utc_s,
|
|
42
|
+
'class' => err.class.to_s,
|
|
43
|
+
'message' => err.message,
|
|
44
|
+
'trace' => err.backtrace,
|
|
45
|
+
'details' => err.respond_to?(:ruote_details) ? err.ruote_details : nil,
|
|
46
|
+
'deviations' => err.respond_to?(:deviations) ? err.deviations : nil,
|
|
47
|
+
'tree' => tree
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Returns a dummy expression. Only used by the error_handler service.
|
|
52
|
+
#
|
|
53
|
+
def self.dummy(h)
|
|
54
|
+
|
|
55
|
+
class << h; include Ruote::HashDot; end
|
|
56
|
+
|
|
57
|
+
fe = self.allocate
|
|
58
|
+
fe.instance_variable_set(:@h, h)
|
|
59
|
+
|
|
60
|
+
fe
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Looks up parent with on_error attribute and triggers it
|
|
64
|
+
#
|
|
65
|
+
def handle_on_error(msg, error)
|
|
66
|
+
|
|
67
|
+
return false if h.state == 'failing'
|
|
68
|
+
|
|
69
|
+
err = deflate(error)
|
|
70
|
+
oe_parent = lookup_on_error(err)
|
|
71
|
+
|
|
72
|
+
return false unless oe_parent
|
|
73
|
+
# no parent with on_error attribute found
|
|
74
|
+
|
|
75
|
+
handler = oe_parent.local_on_error(err)
|
|
76
|
+
|
|
77
|
+
return false if handler.to_s == ''
|
|
78
|
+
# empty on_error handler nullifies ancestor's on_error
|
|
79
|
+
|
|
80
|
+
workitem = msg['workitem']
|
|
81
|
+
workitem['fields']['__error__'] = err
|
|
82
|
+
|
|
83
|
+
immediate = if handler.is_a?(String)
|
|
84
|
+
!! handler.match(/^!/)
|
|
85
|
+
elsif handler.is_a?(Array)
|
|
86
|
+
!! handler.first.to_s.match(/^!/)
|
|
87
|
+
else
|
|
88
|
+
false
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# NOTE: why not pass the handler in the msg?
|
|
92
|
+
# no, because of HandlerEntry (not JSON serializable)
|
|
93
|
+
|
|
94
|
+
@context.storage.put_msg(
|
|
95
|
+
'fail',
|
|
96
|
+
'fei' => oe_parent.h.fei,
|
|
97
|
+
'workitem' => workitem,
|
|
98
|
+
'immediate' => immediate)
|
|
99
|
+
|
|
100
|
+
true # yes, error is being handled.
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
protected
|
|
104
|
+
|
|
105
|
+
#
|
|
106
|
+
# Used by on_error when patterns are involved. Gathers much of the
|
|
107
|
+
# pattern logic...
|
|
108
|
+
#
|
|
109
|
+
class HandlerEntry
|
|
110
|
+
|
|
111
|
+
attr_reader :pattern, :action, :child_id
|
|
112
|
+
|
|
113
|
+
def initialize(on_error_entry)
|
|
114
|
+
|
|
115
|
+
if on_error_entry.is_a?(Hash)
|
|
116
|
+
on_error_entry = on_error_entry.to_a.flatten
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
@pattern, @action, @child_id = on_error_entry
|
|
120
|
+
@pat = Ruote.regex_or_s(@pattern) || //
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def split(pat)
|
|
124
|
+
|
|
125
|
+
@action.split(pat)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def match(regex_or_err)
|
|
129
|
+
|
|
130
|
+
if regex_or_err.is_a?(Regexp)
|
|
131
|
+
@action.match(regex_or_err)
|
|
132
|
+
else
|
|
133
|
+
@pat.match(regex_or_err['message']) ||
|
|
134
|
+
@pat.match(regex_or_err['class'])
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def narrow
|
|
139
|
+
|
|
140
|
+
@action.is_a?(Array) ? @action : self
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def update_tree(tree, retries)
|
|
144
|
+
|
|
145
|
+
child = tree[2][@child_id]
|
|
146
|
+
|
|
147
|
+
if @pattern
|
|
148
|
+
if retries.empty?
|
|
149
|
+
child[1].delete(@pattern)
|
|
150
|
+
else
|
|
151
|
+
child[1][@pattern] = retries.join(', ')
|
|
152
|
+
end
|
|
153
|
+
else
|
|
154
|
+
key, _ = child[1].find { |k, v| v.nil? }
|
|
155
|
+
child[1].delete(key)
|
|
156
|
+
child[1][retries.join(', ')] = nil if retries.any?
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Given an error, returns the on_error registered for it, or nil if none.
|
|
162
|
+
#
|
|
163
|
+
def local_on_error(err)
|
|
164
|
+
|
|
165
|
+
if h.on_error.is_a?(String) or Ruote.is_tree?(h.on_error)
|
|
166
|
+
|
|
167
|
+
return h.on_error
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
if h.on_error.is_a?(Array)
|
|
171
|
+
|
|
172
|
+
# all for the 'on_error' expression
|
|
173
|
+
# see test/functional/eft_38_
|
|
174
|
+
|
|
175
|
+
h.on_error.each do |oe|
|
|
176
|
+
|
|
177
|
+
if (he = HandlerEntry.new(oe)).match(err)
|
|
178
|
+
return he.narrow
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
nil
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Looks up "on_error" attribute locally and in the parent expressions,
|
|
187
|
+
# if any.
|
|
188
|
+
#
|
|
189
|
+
def lookup_on_error(err)
|
|
190
|
+
|
|
191
|
+
if local_on_error(err)
|
|
192
|
+
return self
|
|
193
|
+
end
|
|
194
|
+
if par = parent
|
|
195
|
+
return par.lookup_on_error(err)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
nil
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Called by #trigger when it encounters something like
|
|
202
|
+
#
|
|
203
|
+
# :on_error => '5m: retry, pass'
|
|
204
|
+
#
|
|
205
|
+
def schedule_retries(handler, err)
|
|
206
|
+
|
|
207
|
+
retries = handler.split(/\s*,\s*/)
|
|
208
|
+
after, action = retries.shift.split(/:/)
|
|
209
|
+
|
|
210
|
+
# deal with "* 3"
|
|
211
|
+
|
|
212
|
+
if m = action.match(/^ *([^ ]+) *\* *(\d+)$/)
|
|
213
|
+
|
|
214
|
+
count = m[2].to_i - 1
|
|
215
|
+
|
|
216
|
+
if count == 1
|
|
217
|
+
retries.unshift("#{after}: #{m[1]}")
|
|
218
|
+
elsif count > 1
|
|
219
|
+
retries.unshift("#{after}: #{m[1]} * #{count}")
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# rewrite tree to remove current retry
|
|
224
|
+
|
|
225
|
+
t = Ruote.fulldup(tree)
|
|
226
|
+
|
|
227
|
+
if h.on_error.is_a?(Array)
|
|
228
|
+
handler.update_tree(t, retries)
|
|
229
|
+
else
|
|
230
|
+
if retries.empty?
|
|
231
|
+
t[1].delete('on_error')
|
|
232
|
+
else
|
|
233
|
+
t[1]['on_error'] = retries.join(', ')
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
update_tree(t)
|
|
238
|
+
|
|
239
|
+
# schedule current retry
|
|
240
|
+
|
|
241
|
+
after = after.strip
|
|
242
|
+
action = action.strip
|
|
243
|
+
|
|
244
|
+
msg = {
|
|
245
|
+
'action' => 'cancel',
|
|
246
|
+
'fei' => h.fei,
|
|
247
|
+
'flavour' => 'retry',
|
|
248
|
+
're_apply' => true }
|
|
249
|
+
|
|
250
|
+
(h.timers ||= []) <<
|
|
251
|
+
[ @context.storage.put_schedule('at', h.fei, after, msg), 'retry' ]
|
|
252
|
+
|
|
253
|
+
# over
|
|
254
|
+
|
|
255
|
+
persist_or_raise
|
|
256
|
+
|
|
257
|
+
rescue => e
|
|
258
|
+
|
|
259
|
+
raise Ruote::MetaError.new(__method__.to_s, e)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# 'on_{error|timeout|cancel|re_apply}' triggering
|
|
263
|
+
#
|
|
264
|
+
def trigger(on, workitem)
|
|
265
|
+
|
|
266
|
+
tree = tree()
|
|
267
|
+
err = h.applied_workitem['fields']['__error__']
|
|
268
|
+
|
|
269
|
+
handler = on == 'on_error' ? local_on_error(err) : h[on]
|
|
270
|
+
|
|
271
|
+
if on == 'on_error' && handler.to_s.match(/^!(.+)$/)
|
|
272
|
+
handler = $1
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
if handler.is_a?(Hash) # on_re_apply
|
|
276
|
+
|
|
277
|
+
wi = handler['workitem']
|
|
278
|
+
fi = handler['fields']
|
|
279
|
+
me = handler['merge_in_fields']
|
|
280
|
+
|
|
281
|
+
workitem = if wi == 'applied' || me
|
|
282
|
+
h.applied_workitem
|
|
283
|
+
elsif wi
|
|
284
|
+
wi
|
|
285
|
+
else
|
|
286
|
+
workitem
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
workitem['fields'] = fi if fi
|
|
290
|
+
workitem['fields'].merge!(me) if me
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
if h.trigger && t = workitem['fields']["__#{h.trigger}__"]
|
|
294
|
+
#
|
|
295
|
+
# the "second take"...
|
|
296
|
+
|
|
297
|
+
handler = t
|
|
298
|
+
tree = h.supplanted['original_tree']
|
|
299
|
+
workitem = h.supplanted['applied_workitem']
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
if on == 'on_error' && handler.respond_to?(:match) && handler.match(/:/)
|
|
303
|
+
return schedule_retries(handler, err)
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
new_tree = case handler
|
|
307
|
+
when Hash then handler['tree']
|
|
308
|
+
when Array then handler
|
|
309
|
+
when HandlerEntry then [ handler.action, {}, [] ]
|
|
310
|
+
else [ handler.to_s, {}, [] ]
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
handler = handler.action if handler.is_a?(HandlerEntry)
|
|
314
|
+
handler = handler.strip if handler.respond_to?(:strip)
|
|
315
|
+
|
|
316
|
+
if handler =~ /^can(cel|do)$/ && (on == 'on_cancel' || h.on_cancel == nil)
|
|
317
|
+
handler = handler == 'cancel' ? 'undo' : 'redo'
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
h.on_reply = nil if on == 'on_reply'
|
|
321
|
+
# preventing cascades
|
|
322
|
+
|
|
323
|
+
case handler
|
|
324
|
+
|
|
325
|
+
when 'redo', 'retry'
|
|
326
|
+
#
|
|
327
|
+
# retry with the same tree as before
|
|
328
|
+
|
|
329
|
+
new_tree = tree
|
|
330
|
+
|
|
331
|
+
when 'undo', 'pass', ''
|
|
332
|
+
#
|
|
333
|
+
# let's forget it
|
|
334
|
+
|
|
335
|
+
h.state = on == 'on_cancel' ? 'cancelled' : 'failed'
|
|
336
|
+
|
|
337
|
+
reply_to_parent(workitem); return
|
|
338
|
+
|
|
339
|
+
when 'cancel'
|
|
340
|
+
#
|
|
341
|
+
# let's trigger on the on_cancel
|
|
342
|
+
|
|
343
|
+
trigger('on_cancel', workitem); return
|
|
344
|
+
|
|
345
|
+
when 'cando'
|
|
346
|
+
#
|
|
347
|
+
# trigger on_cancel, then redo
|
|
348
|
+
|
|
349
|
+
h.on_reply = tree
|
|
350
|
+
|
|
351
|
+
trigger('on_cancel', workitem); return
|
|
352
|
+
|
|
353
|
+
when 'raise'
|
|
354
|
+
#
|
|
355
|
+
# re-raise
|
|
356
|
+
|
|
357
|
+
raise Ruote.constantize(err['class']), err['message'], err['trace']
|
|
358
|
+
|
|
359
|
+
when CommandExpression::REGEXP
|
|
360
|
+
#
|
|
361
|
+
# a command like 'jump to shark'...
|
|
362
|
+
|
|
363
|
+
hh = handler.split(' ')
|
|
364
|
+
command = hh.first
|
|
365
|
+
step = hh.last
|
|
366
|
+
|
|
367
|
+
h.state = nil
|
|
368
|
+
workitem['fields'][CommandMixin::F_COMMAND] = [ command, step ]
|
|
369
|
+
|
|
370
|
+
reply(workitem); return
|
|
371
|
+
|
|
372
|
+
#else
|
|
373
|
+
#
|
|
374
|
+
# if h.trigger
|
|
375
|
+
# #
|
|
376
|
+
# # do not accept participant or subprocess names
|
|
377
|
+
# # for "second trigger"
|
|
378
|
+
#
|
|
379
|
+
# h.state = 'failed'
|
|
380
|
+
# reply_to_parent(workitem)
|
|
381
|
+
# return
|
|
382
|
+
# end
|
|
383
|
+
#
|
|
384
|
+
# actually, let's not care about that, let's trust people.
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
workitem = h.applied_workitem if on == 'on_error'
|
|
388
|
+
|
|
389
|
+
#
|
|
390
|
+
# supplant this expression with new tree
|
|
391
|
+
|
|
392
|
+
r = try_unpersist
|
|
393
|
+
|
|
394
|
+
raise(
|
|
395
|
+
"failed to remove exp to supplant " +
|
|
396
|
+
"#{Ruote.to_storage_id(h.fei)} #{tree.first}"
|
|
397
|
+
) if r.respond_to?(:keys)
|
|
398
|
+
|
|
399
|
+
if new_tree[0].match(/^!(.+)$/); new_tree[0] = $1; end
|
|
400
|
+
new_tree[1]['_triggered'] = on
|
|
401
|
+
|
|
402
|
+
attributes.each { |k, v|
|
|
403
|
+
new_tree[1][k] = v if (k.match(/^on_/) && k != on) || k == 'tag'
|
|
404
|
+
}
|
|
405
|
+
#
|
|
406
|
+
# let the triggered tree have the same on_ attributes as the original
|
|
407
|
+
# expression, so that on_cancel/on_error/on_x effects still apply
|
|
408
|
+
#
|
|
409
|
+
# 'tag' is copied as well. (so that 'left_tag' is emitted too)
|
|
410
|
+
#
|
|
411
|
+
# Should 'timeout', should other common attributes be copied as well?
|
|
412
|
+
|
|
413
|
+
@context.storage.put_msg(
|
|
414
|
+
'apply',
|
|
415
|
+
{ 'fei' => h.fei,
|
|
416
|
+
'parent_id' => h.parent_id,
|
|
417
|
+
'tree' => new_tree,
|
|
418
|
+
'workitem' => workitem,
|
|
419
|
+
'variables' => h.variables,
|
|
420
|
+
'trigger' => on,
|
|
421
|
+
'on_reply' => h.on_reply,
|
|
422
|
+
'supplanted' => {
|
|
423
|
+
'tree' => tree,
|
|
424
|
+
'original_tree' => original_tree,
|
|
425
|
+
'applied_workitem' => h.applied_workitem,
|
|
426
|
+
'variables' => h.variables
|
|
427
|
+
}})
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
|