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
|
|
@@ -49,13 +49,27 @@ module Ruote::Exp
|
|
|
49
49
|
# If the goal is to cancel only a segment of a process instance, the
|
|
50
50
|
# expression 'undo' (Ruote::Exp::UndoExpression) is better suited.
|
|
51
51
|
#
|
|
52
|
+
# == 'terminate'
|
|
53
|
+
#
|
|
54
|
+
# Sometimes 'terminate' reads better than 'cancel_process'
|
|
55
|
+
#
|
|
56
|
+
# Ruote.process_definition do
|
|
57
|
+
# alice :task => 'do this'
|
|
58
|
+
# terminate :if => '${no_need_for_bob}'
|
|
59
|
+
# bob :task => 'do that'
|
|
60
|
+
# charly :task => 'just do it'
|
|
61
|
+
# end
|
|
62
|
+
#
|
|
52
63
|
class CancelProcessExpression < FlowExpression
|
|
53
64
|
|
|
54
|
-
names :cancel_process, :terminate
|
|
65
|
+
names :cancel_process, :terminate, :kill_process
|
|
55
66
|
|
|
56
67
|
def apply
|
|
57
68
|
|
|
58
|
-
@context.storage.put_msg(
|
|
69
|
+
@context.storage.put_msg(
|
|
70
|
+
'cancel_process',
|
|
71
|
+
'wfid' => h.fei['wfid'],
|
|
72
|
+
'flavour' => name == 'kill_process' ? 'kill' : nil)
|
|
59
73
|
end
|
|
60
74
|
|
|
61
75
|
def reply(workitem)
|
data/lib/ruote/exp/fe_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
|
|
@@ -29,8 +29,8 @@ require 'ruote/exp/command'
|
|
|
29
29
|
module Ruote::Exp
|
|
30
30
|
|
|
31
31
|
#
|
|
32
|
-
# This class gathers the 'skip', 'back', 'jump', 'rewind', 'continue'
|
|
33
|
-
# 'break' expressions which are used inside of the 'cursor' and 'repeat'
|
|
32
|
+
# This class gathers the 'skip', 'back', 'jump', 'rewind', 'continue', 'reset'
|
|
33
|
+
# and 'break' expressions which are used inside of the 'cursor' and 'repeat'
|
|
34
34
|
# (loop) expressions.
|
|
35
35
|
#
|
|
36
36
|
# Look at the 'cursor' expression Ruote::Exp::Cursor for a discussion of
|
|
@@ -87,7 +87,11 @@ module Ruote::Exp
|
|
|
87
87
|
|
|
88
88
|
include CommandMixin
|
|
89
89
|
|
|
90
|
-
names :skip, :back, :jump, :rewind, :continue, :break, :stop, :over
|
|
90
|
+
names :skip, :back, :jump, :rewind, :continue, :break, :stop, :over, :reset
|
|
91
|
+
|
|
92
|
+
# Used by FlowExpression when dealing with :on_error or :on_timeout
|
|
93
|
+
#
|
|
94
|
+
REGEXP = Regexp.new("^(#{expression_names.join('|')})( .+)?$")
|
|
91
95
|
|
|
92
96
|
def apply
|
|
93
97
|
|
|
@@ -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,6 +52,48 @@ module Ruote::Exp
|
|
|
52
52
|
# in that example, the concurrence will terminate as soon as 1 (count) of
|
|
53
53
|
# the branches replies. The other branch will get cancelled.
|
|
54
54
|
#
|
|
55
|
+
# :count and :wait_for may point to a negative integer, meaning "all but
|
|
56
|
+
# x".
|
|
57
|
+
#
|
|
58
|
+
# concurrence :count => -2 do # all the branches replied but 2
|
|
59
|
+
# # ...
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
# :count can be shortened to :c.
|
|
63
|
+
#
|
|
64
|
+
# === :wait_for
|
|
65
|
+
#
|
|
66
|
+
# This attribute accepts either an integer, either a list of tags.
|
|
67
|
+
#
|
|
68
|
+
# When used with the integer, it's equivalent to the :count attribute:
|
|
69
|
+
#
|
|
70
|
+
# concurrence :wait_for => 1 do
|
|
71
|
+
# # ...
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
74
|
+
# It waits for 1 branch to respond and then moves on (concurrence over).
|
|
75
|
+
#
|
|
76
|
+
# When used with a string (or an array), it extracts a list of tags and waits
|
|
77
|
+
# for the branches with those tags. Once all the tags have replied,
|
|
78
|
+
# the concurrence is over.
|
|
79
|
+
#
|
|
80
|
+
# concurrence :wait_for => 'alpha, bravo' do
|
|
81
|
+
# sequence :tag => 'alpha' do
|
|
82
|
+
# # ...
|
|
83
|
+
# end
|
|
84
|
+
# sequence :tag => 'bravo' do
|
|
85
|
+
# # ...
|
|
86
|
+
# end
|
|
87
|
+
# sequence :tag => 'charly' do
|
|
88
|
+
# # ...
|
|
89
|
+
# end
|
|
90
|
+
# end
|
|
91
|
+
#
|
|
92
|
+
# This concurrence will be over when the branches alpha and bravo have
|
|
93
|
+
# replied. The charly branch may have replied or not, it doesn't matter.
|
|
94
|
+
#
|
|
95
|
+
# :wait_for can be shortened to :wf.
|
|
96
|
+
#
|
|
55
97
|
# === :remaining
|
|
56
98
|
#
|
|
57
99
|
# As said for :count, the remaining branches get cancelled. By setting
|
|
@@ -63,6 +105,15 @@ module Ruote::Exp
|
|
|
63
105
|
# bravo
|
|
64
106
|
# end
|
|
65
107
|
#
|
|
108
|
+
# :remaining can be shortened to :rem or :r.
|
|
109
|
+
#
|
|
110
|
+
# The default is 'cancel', where all the remaining branches are cancelled
|
|
111
|
+
# while the hand is given back to the main flow.
|
|
112
|
+
#
|
|
113
|
+
# There is a third setting, 'wait'. It behaves like 'cancel', but the
|
|
114
|
+
# concurrence waits for the cancelled children to reply. The workitems
|
|
115
|
+
# from cancelled branches are merged in as well.
|
|
116
|
+
#
|
|
66
117
|
# === :merge
|
|
67
118
|
#
|
|
68
119
|
# By default, the workitems override each others. By default, the first
|
|
@@ -97,6 +148,8 @@ module Ruote::Exp
|
|
|
97
148
|
#
|
|
98
149
|
# makes sure that alpha's version of the workitem wins.
|
|
99
150
|
#
|
|
151
|
+
# :merge can be shortened to :m.
|
|
152
|
+
#
|
|
100
153
|
# === :merge_type
|
|
101
154
|
#
|
|
102
155
|
# ==== :override
|
|
@@ -141,8 +194,60 @@ module Ruote::Exp
|
|
|
141
194
|
# This could prove useful for participant having to deal with multiple merge
|
|
142
195
|
# strategy results.
|
|
143
196
|
#
|
|
197
|
+
# ==== :union
|
|
198
|
+
#
|
|
199
|
+
# (Available from ruote 2.3.0)
|
|
200
|
+
#
|
|
201
|
+
# Will override atomic fields, concat arrays and merge hashes...
|
|
202
|
+
#
|
|
203
|
+
# The union of those two workitems
|
|
204
|
+
#
|
|
205
|
+
# { 'a' => 0, 'b' => [ 'x', 'y' ], 'c' => { 'aa' => 'bb' }
|
|
206
|
+
# { 'a' => 1, 'b' => [ 'y', 'z' ], 'c' => { 'cc' => 'dd' }
|
|
207
|
+
#
|
|
208
|
+
# will be
|
|
209
|
+
#
|
|
210
|
+
# { 'a' => 1,
|
|
211
|
+
# 'b' => [ 'x', 'y', 'z' ],
|
|
212
|
+
# 'c' => { 'aa' => 'bb', 'cc' => 'dd' } }
|
|
213
|
+
#
|
|
214
|
+
# Warning: duplicates in arrays present _before_ the merge will be removed
|
|
215
|
+
# as well.
|
|
216
|
+
#
|
|
217
|
+
# ==== :concat
|
|
218
|
+
#
|
|
219
|
+
# (Available from ruote 2.3.0)
|
|
220
|
+
#
|
|
221
|
+
# Much like :union, but duplicates are not removed. Thus
|
|
222
|
+
#
|
|
223
|
+
# { 'a' => 0, 'b' => [ 'x', 'y' ], 'c' => { 'aa' => 'bb' }
|
|
224
|
+
# { 'a' => 1, 'b' => [ 'y', 'z' ], 'c' => { 'cc' => 'dd' }
|
|
225
|
+
#
|
|
226
|
+
# will be
|
|
227
|
+
#
|
|
228
|
+
# { 'a' => 1,
|
|
229
|
+
# 'b' => [ 'x', 'y', 'y', 'z' ],
|
|
230
|
+
# 'c' => { 'aa' => 'bb', 'cc' => 'dd' } }
|
|
231
|
+
#
|
|
232
|
+
# ==== :deep
|
|
233
|
+
#
|
|
234
|
+
# (Available from ruote 2.3.0)
|
|
235
|
+
#
|
|
236
|
+
# Identical to :concat but hashes are merged with deep_merge (ActiveSupport
|
|
237
|
+
# flavour).
|
|
238
|
+
#
|
|
239
|
+
# ==== :ignore
|
|
144
240
|
#
|
|
145
|
-
#
|
|
241
|
+
# (Available from ruote 2.3.0)
|
|
242
|
+
#
|
|
243
|
+
# A very simple merge type, the workitems given back by the branches are
|
|
244
|
+
# simply discarded and the workitem as passed to the concurrence expression
|
|
245
|
+
# is used to reply to the parent expression (of the concurrence expression).
|
|
246
|
+
#
|
|
247
|
+
# :merge_type can be shortened to :mt.
|
|
248
|
+
#
|
|
249
|
+
#
|
|
250
|
+
# === :over_if (and :over_unless) attribute
|
|
146
251
|
#
|
|
147
252
|
# Like the :count attribute controls how many branches have to reply before
|
|
148
253
|
# a concurrence ends, the :over attribute is used to specify a condition
|
|
@@ -166,30 +271,70 @@ module Ruote::Exp
|
|
|
166
271
|
|
|
167
272
|
names :concurrence
|
|
168
273
|
|
|
274
|
+
COUNT_R = /^-?\d+$/
|
|
275
|
+
|
|
169
276
|
def apply
|
|
170
277
|
|
|
171
|
-
h.
|
|
172
|
-
|
|
278
|
+
return do_reply_to_parent(h.applied_workitem) if tree_children.empty?
|
|
279
|
+
|
|
280
|
+
#
|
|
281
|
+
# count and wait_for
|
|
282
|
+
|
|
283
|
+
count = (attribute(:count) || attribute(:c)).to_s
|
|
284
|
+
count = nil unless COUNT_R.match(count)
|
|
285
|
+
|
|
286
|
+
wf = count || attribute(:wait_for) || attribute(:wf)
|
|
287
|
+
|
|
288
|
+
if COUNT_R.match(wf.to_s)
|
|
289
|
+
h.ccount = wf.to_i
|
|
290
|
+
elsif wf
|
|
291
|
+
h.wait_for = Ruote.comma_split(wf)
|
|
292
|
+
end
|
|
173
293
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
294
|
+
#
|
|
295
|
+
# other attributes
|
|
296
|
+
|
|
297
|
+
h.cmerge = att(
|
|
298
|
+
[ :merge, :m ],
|
|
299
|
+
%w[ first last highest lowest ])
|
|
300
|
+
h.cmerge_type = att(
|
|
301
|
+
[ :merge_type, :mt ],
|
|
302
|
+
%w[ override mix isolate stack union ignore concat deep ])
|
|
303
|
+
h.remaining = att(
|
|
304
|
+
[ :remaining, :rem, :r ],
|
|
305
|
+
%w[ cancel forget wait ])
|
|
177
306
|
|
|
178
307
|
h.workitems = (h.cmerge == 'first' || h.cmerge == 'last') ? [] : {}
|
|
179
308
|
|
|
180
309
|
h.over = false
|
|
181
310
|
|
|
182
311
|
apply_children
|
|
312
|
+
|
|
313
|
+
@context.storage.put_msg(
|
|
314
|
+
'reply', 'fei' => h.fei, 'workitem' => h.applied_workitem
|
|
315
|
+
) if h.ccount == 0
|
|
316
|
+
#
|
|
317
|
+
# force an immediate reply
|
|
183
318
|
end
|
|
184
319
|
|
|
185
320
|
def reply(workitem)
|
|
186
321
|
|
|
322
|
+
workitem = Ruote.fulldup(workitem)
|
|
323
|
+
#
|
|
324
|
+
# since workitem field merging might happen, better to work on
|
|
325
|
+
# a copy of the workitem (so that history, coming afterwards,
|
|
326
|
+
# doesn't see a modified version of the workitem)
|
|
327
|
+
|
|
187
328
|
if h.cmerge == 'first' || h.cmerge == 'last'
|
|
188
329
|
h.workitems << workitem
|
|
189
330
|
else
|
|
190
331
|
h.workitems[workitem['fei']['expid']] = workitem
|
|
191
332
|
end
|
|
192
333
|
|
|
334
|
+
if h.wait_for && tag = workitem['fields']['__left_tag__']
|
|
335
|
+
h.wait_for.delete(tag)
|
|
336
|
+
end
|
|
337
|
+
|
|
193
338
|
over = h.over
|
|
194
339
|
h.over = over || over?(workitem)
|
|
195
340
|
|
|
@@ -198,6 +343,10 @@ module Ruote::Exp
|
|
|
198
343
|
|
|
199
344
|
reply_to_parent(nil)
|
|
200
345
|
|
|
346
|
+
elsif h.over && h.remaining == 'wait'
|
|
347
|
+
|
|
348
|
+
reply_to_parent(nil)
|
|
349
|
+
|
|
201
350
|
elsif h.children.empty?
|
|
202
351
|
|
|
203
352
|
do_unpersist || return
|
|
@@ -236,9 +385,13 @@ module Ruote::Exp
|
|
|
236
385
|
over_unless = attribute(:over_unless, workitem)
|
|
237
386
|
|
|
238
387
|
if over_if && Condition.true?(over_if)
|
|
388
|
+
workitem['winner'] = true
|
|
239
389
|
true
|
|
240
390
|
elsif over_unless && (not Condition.true?(over_unless))
|
|
391
|
+
workitem['winner'] = true
|
|
241
392
|
true
|
|
393
|
+
elsif h.wait_for
|
|
394
|
+
h.wait_for.empty?
|
|
242
395
|
else
|
|
243
396
|
(h.workitems.size >= expected_count)
|
|
244
397
|
end
|
|
@@ -246,30 +399,70 @@ module Ruote::Exp
|
|
|
246
399
|
|
|
247
400
|
# How many branch replies are expected before the concurrence is over ?
|
|
248
401
|
#
|
|
402
|
+
def expected_count
|
|
403
|
+
|
|
404
|
+
if h.ccount.nil?
|
|
405
|
+
count_list_size
|
|
406
|
+
elsif h.ccount >= 0
|
|
407
|
+
[ h.ccount, count_list_size ].min
|
|
408
|
+
else # all but 1, 2, ...
|
|
409
|
+
i = count_list_size + h.ccount
|
|
410
|
+
i < 1 ? 1 : i
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
249
414
|
# (note : concurrent_iterator overrides it)
|
|
250
415
|
#
|
|
251
|
-
def
|
|
416
|
+
def count_list_size
|
|
252
417
|
|
|
253
|
-
|
|
418
|
+
tree_children.size
|
|
254
419
|
end
|
|
255
420
|
|
|
256
421
|
def reply_to_parent(_workitem)
|
|
257
422
|
|
|
423
|
+
#
|
|
424
|
+
# remaining 'wait' case first
|
|
425
|
+
|
|
426
|
+
if h.remaining == 'wait'
|
|
427
|
+
|
|
428
|
+
if h.workitems.size >= count_list_size
|
|
429
|
+
#
|
|
430
|
+
# all children have replied
|
|
431
|
+
|
|
432
|
+
workitem = merge_all_workitems
|
|
433
|
+
|
|
434
|
+
do_unpersist && super(workitem, false)
|
|
435
|
+
|
|
436
|
+
elsif h.children_cancelled == nil
|
|
437
|
+
#
|
|
438
|
+
# the concurrence is over, let's cancel all children and then
|
|
439
|
+
# wait for them
|
|
440
|
+
|
|
441
|
+
h.children_cancelled = true
|
|
442
|
+
do_persist
|
|
443
|
+
|
|
444
|
+
h.children.each { |i| @context.storage.put_msg('cancel', 'fei' => i) }
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
return
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
#
|
|
451
|
+
# remaining 'forget' and 'cancel' cases
|
|
452
|
+
|
|
258
453
|
workitem = merge_all_workitems
|
|
259
454
|
|
|
260
|
-
if h.
|
|
455
|
+
if h.children.empty?
|
|
261
456
|
|
|
262
457
|
do_unpersist && super(workitem, false)
|
|
263
458
|
|
|
264
459
|
elsif h.remaining == 'cancel'
|
|
265
460
|
|
|
266
|
-
if
|
|
461
|
+
if do_unpersist
|
|
267
462
|
|
|
268
463
|
super(workitem, false)
|
|
269
464
|
|
|
270
|
-
h.children.each
|
|
271
|
-
@context.storage.put_msg('cancel', 'fei' => i) #unless replied?(i)
|
|
272
|
-
end
|
|
465
|
+
h.children.each { |i| @context.storage.put_msg('cancel', 'fei' => i) }
|
|
273
466
|
end
|
|
274
467
|
|
|
275
468
|
else # h.remaining == 'forget'
|
|
@@ -281,9 +474,13 @@ module Ruote::Exp
|
|
|
281
474
|
end
|
|
282
475
|
end
|
|
283
476
|
|
|
477
|
+
# Called by #reply_to_parent, returns the unique, merged, workitem that
|
|
478
|
+
# will be fed back to the parent expression.
|
|
479
|
+
#
|
|
284
480
|
def merge_all_workitems
|
|
285
481
|
|
|
286
482
|
return h.applied_workitem if h.workitems.size < 1
|
|
483
|
+
return h.applied_workitem if h.cmerge_type == 'ignore'
|
|
287
484
|
|
|
288
485
|
wis = case h.cmerge
|
|
289
486
|
when 'first'
|
|
@@ -294,11 +491,14 @@ module Ruote::Exp
|
|
|
294
491
|
is = h.workitems.keys.sort.collect { |k| h.workitems[k] }
|
|
295
492
|
h.cmerge == 'highest' ? is.reverse : is
|
|
296
493
|
end
|
|
297
|
-
rwis = wis.reverse
|
|
298
494
|
|
|
299
|
-
wis.
|
|
300
|
-
|
|
301
|
-
|
|
495
|
+
as, bs = wis.partition { |wi| wi.delete('winner') }
|
|
496
|
+
wis = bs + as
|
|
497
|
+
#
|
|
498
|
+
# the 'winner' is the workitem that triggered successfully the
|
|
499
|
+
# :over_if or :over_unless, let's take him precedence in the merge...
|
|
500
|
+
|
|
501
|
+
merge_workitems(wis, h.cmerge_type)
|
|
302
502
|
end
|
|
303
503
|
end
|
|
304
504
|
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
|
|
@@ -64,6 +64,43 @@ module Ruote::Exp
|
|
|
64
64
|
# rewind/break/jump/... like 'iterator' does, since it fires all its
|
|
65
65
|
# branches when applied.
|
|
66
66
|
#
|
|
67
|
+
# == :on and arrays
|
|
68
|
+
#
|
|
69
|
+
# Given a workitem field named 'x' containing the array value
|
|
70
|
+
# [ 'a', 'b', 'c' ] and a workitem field 'y' containing the string 'a, b, c',
|
|
71
|
+
# this:
|
|
72
|
+
#
|
|
73
|
+
# concurrent_iterator :on_field => 'x', :to_f => 'xx' do
|
|
74
|
+
# # ...
|
|
75
|
+
# end
|
|
76
|
+
#
|
|
77
|
+
# is equivalent to
|
|
78
|
+
#
|
|
79
|
+
# concurrent_iterator :on => '$f:x', :to_f => 'xx' do
|
|
80
|
+
# # ...
|
|
81
|
+
# end
|
|
82
|
+
#
|
|
83
|
+
# is equivalent to
|
|
84
|
+
#
|
|
85
|
+
# concurrent_iterator :on => '${f:y}', :to_f => 'xx' do
|
|
86
|
+
# # ...
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# == :to_field and :to_f, :to_var and :to_v, :to
|
|
90
|
+
#
|
|
91
|
+
# Those 4 lines are equivalent:
|
|
92
|
+
#
|
|
93
|
+
# concurrent_iterator :on => [ 'ceo', 'cto' ], :to_field => 'a' do ...
|
|
94
|
+
# concurrent_iterator :on => [ 'ceo', 'cto' ], :to_f => 'a' do ...
|
|
95
|
+
# concurrent_iterator :on => [ 'ceo', 'cto' ], :to => 'f:a' do ...
|
|
96
|
+
# concurrent_iterator :on => [ 'ceo', 'cto' ], :to => 'a' do ...
|
|
97
|
+
#
|
|
98
|
+
# Those 3 lines are equivalent:
|
|
99
|
+
#
|
|
100
|
+
# concurrent_iterator :on => [ 'ceo', 'cto' ], :to_var => 'a' do ...
|
|
101
|
+
# concurrent_iterator :on => [ 'ceo', 'cto' ], :to_v => 'a' do ...
|
|
102
|
+
# concurrent_iterator :on => [ 'ceo', 'cto' ], :to => 'v:a' do ...
|
|
103
|
+
#
|
|
67
104
|
# == :times and :branches
|
|
68
105
|
#
|
|
69
106
|
# Similarly to the iterator expression, the :times or the :branches attribute
|
|
@@ -86,6 +123,28 @@ module Ruote::Exp
|
|
|
86
123
|
# end
|
|
87
124
|
#
|
|
88
125
|
#
|
|
126
|
+
# == ruote 2.3.0 and the citerator children
|
|
127
|
+
#
|
|
128
|
+
# Prior to ruote 2.3.0, the concurrent-iterator only considered one child
|
|
129
|
+
# expression:
|
|
130
|
+
#
|
|
131
|
+
# concurrent_iterator :times => 3 do
|
|
132
|
+
# participant 'al'
|
|
133
|
+
# participant 'bob' # 'bob' would never be reached
|
|
134
|
+
# end
|
|
135
|
+
#
|
|
136
|
+
# So one had to write:
|
|
137
|
+
#
|
|
138
|
+
# concurrent_iterator :times => 3 do
|
|
139
|
+
# sequence do
|
|
140
|
+
# participant 'al'
|
|
141
|
+
# participant 'bob' # 'bob' would never be reached
|
|
142
|
+
# end
|
|
143
|
+
# end
|
|
144
|
+
#
|
|
145
|
+
# Ruote 2.3.0 lifts that restriction.
|
|
146
|
+
#
|
|
147
|
+
#
|
|
89
148
|
# == options
|
|
90
149
|
#
|
|
91
150
|
# the concurrent_iterator accepts the same options for merging as its bigger
|
|
@@ -145,7 +204,7 @@ module Ruote::Exp
|
|
|
145
204
|
|
|
146
205
|
count = (list.first.to_i rescue nil)
|
|
147
206
|
|
|
148
|
-
list = (h.list_size +
|
|
207
|
+
list = (h.list_size + 0...h.list_size + count) if count
|
|
149
208
|
end
|
|
150
209
|
|
|
151
210
|
list.each do |val|
|
|
@@ -153,7 +212,6 @@ module Ruote::Exp
|
|
|
153
212
|
h.list_size += 1
|
|
154
213
|
|
|
155
214
|
workitem = Ruote.fulldup(h.applied_workitem)
|
|
156
|
-
#workitem = Rufus::Json.dup(h.applied_workitem)
|
|
157
215
|
|
|
158
216
|
variables = { 'ii' => h.list_size - 1 }
|
|
159
217
|
|
|
@@ -163,11 +221,14 @@ module Ruote::Exp
|
|
|
163
221
|
workitem['fields'][h.to_f] = val
|
|
164
222
|
end
|
|
165
223
|
|
|
224
|
+
expid, subtree = if tree_children.size > 1
|
|
225
|
+
[ h.fei['expid'], [ 'sequence', {}, tree_children ] ]
|
|
226
|
+
else
|
|
227
|
+
[ "#{h.fei['expid']}_0", tree_children[0] ]
|
|
228
|
+
end
|
|
229
|
+
|
|
166
230
|
launch_sub(
|
|
167
|
-
|
|
168
|
-
tree_children[0],
|
|
169
|
-
:workitem => workitem,
|
|
170
|
-
:variables => variables)
|
|
231
|
+
expid, subtree, :workitem => workitem, :variables => variables)
|
|
171
232
|
end
|
|
172
233
|
end
|
|
173
234
|
|
|
@@ -199,7 +260,7 @@ module Ruote::Exp
|
|
|
199
260
|
return reply_to_parent(h.applied_workitem) if list.empty?
|
|
200
261
|
|
|
201
262
|
h.to_v, h.to_f = determine_tos
|
|
202
|
-
h.to_v = 'i'
|
|
263
|
+
h.to_v = 'i' unless h.to_v or h.to_f
|
|
203
264
|
|
|
204
265
|
h.list_size = 0
|
|
205
266
|
|
|
@@ -210,9 +271,9 @@ module Ruote::Exp
|
|
|
210
271
|
|
|
211
272
|
# Overrides the implementation found in ConcurrenceExpression
|
|
212
273
|
#
|
|
213
|
-
def
|
|
274
|
+
def count_list_size
|
|
214
275
|
|
|
215
|
-
h.
|
|
276
|
+
h.list_size
|
|
216
277
|
end
|
|
217
278
|
end
|
|
218
279
|
end
|