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/command.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,8 +30,13 @@ module Ruote::Exp
|
|
|
30
30
|
#
|
|
31
31
|
module CommandMixin
|
|
32
32
|
|
|
33
|
+
# Field name '__command__', where one can place a command.
|
|
34
|
+
#
|
|
33
35
|
F_COMMAND = '__command__'
|
|
34
|
-
|
|
36
|
+
|
|
37
|
+
# break_if, break_unless, rewind_if, rewind_unless, ...
|
|
38
|
+
#
|
|
39
|
+
ATT_COMMANDS = %w[ break rewind reset over stop ]
|
|
35
40
|
|
|
36
41
|
protected
|
|
37
42
|
|
data/lib/ruote/exp/commanded.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
|
|
@@ -58,7 +58,7 @@ module Ruote::Exp
|
|
|
58
58
|
h.command_workitem = workitem
|
|
59
59
|
h.command_workitem['fei'] = h.children.first
|
|
60
60
|
|
|
61
|
-
do_persist
|
|
61
|
+
do_persist or return
|
|
62
62
|
|
|
63
63
|
@context.storage.put_msg('cancel', 'fei' => h.children.first)
|
|
64
64
|
|
data/lib/ruote/exp/condition.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
|
|
@@ -52,8 +52,8 @@ module Ruote::Exp
|
|
|
52
52
|
|
|
53
53
|
def self.apply?(sif, sunless)
|
|
54
54
|
|
|
55
|
-
return (true?(sif)) if sif
|
|
56
|
-
return ( ! true?(sunless)) if sunless
|
|
55
|
+
return (true?(sif)) if sif != nil
|
|
56
|
+
return ( ! true?(sunless)) if sunless != nil
|
|
57
57
|
|
|
58
58
|
true
|
|
59
59
|
end
|
|
@@ -65,9 +65,8 @@ module Ruote::Exp
|
|
|
65
65
|
conditional = unescape(conditional.to_s)
|
|
66
66
|
|
|
67
67
|
REGEXES.each do |method, regex|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
end
|
|
68
|
+
m = regex.match(conditional)
|
|
69
|
+
return self.send(method, m) if m
|
|
71
70
|
end
|
|
72
71
|
|
|
73
72
|
evl(conditional) ? true : false
|
|
@@ -77,6 +76,13 @@ module Ruote::Exp
|
|
|
77
76
|
raise ConditionError.new(conditional)
|
|
78
77
|
end
|
|
79
78
|
|
|
79
|
+
# Returns true if the given conditional string evaluates to false.
|
|
80
|
+
#
|
|
81
|
+
def self.false?(conditional)
|
|
82
|
+
|
|
83
|
+
( ! true?(conditional))
|
|
84
|
+
end
|
|
85
|
+
|
|
80
86
|
# Evaluates the given [conditional] code string and returns the
|
|
81
87
|
# result.
|
|
82
88
|
#
|
|
@@ -95,13 +101,11 @@ module Ruote::Exp
|
|
|
95
101
|
|
|
96
102
|
def self.parse(conditional)
|
|
97
103
|
|
|
98
|
-
|
|
104
|
+
Ruote.parse_ruby(conditional)
|
|
99
105
|
|
|
100
|
-
rescue
|
|
106
|
+
rescue SyntaxError => se
|
|
101
107
|
|
|
102
|
-
|
|
103
|
-
"/!\\ please upgrade your rufus-treechecker gem /!\\"
|
|
104
|
-
)
|
|
108
|
+
[ :str, conditional ]
|
|
105
109
|
|
|
106
110
|
rescue => e
|
|
107
111
|
|
|
@@ -147,9 +151,16 @@ module Ruote::Exp
|
|
|
147
151
|
return evl(tree[1]).send(tree[2], evl(tree.last.last))
|
|
148
152
|
end
|
|
149
153
|
|
|
150
|
-
|
|
154
|
+
if (c = flatten_and_compare(tree)) != nil
|
|
155
|
+
return c
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
if tree[0] == :call
|
|
159
|
+
return flatten(tree)
|
|
160
|
+
end
|
|
151
161
|
|
|
152
162
|
raise ArgumentError
|
|
163
|
+
# TODO : consider returning false
|
|
153
164
|
|
|
154
165
|
#require 'ruby2ruby'
|
|
155
166
|
#Ruby2Ruby.new.process(Sexp.from_array(tree))
|
|
@@ -157,7 +168,21 @@ module Ruote::Exp
|
|
|
157
168
|
# it's nice but "Loan/Grant" becomes "(Loan / Grant)"
|
|
158
169
|
end
|
|
159
170
|
|
|
160
|
-
|
|
171
|
+
def self.flatten_and_compare(tree)
|
|
172
|
+
|
|
173
|
+
ftree = tree.flatten
|
|
174
|
+
comparator = (ftree & COMPARATORS).first
|
|
175
|
+
|
|
176
|
+
return nil unless comparator
|
|
177
|
+
|
|
178
|
+
icomparator = ftree.index(comparator)
|
|
179
|
+
left = ftree[0..icomparator - 1]
|
|
180
|
+
right = ftree[icomparator + 1..-1]
|
|
181
|
+
|
|
182
|
+
evl("#{flatten(left).inspect} #{comparator} #{flatten(right).inspect}")
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
KEYWORDS = %w[ call const arglist str ].collect { |w| w.to_sym }
|
|
161
186
|
|
|
162
187
|
def self.flatten(tree)
|
|
163
188
|
|
|
@@ -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_apply.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
|
|
@@ -0,0 +1,357 @@
|
|
|
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
|
+
require 'ruote/exp/condition'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
module Ruote::Exp
|
|
30
|
+
|
|
31
|
+
#
|
|
32
|
+
# The 'await' expression is the successor of the 'listen' expression
|
|
33
|
+
# (Ruote::Exp::ListenExpression). It's been introduced in ruote 2.3.0.
|
|
34
|
+
#
|
|
35
|
+
# Hopefully it has a simpler syntax than 'listen'. The major difference
|
|
36
|
+
# between listen and await is that await, by default, listens only
|
|
37
|
+
# to events in the same process instance.
|
|
38
|
+
#
|
|
39
|
+
# This expression blocks until an event occurs somewhere else in the same
|
|
40
|
+
# process instance.
|
|
41
|
+
#
|
|
42
|
+
# concurrence do
|
|
43
|
+
# sequence do
|
|
44
|
+
# participant 'alice'
|
|
45
|
+
# await :left_tag => 'a'
|
|
46
|
+
# participant 'bob'
|
|
47
|
+
# end
|
|
48
|
+
# sequence :tag => 'a' do
|
|
49
|
+
# participant 'charly'
|
|
50
|
+
# participant 'doug'
|
|
51
|
+
# end
|
|
52
|
+
# sequence do
|
|
53
|
+
# participant 'eric'
|
|
54
|
+
# end
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# In this example, the flow between alice and bob, will block until 'doug'
|
|
58
|
+
# has replied (Yes, this example could have been written using
|
|
59
|
+
# :left_participant => 'doug').
|
|
60
|
+
#
|
|
61
|
+
# == modes
|
|
62
|
+
#
|
|
63
|
+
# 'await', like 'listen' works in two mode, "once" and "multiple times".
|
|
64
|
+
#
|
|
65
|
+
# In the 'once' mode, the await expression blocks the flow until the workitem
|
|
66
|
+
# (somewhere else in the process instance) leaves the alice participant:
|
|
67
|
+
#
|
|
68
|
+
# sequence do
|
|
69
|
+
# await :left_participant => 'alice'
|
|
70
|
+
# participant 'eric'
|
|
71
|
+
# end
|
|
72
|
+
#
|
|
73
|
+
# In the 'multiple times' mode, the await expression triggers its children
|
|
74
|
+
# expressions each time a matching event occurs. It never replies to its
|
|
75
|
+
# parent expression. Here, the participant 'post_alice' will receive a
|
|
76
|
+
# workitem each time, somewhere else in the process
|
|
77
|
+
#
|
|
78
|
+
# await :left_participant => 'alice' do
|
|
79
|
+
# participant 'post_alice'
|
|
80
|
+
# end
|
|
81
|
+
#
|
|
82
|
+
# Note, that, unlike "listen" in previous versions of ruote, it's OK
|
|
83
|
+
# to consider the children of "await" as part of an implicit sequence:
|
|
84
|
+
#
|
|
85
|
+
# await :left_participant => 'alice' do
|
|
86
|
+
# participant 'bob'
|
|
87
|
+
# participant 'charly'
|
|
88
|
+
# end
|
|
89
|
+
#
|
|
90
|
+
# Bob and charly will be applied in sequence.
|
|
91
|
+
#
|
|
92
|
+
# == tag, participant or error events
|
|
93
|
+
#
|
|
94
|
+
# Await listens to 3 types of events: tag, participant and error events.
|
|
95
|
+
#
|
|
96
|
+
# Here is a assortment of examples:
|
|
97
|
+
#
|
|
98
|
+
# await :in_participant => 'alice'
|
|
99
|
+
# await :reached_participant => 'alice'
|
|
100
|
+
# await :out_participant => 'alice'
|
|
101
|
+
# await :left_participant => 'alice'
|
|
102
|
+
#
|
|
103
|
+
# await :participant => 'alice'
|
|
104
|
+
# await :participants => 'alice' # looks better with an array
|
|
105
|
+
#
|
|
106
|
+
# # implicit OR with arrays:
|
|
107
|
+
# #
|
|
108
|
+
# await :in_participant => /^al/
|
|
109
|
+
# await :in_participant => %w[ alice alfred ]
|
|
110
|
+
# await :in_participant => [ /^al/, /fred$/ ]
|
|
111
|
+
#
|
|
112
|
+
# await :in_tag => 'phase2'
|
|
113
|
+
# await :reached_tag => 'phase2'
|
|
114
|
+
# await :out_tag => 'phase2'
|
|
115
|
+
# await :left_tag => 'phase2'
|
|
116
|
+
#
|
|
117
|
+
# await :tags => 'phase2'
|
|
118
|
+
#
|
|
119
|
+
# await :error
|
|
120
|
+
# await :error => 'ArgumentError'
|
|
121
|
+
# await :error => 'RuntimeError, ArgumentError'
|
|
122
|
+
# await :error => %w[ RuntimeError ArgumentError ]
|
|
123
|
+
#
|
|
124
|
+
# Basically, the attribute is composed of a left part and a right part.
|
|
125
|
+
# The right part is one of "in", "reached" or "out", "left". "in" and
|
|
126
|
+
# "reached" are equivalent, as are "out" and "left".
|
|
127
|
+
#
|
|
128
|
+
# The right part is "tag" or "participant".
|
|
129
|
+
#
|
|
130
|
+
# "error" can be used alone.
|
|
131
|
+
#
|
|
132
|
+
# When "tags" and "participant(s)" are used alone, they are synonymous with
|
|
133
|
+
# "reached_tag" and "reached_participant" respectively.
|
|
134
|
+
#
|
|
135
|
+
# === absolute tags
|
|
136
|
+
#
|
|
137
|
+
# It's OK to specify absolute tags, like in:
|
|
138
|
+
#
|
|
139
|
+
# pdef = Ruote.define do
|
|
140
|
+
# concurrence do
|
|
141
|
+
# sequence do
|
|
142
|
+
# await :tag => 'a/b'
|
|
143
|
+
# echo 'a/b'
|
|
144
|
+
# end
|
|
145
|
+
# sequence :tag => 'a' do
|
|
146
|
+
# noop
|
|
147
|
+
# sequence :tag => 'b' do
|
|
148
|
+
# echo 'b'
|
|
149
|
+
# end
|
|
150
|
+
# end
|
|
151
|
+
# end
|
|
152
|
+
# end
|
|
153
|
+
#
|
|
154
|
+
# == :where condition
|
|
155
|
+
#
|
|
156
|
+
# The "await" expression accepts an optional attribute which adds another
|
|
157
|
+
# guard which is checked to determine if the trigger should occur or not.
|
|
158
|
+
#
|
|
159
|
+
# pdef = Ruote.process_definition do
|
|
160
|
+
# concurrence :wait_for => 1 do
|
|
161
|
+
# await :left_participant => 'a', :where => "${task} == 'sing'" do
|
|
162
|
+
# echo 'sing-a'
|
|
163
|
+
# end
|
|
164
|
+
# await :left_participant => 'a' do
|
|
165
|
+
# echo 'any-a'
|
|
166
|
+
# end
|
|
167
|
+
# concurrence do
|
|
168
|
+
# participant 'a', :task => 'talk'
|
|
169
|
+
# participant 'a', :task => 'sing'
|
|
170
|
+
# end
|
|
171
|
+
# end
|
|
172
|
+
# end
|
|
173
|
+
#
|
|
174
|
+
# In this example, the message 'sing-a' will be echoed only once (twice for
|
|
175
|
+
# 'any-a').
|
|
176
|
+
#
|
|
177
|
+
#
|
|
178
|
+
# == :global => false by default
|
|
179
|
+
#
|
|
180
|
+
# Unlike the 'listen' expression, 'await', by default, only triggers for
|
|
181
|
+
# events in the same process instance. To react on events whatever the
|
|
182
|
+
# process instance, :global => true (or "true") can be used.
|
|
183
|
+
#
|
|
184
|
+
# await :left_tag => 'phase1', :global => true do
|
|
185
|
+
# participant 'supervisor', :msg => 'phase1 over'
|
|
186
|
+
# end
|
|
187
|
+
#
|
|
188
|
+
#
|
|
189
|
+
# == :merge => nil/ignore
|
|
190
|
+
#
|
|
191
|
+
# In the listen expression, the default is for the event's workitem to
|
|
192
|
+
# get merged into the waiting workitem. With 'await', the default is
|
|
193
|
+
# the event's workitem completely overriding the awaiting workitem.
|
|
194
|
+
#
|
|
195
|
+
# Using the :merge attribute, other behaviours are possible.
|
|
196
|
+
#
|
|
197
|
+
# await :left_tag => 'phase3', :merge => 'ignore'
|
|
198
|
+
# await :left_tag => 'phase3', :merge => 'drop'
|
|
199
|
+
# # the event's workitem is ignored, the awaiting workitem is used
|
|
200
|
+
#
|
|
201
|
+
# await :left_tag => 'phase3', :merge => 'override'
|
|
202
|
+
# # the event's workitem is used, this is the default
|
|
203
|
+
#
|
|
204
|
+
# await :left_tag => 'phase3', :merge => 'incoming'
|
|
205
|
+
# # a hash merge happens, the incoming (event) workitem wins
|
|
206
|
+
# # workitem = awaiting.merge(incoming)
|
|
207
|
+
#
|
|
208
|
+
# await :left_tag => 'phase3', :merge => 'awaiting'
|
|
209
|
+
# # a hash merge happens, the awaiting workitem wins
|
|
210
|
+
# # workitem = incoming.merge(awaiting)
|
|
211
|
+
#
|
|
212
|
+
# Note: the :where guard is always about the event's workitem (not the
|
|
213
|
+
# workitem as it reached the 'await' expression).
|
|
214
|
+
#
|
|
215
|
+
class AwaitExpression < FlowExpression
|
|
216
|
+
|
|
217
|
+
names :await
|
|
218
|
+
|
|
219
|
+
INS = %w[ in entered reached]
|
|
220
|
+
OUTS = %w[ out left ]
|
|
221
|
+
|
|
222
|
+
SPLIT_R = /^(#{(INS + OUTS).join('|')})_(tag|participant)s?$/
|
|
223
|
+
SINGLE_R = /^(tag)s|(participant|error)s?$/ # not 'tag' alone
|
|
224
|
+
|
|
225
|
+
def apply
|
|
226
|
+
|
|
227
|
+
#
|
|
228
|
+
# gathering info
|
|
229
|
+
|
|
230
|
+
direction, type, value = attributes.collect { |k, v|
|
|
231
|
+
if m = SPLIT_R.match(k)
|
|
232
|
+
[ m[1], m[2], v ]
|
|
233
|
+
elsif m = SINGLE_R.match(k)
|
|
234
|
+
[ 'in', m[1] || m[2], v ]
|
|
235
|
+
else
|
|
236
|
+
nil
|
|
237
|
+
end
|
|
238
|
+
}.compact.first
|
|
239
|
+
|
|
240
|
+
raise ArgumentError.new(
|
|
241
|
+
"couldn't determine which event to listen to from: " +
|
|
242
|
+
attributes.inspect
|
|
243
|
+
) unless direction
|
|
244
|
+
|
|
245
|
+
global = (attribute(:global).to_s == 'true')
|
|
246
|
+
global = false if type == 'error'
|
|
247
|
+
|
|
248
|
+
h.amerge = attribute(:merge).to_s
|
|
249
|
+
|
|
250
|
+
action = if type == 'tag'
|
|
251
|
+
INS.include?(direction) ? 'entered_tag' : 'left_tag'
|
|
252
|
+
elsif type == 'participant'
|
|
253
|
+
INS.include?(direction) ? 'dispatch' : 'receive'
|
|
254
|
+
else # error
|
|
255
|
+
'error_intercepted'
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
persist_or_raise
|
|
259
|
+
|
|
260
|
+
#
|
|
261
|
+
# adding a new tracker
|
|
262
|
+
|
|
263
|
+
@context.tracker.add_tracker(
|
|
264
|
+
global ? nil : h.fei['wfid'],
|
|
265
|
+
action,
|
|
266
|
+
Ruote.to_storage_id(h.fei),
|
|
267
|
+
determine_condition(type, value),
|
|
268
|
+
{ 'action' => 'reply',
|
|
269
|
+
'fei' => h.fei,
|
|
270
|
+
'workitem' => 'replace',
|
|
271
|
+
'flavour' => 'await' })
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def reply(workitem)
|
|
275
|
+
|
|
276
|
+
#
|
|
277
|
+
# :where guard
|
|
278
|
+
|
|
279
|
+
where = attribute(:where, workitem)
|
|
280
|
+
return if where && Condition.false?(where)
|
|
281
|
+
|
|
282
|
+
#
|
|
283
|
+
# merge
|
|
284
|
+
|
|
285
|
+
wi = h.applied_workitem.dup
|
|
286
|
+
|
|
287
|
+
wi['fields'] = case h.amerge
|
|
288
|
+
when 'ignore', 'drop' then wi['fields']
|
|
289
|
+
when 'incoming' then wi['fields'].merge(workitem['fields'])
|
|
290
|
+
when 'awaiting' then workitem['fields'].merge(wi['fields'])
|
|
291
|
+
else workitem['fields'] # 'override'
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
#
|
|
295
|
+
# actual trigger
|
|
296
|
+
|
|
297
|
+
if tree_children.any?
|
|
298
|
+
|
|
299
|
+
i, t = if tree_children.size == 1
|
|
300
|
+
[ "#{h.fei['expid']}_0", tree_children[0] ]
|
|
301
|
+
else
|
|
302
|
+
[ h.fei['expid'], [ 'sequence', {}, tree_children ] ]
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
launch_sub(i, t, :forget => true, :workitem => wi)
|
|
306
|
+
|
|
307
|
+
else
|
|
308
|
+
|
|
309
|
+
reply_to_parent(wi)
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
protected
|
|
314
|
+
|
|
315
|
+
# Overriding the parent's #reply_to_parent to make sure the tracker is
|
|
316
|
+
# removed before (expression terminating, no need for it to track anything
|
|
317
|
+
# anymore).
|
|
318
|
+
#
|
|
319
|
+
def reply_to_parent(workitem)
|
|
320
|
+
|
|
321
|
+
@context.tracker.remove_tracker(h.fei)
|
|
322
|
+
|
|
323
|
+
super(workitem)
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
# Matches Ruby class names, like "Ruote::ForcedError" or "::ArgumentError"
|
|
327
|
+
#
|
|
328
|
+
KLASS_R = /^(::)?([A-Z][a-z]+)+(::([A-Z][a-z]+)+)*$/
|
|
329
|
+
|
|
330
|
+
# Builds the condition used by the tracker service to filter msgs.
|
|
331
|
+
#
|
|
332
|
+
def determine_condition(type, value)
|
|
333
|
+
|
|
334
|
+
value = Ruote.comma_split(value)
|
|
335
|
+
|
|
336
|
+
if type == 'participant'
|
|
337
|
+
|
|
338
|
+
{ 'participant_name' => value }
|
|
339
|
+
|
|
340
|
+
elsif type == 'error'
|
|
341
|
+
|
|
342
|
+
# array or comma string or string ?
|
|
343
|
+
|
|
344
|
+
h = { 'class' => [], 'message' => [] }
|
|
345
|
+
|
|
346
|
+
value.each { |e| (KLASS_R.match(e) ? h['class'] : h['message']) << e }
|
|
347
|
+
|
|
348
|
+
h.delete_if { |k, v| v == nil or v == [] }
|
|
349
|
+
|
|
350
|
+
else # 'tag'
|
|
351
|
+
|
|
352
|
+
{ (value.first.to_s.match(/\//) ? 'full_tag' : 'tag') => value }
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
|