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
|
|
@@ -41,8 +41,11 @@ module Ruote
|
|
|
41
41
|
#
|
|
42
42
|
# process_history = engine.history.by_wfid(wfid0)
|
|
43
43
|
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
44
|
+
#
|
|
45
|
+
# == final note
|
|
46
|
+
#
|
|
47
|
+
# By default, the history is an in-memory history (see Ruote::DefaultHistory)
|
|
48
|
+
# (and it is worthless when there are multiple workers).
|
|
46
49
|
#
|
|
47
50
|
class StorageHistory
|
|
48
51
|
|
|
@@ -53,13 +56,7 @@ module Ruote
|
|
|
53
56
|
@context = context
|
|
54
57
|
@options = options
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
# only care about logging if there is a worker present
|
|
59
|
-
|
|
60
|
-
@context.storage.add_type('history')
|
|
61
|
-
@context.worker.subscribe(:all, self)
|
|
62
|
-
end
|
|
59
|
+
@context.storage.add_type('history')
|
|
63
60
|
end
|
|
64
61
|
|
|
65
62
|
# Returns all the wfids for which there are history items (msgs) stored.
|
|
@@ -126,10 +123,12 @@ module Ruote
|
|
|
126
123
|
@context.storage.purge_type!('history')
|
|
127
124
|
end
|
|
128
125
|
|
|
129
|
-
# This is
|
|
130
|
-
# are
|
|
126
|
+
# This method is called by the worker via the context. Successfully
|
|
127
|
+
# processed msgs are passed here.
|
|
131
128
|
#
|
|
132
|
-
def
|
|
129
|
+
def on_msg(msg)
|
|
130
|
+
|
|
131
|
+
return unless accept?(msg)
|
|
133
132
|
|
|
134
133
|
msg = msg.dup
|
|
135
134
|
# a shallow copy is sufficient
|
|
@@ -151,6 +150,17 @@ module Ruote
|
|
|
151
150
|
|
|
152
151
|
@context.storage.put(msg)
|
|
153
152
|
end
|
|
153
|
+
|
|
154
|
+
protected
|
|
155
|
+
|
|
156
|
+
# This default implementation lets all the messages in.
|
|
157
|
+
#
|
|
158
|
+
# Feel free to override this method in a subclass.
|
|
159
|
+
#
|
|
160
|
+
def accept?(msg)
|
|
161
|
+
|
|
162
|
+
true
|
|
163
|
+
end
|
|
154
164
|
end
|
|
155
165
|
end
|
|
156
166
|
|
|
@@ -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
|
|
@@ -22,45 +22,252 @@
|
|
|
22
22
|
# Made in Japan.
|
|
23
23
|
#++
|
|
24
24
|
|
|
25
|
-
require 'ruote/log/test_logger'
|
|
26
|
-
|
|
27
25
|
|
|
28
26
|
module Ruote
|
|
29
27
|
|
|
28
|
+
# The error raised by WaitLogger#wait_for upon a timeout.
|
|
29
|
+
#
|
|
30
|
+
class LoggerTimeout < StandardError
|
|
31
|
+
|
|
32
|
+
def initialize(interests, timeout)
|
|
33
|
+
|
|
34
|
+
super("waited for #{interests.inspect}, timed out after #{timeout}s")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# The logic behind Ruote::Dashboard#wait_for is implemented here.
|
|
40
|
+
#
|
|
41
|
+
# This logger keeps track of the last 147 events. This number can
|
|
42
|
+
# be tweaked via the 'wait_logger_max' storage option
|
|
43
|
+
# (http://ruote.rubyforge.org/configuration.html)
|
|
44
|
+
#
|
|
45
|
+
# One doesn't play directly with this class. It's available only via
|
|
46
|
+
# the Ruote::Dashboard#wait_for and Ruote::Dashboard#noisy=
|
|
30
47
|
#
|
|
31
|
-
#
|
|
48
|
+
# To access the log of processed msgs, look at history services, not
|
|
49
|
+
# at this wait_logger.
|
|
32
50
|
#
|
|
33
|
-
#
|
|
51
|
+
# === options (storage initialization options)
|
|
34
52
|
#
|
|
35
|
-
|
|
53
|
+
# wait_logger_max(Integer)::
|
|
54
|
+
# defaults to 147, max number of recent records to keep track of
|
|
55
|
+
# wait_logger_timeout(Integer)::
|
|
56
|
+
# defaults to 60 (seconds), #wait_for times out after how many seconds?
|
|
57
|
+
#
|
|
58
|
+
class WaitLogger
|
|
59
|
+
|
|
60
|
+
require 'ruote/log/fancy_printing'
|
|
61
|
+
|
|
62
|
+
attr_reader :seen
|
|
63
|
+
attr_reader :log
|
|
36
64
|
|
|
65
|
+
# When set to true, this logger will spit out the ruote activity
|
|
66
|
+
# happening in this Ruby's runtime ruote worker (if any) to $stdout.
|
|
67
|
+
#
|
|
37
68
|
attr_accessor :noisy
|
|
38
69
|
|
|
70
|
+
# The timeout for #wait_for. Defaults to 60 (seconds). When set to
|
|
71
|
+
# number inferior or equal to zero, no timeout will be enforced.
|
|
72
|
+
#
|
|
73
|
+
attr_accessor :timeout
|
|
74
|
+
|
|
39
75
|
def initialize(context)
|
|
40
76
|
|
|
41
77
|
@context = context
|
|
42
|
-
@color = 33
|
|
43
78
|
|
|
44
|
-
@
|
|
79
|
+
@seen = []
|
|
80
|
+
@log = []
|
|
81
|
+
@waiting = []
|
|
45
82
|
|
|
46
|
-
@noisy = false
|
|
47
83
|
@count = -1
|
|
84
|
+
@color = 33
|
|
85
|
+
@noisy = false
|
|
48
86
|
|
|
49
|
-
@
|
|
50
|
-
@
|
|
87
|
+
@log_max = context['wait_logger_max'] || 147
|
|
88
|
+
@timeout = context['wait_logger_timeout'] || 60 # in seconds
|
|
89
|
+
|
|
90
|
+
@check_mutex = Mutex.new
|
|
51
91
|
end
|
|
52
92
|
|
|
53
|
-
|
|
93
|
+
# The context will call this method for each msg sucessfully processed
|
|
94
|
+
# by the worker.
|
|
95
|
+
#
|
|
96
|
+
def on_msg(msg)
|
|
54
97
|
|
|
55
|
-
puts(
|
|
98
|
+
puts(fancy_print(msg, @noisy)) if @noisy
|
|
56
99
|
|
|
57
|
-
|
|
58
|
-
#check_msg(msg)
|
|
100
|
+
return if msg['action'] == 'noop'
|
|
59
101
|
|
|
60
102
|
@seen << msg
|
|
61
|
-
@
|
|
103
|
+
@log << msg
|
|
104
|
+
|
|
105
|
+
while @log.size > @log_max; @log.shift; end
|
|
106
|
+
while @seen.size > @log_max; @seen.shift; end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Returns an array of the latest msgs, but fancy-printed. The oldest
|
|
110
|
+
# first.
|
|
111
|
+
#
|
|
112
|
+
def fancy_log
|
|
113
|
+
|
|
114
|
+
@log.collect { |msg| fancy_print(msg) }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Debug only : dumps all the seen events to $stdout
|
|
118
|
+
#
|
|
119
|
+
def dump
|
|
120
|
+
|
|
121
|
+
@seen.collect { |msg| fancy_print(msg) }.join("\n")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Blocks until one or more interests are satisfied.
|
|
125
|
+
#
|
|
126
|
+
# interests must be an array of interests. Please refer to
|
|
127
|
+
# Dashboard#wait_for documentation for allowed values of each interest.
|
|
128
|
+
#
|
|
129
|
+
# If multiple interests are given, wait_for blocks until
|
|
130
|
+
# all of the interests are satisfied.
|
|
131
|
+
#
|
|
132
|
+
# wait_for may only be used by one thread at a time. If one
|
|
133
|
+
# thread calls wait_for and later another thread calls wait_for
|
|
134
|
+
# while the first thread is waiting, the first thread's
|
|
135
|
+
# interests are lost and the first thread will never wake up.
|
|
136
|
+
#
|
|
137
|
+
def wait_for(interests, opts={})
|
|
138
|
+
|
|
139
|
+
@waiting << [ Thread.current, interests ]
|
|
140
|
+
|
|
141
|
+
Thread.current['__result__'] = nil
|
|
142
|
+
start = Time.now
|
|
143
|
+
|
|
144
|
+
to = opts[:timeout] || @timeout
|
|
145
|
+
to = nil if to.nil? || to <= 0
|
|
146
|
+
|
|
147
|
+
loop do
|
|
148
|
+
|
|
149
|
+
raise(
|
|
150
|
+
Ruote::LoggerTimeout.new(interests, to)
|
|
151
|
+
) if to && (Time.now - start) > to
|
|
152
|
+
|
|
153
|
+
@check_mutex.synchronize { check_waiting }
|
|
154
|
+
|
|
155
|
+
break if Thread.current['__result__']
|
|
156
|
+
|
|
157
|
+
sleep 0.007
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
Thread.current['__result__']
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def color=(c)
|
|
164
|
+
|
|
165
|
+
@color = c
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def self.fp(msg)
|
|
169
|
+
|
|
170
|
+
@logger ||= TestLogger.new(nil)
|
|
171
|
+
puts @logger.send(:fancy_print, msg)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
protected
|
|
175
|
+
|
|
176
|
+
def check_waiting
|
|
177
|
+
|
|
178
|
+
while @waiting.any? and msg = @seen.shift
|
|
179
|
+
|
|
180
|
+
@waiting.delete_if do |thread, interests|
|
|
181
|
+
thread['__result__'] = msg if matches(interests, msg)
|
|
182
|
+
(interests.size < 1)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
FINAL_ACTIONS = %w[
|
|
188
|
+
terminated ceased error_intercepted
|
|
189
|
+
]
|
|
190
|
+
ACTIONS = FINAL_ACTIONS + %w[
|
|
191
|
+
launch apply reply
|
|
192
|
+
fail
|
|
193
|
+
dispatch dispatched receive
|
|
194
|
+
cancel dispatch_cancel kill
|
|
195
|
+
pause resume dispatch_pause dispatch_resume
|
|
196
|
+
regenerate
|
|
197
|
+
pause_process resume_process cancel_process kill_process
|
|
198
|
+
reput noop raise
|
|
199
|
+
respark
|
|
200
|
+
]
|
|
201
|
+
|
|
202
|
+
# Checks whether message msg matches any of interests being waited for.
|
|
203
|
+
#
|
|
204
|
+
# Some interests look for actions on particular workflows (e.g.,
|
|
205
|
+
# waiting for some workflow to finish). Other interests are not
|
|
206
|
+
# attached to any particular workflow (e.g., :inactive waits until
|
|
207
|
+
# the engine finishes processing all active and pending workflows)
|
|
208
|
+
# but are still satisfied when actions happen on workflows (e.g.,
|
|
209
|
+
# the last workflow being run finishes).
|
|
210
|
+
#
|
|
211
|
+
# Returns true if all interests being waited for have been satisfied,
|
|
212
|
+
# false otherwise.
|
|
213
|
+
#
|
|
214
|
+
def matches(interests, msg)
|
|
215
|
+
|
|
216
|
+
action = msg['action']
|
|
217
|
+
|
|
218
|
+
interests.each do |interest|
|
|
219
|
+
|
|
220
|
+
satisfied = case interest
|
|
221
|
+
|
|
222
|
+
when :or_error
|
|
223
|
+
#
|
|
224
|
+
# let's force an immediate reply
|
|
225
|
+
|
|
226
|
+
interests.clear if action == 'error_intercepted'
|
|
227
|
+
|
|
228
|
+
when :inactive
|
|
229
|
+
|
|
230
|
+
(FINAL_ACTIONS.include?(action) && @context.worker.inactive?)
|
|
231
|
+
|
|
232
|
+
when :empty
|
|
233
|
+
|
|
234
|
+
(action == 'terminated' && @context.storage.empty?('expressions'))
|
|
235
|
+
|
|
236
|
+
when Symbol
|
|
237
|
+
|
|
238
|
+
(action == 'dispatch' && msg['participant_name'] == interest.to_s)
|
|
239
|
+
|
|
240
|
+
when Fixnum
|
|
241
|
+
|
|
242
|
+
interests.delete(interest)
|
|
243
|
+
|
|
244
|
+
if (interest > 1)
|
|
245
|
+
interests << (interest - 1)
|
|
246
|
+
false
|
|
247
|
+
else
|
|
248
|
+
true
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
when Hash
|
|
252
|
+
|
|
253
|
+
interest.all? { |k, v|
|
|
254
|
+
k = 'tree.0' if k == 'exp_name'
|
|
255
|
+
Ruote.lookup(msg, k) == v
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
when /^[a-z_]+$/
|
|
259
|
+
|
|
260
|
+
(action == interest)
|
|
261
|
+
|
|
262
|
+
else # wfid
|
|
263
|
+
|
|
264
|
+
(FINAL_ACTIONS.include?(action) && msg['wfid'] == interest)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
interests.delete(interest) if satisfied
|
|
268
|
+
end
|
|
62
269
|
|
|
63
|
-
|
|
270
|
+
(interests.size < 1)
|
|
64
271
|
end
|
|
65
272
|
end
|
|
66
273
|
end
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# An abstract class for observing the activity of a ruote engine.
|
|
30
|
+
#
|
|
31
|
+
# Subclass it and add it as a service to observe certain events.
|
|
32
|
+
#
|
|
33
|
+
# require 'ruote/observer'
|
|
34
|
+
#
|
|
35
|
+
# class MyLaunchObserver < Ruote::Observer
|
|
36
|
+
#
|
|
37
|
+
# def on_msg_launch(msg)
|
|
38
|
+
# puts "just launched process instance #{msg['wfid']}"
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# dashboard.add_service('launch_observer', MyLaunchObserver)
|
|
43
|
+
#
|
|
44
|
+
# # ...
|
|
45
|
+
#
|
|
46
|
+
# Simply add a "on_msg_<msg_name>" method for it to intercept the
|
|
47
|
+
# given messages.
|
|
48
|
+
#
|
|
49
|
+
# See Ruote::ProcessObserver for a base class with precisely defined
|
|
50
|
+
# methods with helpful arguments if you don't want to investigate
|
|
51
|
+
# "msgs" too much.
|
|
52
|
+
#
|
|
53
|
+
class Observer
|
|
54
|
+
|
|
55
|
+
def initialize(context)
|
|
56
|
+
|
|
57
|
+
@context = context
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def on_pre_msg(msg)
|
|
61
|
+
|
|
62
|
+
route('pre', msg)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def on_msg(msg)
|
|
66
|
+
|
|
67
|
+
route(nil, msg)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
protected
|
|
71
|
+
|
|
72
|
+
def route(time, msg)
|
|
73
|
+
|
|
74
|
+
target = [ 'on', time, 'msg', msg['action'] ].compact.join('_')
|
|
75
|
+
|
|
76
|
+
return unless self.respond_to?(target)
|
|
77
|
+
|
|
78
|
+
send(target, msg)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright (c) 2005-
|
|
2
|
+
# Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -22,8 +22,6 @@
|
|
|
22
22
|
# Made in Japan.
|
|
23
23
|
#++
|
|
24
24
|
|
|
25
|
-
require 'ruote/part/local_participant'
|
|
26
|
-
|
|
27
25
|
|
|
28
26
|
module Ruote
|
|
29
27
|
|
|
@@ -48,19 +46,20 @@ module Ruote
|
|
|
48
46
|
# == do_not_thread
|
|
49
47
|
#
|
|
50
48
|
# By default, this participant (like most other participants) is executed
|
|
51
|
-
# in its own thread
|
|
52
|
-
# EM.next_tick is used instead of a new thread).
|
|
49
|
+
# in its own thread.
|
|
53
50
|
#
|
|
54
|
-
# You can change that behaviour (beware block thats monopolises the whole
|
|
55
|
-
# engine !) by doing
|
|
56
51
|
#
|
|
57
|
-
#
|
|
58
|
-
# workitem.fields['time'] = Time.now
|
|
59
|
-
# end
|
|
52
|
+
# == context
|
|
60
53
|
#
|
|
61
|
-
#
|
|
54
|
+
# As it includes Ruote::LocalParticipant, the block partitcipant has
|
|
55
|
+
# access to:
|
|
62
56
|
#
|
|
63
|
-
#
|
|
57
|
+
# * #context: the ruote context
|
|
58
|
+
# * #workitem: the current workitem (usually passed as arg to the block)
|
|
59
|
+
# * #fei: the current flow expression id
|
|
60
|
+
# * #fexp: the current flow expression
|
|
61
|
+
# * #flavour: only used in #on_cancel (nil or 'kill')
|
|
62
|
+
# * #lookup_variable(key): looks up a variable...
|
|
64
63
|
#
|
|
65
64
|
class BlockParticipant
|
|
66
65
|
|
|
@@ -73,26 +72,14 @@ module Ruote
|
|
|
73
72
|
@opts = opts
|
|
74
73
|
end
|
|
75
74
|
|
|
76
|
-
def
|
|
77
|
-
|
|
78
|
-
@opts['do_not_thread']
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def consume(workitem)
|
|
75
|
+
def on_workitem
|
|
82
76
|
|
|
83
|
-
block =
|
|
84
|
-
|
|
85
|
-
@context.treechecker.block_check(block)
|
|
86
|
-
# raises in case of 'security' violation
|
|
87
|
-
|
|
88
|
-
#block = eval(block, @context.send(:binding))
|
|
89
|
-
# doesn't work with ruby 1.9.2-p136
|
|
90
|
-
block = eval(block, @context.instance_eval { binding })
|
|
91
|
-
# works OK with ruby 1.8.7-249 and 1.9.2-p136
|
|
77
|
+
block = get_block('on_workitem', 'block')
|
|
92
78
|
|
|
93
79
|
r = if block.arity == 1
|
|
94
80
|
|
|
95
81
|
block.call(workitem)
|
|
82
|
+
|
|
96
83
|
else
|
|
97
84
|
|
|
98
85
|
block.call(
|
|
@@ -108,7 +95,57 @@ module Ruote
|
|
|
108
95
|
|
|
109
96
|
def cancel(fei, flavour)
|
|
110
97
|
|
|
111
|
-
|
|
98
|
+
if block = get_block('on_cancel')
|
|
99
|
+
block.call(fei, flavour)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def on_reply(workitem)
|
|
104
|
+
|
|
105
|
+
if block = get_block('on_reply')
|
|
106
|
+
block.call(workitem)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def accept?(workitem)
|
|
111
|
+
|
|
112
|
+
if block = get_block('accept?')
|
|
113
|
+
block.call(workitem)
|
|
114
|
+
else
|
|
115
|
+
true
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def do_not_thread(workitem)
|
|
120
|
+
|
|
121
|
+
dnt = @opts['do_not_thread']
|
|
122
|
+
|
|
123
|
+
return dnt unless dnt.is_a?(String)
|
|
124
|
+
|
|
125
|
+
block = get_block('do_not_thread')
|
|
126
|
+
|
|
127
|
+
block.call(workitem)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
protected
|
|
131
|
+
|
|
132
|
+
def get_block(*keys)
|
|
133
|
+
|
|
134
|
+
key = keys.find { |k| @opts[k] }
|
|
135
|
+
|
|
136
|
+
return nil unless key
|
|
137
|
+
|
|
138
|
+
block = @opts[key]
|
|
139
|
+
|
|
140
|
+
@context.treechecker.block_check(block)
|
|
141
|
+
# raises in case of 'security' violation
|
|
142
|
+
|
|
143
|
+
#eval(block, @context.send(:binding))
|
|
144
|
+
# doesn't work with ruby 1.9.2-p136
|
|
145
|
+
#eval(block, @context.instance_eval { binding })
|
|
146
|
+
# works OK with ruby 1.8.7-249 and 1.9.2-p136
|
|
147
|
+
eval(block, self.instance_eval { binding })
|
|
148
|
+
# works OK with ruby 1.8.7-249 and 1.9.2-p136
|
|
112
149
|
end
|
|
113
150
|
end
|
|
114
151
|
end
|