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.
Files changed (305) hide show
  1. data/CHANGELOG.txt +166 -1
  2. data/CREDITS.txt +36 -17
  3. data/LICENSE.txt +1 -1
  4. data/README.rdoc +1 -7
  5. data/Rakefile +38 -29
  6. data/TODO.txt +93 -52
  7. data/lib/ruote-fs.rb +3 -0
  8. data/lib/ruote.rb +5 -1
  9. data/lib/ruote/context.rb +140 -35
  10. data/lib/ruote/dashboard.rb +1247 -0
  11. data/lib/ruote/{engine → dboard}/process_error.rb +22 -2
  12. data/lib/ruote/dboard/process_status.rb +587 -0
  13. data/lib/ruote/engine.rb +6 -871
  14. data/lib/ruote/exp/command.rb +7 -2
  15. data/lib/ruote/exp/commanded.rb +2 -2
  16. data/lib/ruote/exp/condition.rb +38 -13
  17. data/lib/ruote/exp/fe_add_branches.rb +1 -1
  18. data/lib/ruote/exp/fe_apply.rb +1 -1
  19. data/lib/ruote/exp/fe_await.rb +357 -0
  20. data/lib/ruote/exp/fe_cancel_process.rb +17 -3
  21. data/lib/ruote/exp/fe_command.rb +8 -4
  22. data/lib/ruote/exp/fe_concurrence.rb +218 -18
  23. data/lib/ruote/exp/fe_concurrent_iterator.rb +71 -10
  24. data/lib/ruote/exp/fe_cron.rb +3 -10
  25. data/lib/ruote/exp/fe_cursor.rb +14 -4
  26. data/lib/ruote/exp/fe_define.rb +3 -1
  27. data/lib/ruote/exp/fe_echo.rb +1 -1
  28. data/lib/ruote/exp/fe_equals.rb +1 -1
  29. data/lib/ruote/exp/fe_error.rb +1 -1
  30. data/lib/ruote/exp/fe_filter.rb +163 -4
  31. data/lib/ruote/exp/fe_forget.rb +21 -4
  32. data/lib/ruote/exp/fe_given.rb +1 -1
  33. data/lib/ruote/exp/fe_if.rb +1 -1
  34. data/lib/ruote/exp/fe_inc.rb +102 -35
  35. data/lib/ruote/exp/fe_iterator.rb +47 -12
  36. data/lib/ruote/exp/fe_listen.rb +96 -11
  37. data/lib/ruote/exp/fe_lose.rb +31 -4
  38. data/lib/ruote/exp/fe_noop.rb +1 -1
  39. data/lib/ruote/exp/fe_on_error.rb +109 -0
  40. data/lib/ruote/exp/fe_once.rb +10 -19
  41. data/lib/ruote/exp/fe_participant.rb +90 -28
  42. data/lib/ruote/exp/fe_read.rb +69 -0
  43. data/lib/ruote/exp/fe_redo.rb +3 -2
  44. data/lib/ruote/exp/fe_ref.rb +57 -27
  45. data/lib/ruote/exp/fe_registerp.rb +1 -3
  46. data/lib/ruote/exp/fe_reserve.rb +1 -1
  47. data/lib/ruote/exp/fe_restore.rb +6 -6
  48. data/lib/ruote/exp/fe_save.rb +12 -19
  49. data/lib/ruote/exp/fe_sequence.rb +38 -2
  50. data/lib/ruote/exp/fe_set.rb +143 -40
  51. data/lib/ruote/exp/{fe_let.rb → fe_stall.rb} +7 -38
  52. data/lib/ruote/exp/fe_subprocess.rb +8 -2
  53. data/lib/ruote/exp/fe_that.rb +1 -1
  54. data/lib/ruote/exp/fe_undo.rb +40 -4
  55. data/lib/ruote/exp/fe_unregisterp.rb +1 -3
  56. data/lib/ruote/exp/fe_wait.rb +12 -25
  57. data/lib/ruote/exp/{flowexpression.rb → flow_expression.rb} +375 -229
  58. data/lib/ruote/exp/iterator.rb +2 -2
  59. data/lib/ruote/exp/merge.rb +78 -17
  60. data/lib/ruote/exp/ro_attributes.rb +46 -36
  61. data/lib/ruote/exp/ro_filters.rb +34 -8
  62. data/lib/ruote/exp/ro_on_x.rb +431 -0
  63. data/lib/ruote/exp/ro_persist.rb +19 -7
  64. data/lib/ruote/exp/ro_timers.rb +123 -0
  65. data/lib/ruote/exp/ro_variables.rb +90 -29
  66. data/lib/ruote/fei.rb +57 -3
  67. data/lib/ruote/fs.rb +3 -0
  68. data/lib/ruote/id/mnemo_wfid_generator.rb +30 -7
  69. data/lib/ruote/id/wfid_generator.rb +17 -38
  70. data/lib/ruote/log/default_history.rb +23 -9
  71. data/lib/ruote/log/fancy_printing.rb +265 -0
  72. data/lib/ruote/log/storage_history.rb +23 -13
  73. data/lib/ruote/log/wait_logger.rb +224 -17
  74. data/lib/ruote/observer.rb +82 -0
  75. data/lib/ruote/part/block_participant.rb +65 -28
  76. data/lib/ruote/part/code_participant.rb +81 -0
  77. data/lib/ruote/part/engine_participant.rb +7 -2
  78. data/lib/ruote/part/local_participant.rb +221 -21
  79. data/lib/ruote/part/no_op_participant.rb +1 -1
  80. data/lib/ruote/part/null_participant.rb +1 -1
  81. data/lib/ruote/part/participant.rb +50 -0
  82. data/lib/ruote/part/rev_participant.rb +178 -0
  83. data/lib/ruote/part/smtp_participant.rb +2 -2
  84. data/lib/ruote/part/storage_participant.rb +228 -60
  85. data/lib/ruote/part/template.rb +1 -1
  86. data/lib/ruote/participant.rb +2 -0
  87. data/lib/ruote/reader.rb +205 -68
  88. data/lib/ruote/reader/json.rb +49 -0
  89. data/lib/ruote/reader/radial.rb +303 -0
  90. data/lib/ruote/reader/ruby_dsl.rb +44 -9
  91. data/lib/ruote/reader/xml.rb +11 -8
  92. data/lib/ruote/receiver/base.rb +98 -45
  93. data/lib/ruote/storage/base.rb +104 -35
  94. data/lib/ruote/storage/composite_storage.rb +50 -60
  95. data/lib/ruote/storage/fs_storage.rb +25 -34
  96. data/lib/ruote/storage/hash_storage.rb +38 -36
  97. data/lib/ruote/svc/dispatch_pool.rb +104 -35
  98. data/lib/ruote/svc/dollar_sub.rb +10 -8
  99. data/lib/ruote/svc/error_handler.rb +108 -52
  100. data/lib/ruote/svc/expression_map.rb +3 -3
  101. data/lib/ruote/svc/participant_list.rb +160 -55
  102. data/lib/ruote/svc/tracker.rb +31 -31
  103. data/lib/ruote/svc/treechecker.rb +28 -16
  104. data/lib/ruote/tree_dot.rb +1 -1
  105. data/lib/ruote/util/deep.rb +143 -0
  106. data/lib/ruote/util/filter.rb +125 -18
  107. data/lib/ruote/util/hashdot.rb +15 -13
  108. data/lib/ruote/util/look.rb +1 -1
  109. data/lib/ruote/util/lookup.rb +60 -22
  110. data/lib/ruote/util/misc.rb +63 -18
  111. data/lib/ruote/util/mpatch.rb +53 -0
  112. data/lib/ruote/util/ometa.rb +1 -2
  113. data/lib/ruote/util/process_observer.rb +177 -0
  114. data/lib/ruote/util/subprocess.rb +1 -1
  115. data/lib/ruote/util/time.rb +2 -2
  116. data/lib/ruote/util/tree.rb +64 -2
  117. data/lib/ruote/version.rb +3 -2
  118. data/lib/ruote/worker.rb +421 -92
  119. data/lib/ruote/workitem.rb +157 -22
  120. data/ruote.gemspec +15 -9
  121. data/test/bm/ci.rb +0 -2
  122. data/test/bm/ici.rb +0 -2
  123. data/test/bm/load_26c.rb +0 -3
  124. data/test/bm/mega.rb +0 -2
  125. data/test/functional/base.rb +57 -43
  126. data/test/functional/concurrent_base.rb +16 -13
  127. data/test/functional/ct_0_concurrence.rb +7 -11
  128. data/test/functional/ct_1_iterator.rb +9 -11
  129. data/test/functional/ct_2_cancel.rb +28 -17
  130. data/test/functional/eft_0_flow_expression.rb +35 -0
  131. data/test/functional/eft_10_cancel_process.rb +1 -1
  132. data/test/functional/eft_11_wait.rb +13 -13
  133. data/test/functional/eft_12_listen.rb +199 -66
  134. data/test/functional/eft_13_iterator.rb +95 -29
  135. data/test/functional/eft_14_cursor.rb +74 -24
  136. data/test/functional/eft_15_loop.rb +7 -7
  137. data/test/functional/eft_16_if.rb +1 -1
  138. data/test/functional/eft_17_equals.rb +1 -1
  139. data/test/functional/eft_18_concurrent_iterator.rb +156 -68
  140. data/test/functional/eft_19_reserve.rb +15 -15
  141. data/test/functional/eft_1_echo.rb +1 -1
  142. data/test/functional/eft_20_save.rb +51 -9
  143. data/test/functional/eft_21_restore.rb +1 -1
  144. data/test/functional/eft_22_noop.rb +1 -1
  145. data/test/functional/eft_23_apply.rb +1 -1
  146. data/test/functional/eft_24_add_branches.rb +7 -8
  147. data/test/functional/eft_25_command.rb +1 -1
  148. data/test/functional/eft_26_error.rb +11 -11
  149. data/test/functional/eft_27_inc.rb +111 -67
  150. data/test/functional/eft_28_once.rb +16 -16
  151. data/test/functional/eft_29_cron.rb +9 -9
  152. data/test/functional/eft_2_sequence.rb +23 -4
  153. data/test/functional/eft_30_ref.rb +36 -24
  154. data/test/functional/eft_31_registerp.rb +24 -24
  155. data/test/functional/eft_32_lose.rb +46 -20
  156. data/test/functional/eft_34_given.rb +1 -1
  157. data/test/functional/eft_35_filter.rb +161 -7
  158. data/test/functional/eft_36_read.rb +97 -0
  159. data/test/functional/{eft_0_process_definition.rb → eft_37_process_definition.rb} +4 -4
  160. data/test/functional/eft_38_on_error.rb +195 -0
  161. data/test/functional/eft_39_stall.rb +35 -0
  162. data/test/functional/eft_3_participant.rb +77 -22
  163. data/test/functional/eft_40_await.rb +297 -0
  164. data/test/functional/eft_4_set.rb +110 -11
  165. data/test/functional/eft_5_subprocess.rb +27 -5
  166. data/test/functional/eft_6_concurrence.rb +299 -60
  167. data/test/functional/eft_7_forget.rb +24 -22
  168. data/test/functional/eft_8_undo.rb +52 -15
  169. data/test/functional/eft_9_redo.rb +18 -20
  170. data/test/functional/ft_0_worker.rb +122 -13
  171. data/test/functional/ft_10_dollar.rb +77 -16
  172. data/test/functional/ft_11_recursion.rb +9 -9
  173. data/test/functional/ft_12_launchitem.rb +7 -9
  174. data/test/functional/ft_13_variables.rb +125 -22
  175. data/test/functional/ft_14_re_apply.rb +112 -56
  176. data/test/functional/ft_15_timeout.rb +64 -33
  177. data/test/functional/ft_16_participant_params.rb +59 -6
  178. data/test/functional/ft_17_conditional.rb +68 -2
  179. data/test/functional/ft_18_kill.rb +48 -30
  180. data/test/functional/ft_19_participant_code.rb +67 -0
  181. data/test/functional/ft_1_process_status.rb +222 -150
  182. data/test/functional/ft_20_storage_participant.rb +445 -44
  183. data/test/functional/ft_21_forget.rb +21 -26
  184. data/test/functional/ft_22_process_definitions.rb +8 -6
  185. data/test/functional/ft_23_load_defs.rb +29 -5
  186. data/test/functional/ft_24_block_participant.rb +199 -20
  187. data/test/functional/ft_25_receiver.rb +98 -46
  188. data/test/functional/ft_26_participant_rtimeout.rb +34 -26
  189. data/test/functional/ft_27_var_indirection.rb +40 -5
  190. data/test/functional/ft_28_null_noop_participants.rb +5 -5
  191. data/test/functional/ft_29_part_template.rb +2 -2
  192. data/test/functional/ft_2_errors.rb +106 -74
  193. data/test/functional/ft_30_smtp_participant.rb +7 -7
  194. data/test/functional/ft_31_part_blocking.rb +11 -11
  195. data/test/functional/ft_32_scope.rb +50 -0
  196. data/test/functional/ft_33_participant_subprocess_priority.rb +3 -3
  197. data/test/functional/ft_34_cursor_rewind.rb +14 -14
  198. data/test/functional/ft_35_add_service.rb +67 -9
  199. data/test/functional/ft_36_storage_history.rb +92 -24
  200. data/test/functional/ft_37_default_history.rb +35 -23
  201. data/test/functional/ft_38_participant_more.rb +189 -32
  202. data/test/functional/ft_39_wait_for.rb +25 -25
  203. data/test/functional/ft_3_participant_registration.rb +235 -107
  204. data/test/functional/ft_40_wait_logger.rb +105 -18
  205. data/test/functional/ft_41_participants.rb +13 -12
  206. data/test/functional/ft_42_storage_copy.rb +12 -12
  207. data/test/functional/ft_43_participant_on_reply.rb +85 -11
  208. data/test/functional/ft_44_var_participant.rb +5 -5
  209. data/test/functional/ft_45_participant_accept.rb +3 -3
  210. data/test/functional/ft_46_launch_single.rb +17 -17
  211. data/test/functional/ft_47_wfids.rb +41 -0
  212. data/test/functional/ft_48_lose.rb +19 -25
  213. data/test/functional/ft_49_engine_on_error.rb +54 -70
  214. data/test/functional/ft_4_cancel.rb +84 -26
  215. data/test/functional/ft_50_engine_config.rb +4 -4
  216. data/test/functional/ft_51_misc.rb +12 -12
  217. data/test/functional/ft_52_case.rb +17 -17
  218. data/test/functional/ft_53_engine_on_terminate.rb +18 -21
  219. data/test/functional/ft_54_patterns.rb +18 -16
  220. data/test/functional/ft_55_engine_participant.rb +55 -55
  221. data/test/functional/ft_56_filter_attribute.rb +90 -52
  222. data/test/functional/ft_57_rev_participant.rb +252 -0
  223. data/test/functional/ft_58_workitem.rb +150 -0
  224. data/test/functional/ft_59_pause.rb +329 -0
  225. data/test/functional/ft_5_on_error.rb +430 -77
  226. data/test/functional/ft_60_code_participant.rb +65 -0
  227. data/test/functional/ft_61_trailing_fields.rb +34 -0
  228. data/test/functional/ft_62_exp_name_and_dollar_substitution.rb +35 -0
  229. data/test/functional/ft_63_participants_221.rb +458 -0
  230. data/test/functional/ft_64_stash.rb +41 -0
  231. data/test/functional/ft_65_timers.rb +313 -0
  232. data/test/functional/ft_66_flank.rb +133 -0
  233. data/test/functional/ft_67_radial_misc.rb +34 -0
  234. data/test/functional/ft_68_reput.rb +72 -0
  235. data/test/functional/ft_69_worker_info.rb +56 -0
  236. data/test/functional/ft_6_on_cancel.rb +189 -36
  237. data/test/functional/ft_70_take_and_discard_attributes.rb +94 -0
  238. data/test/functional/ft_71_retries.rb +144 -0
  239. data/test/functional/ft_72_on_terminate.rb +60 -0
  240. data/test/functional/ft_73_raise_msg.rb +107 -0
  241. data/test/functional/ft_74_respark.rb +106 -0
  242. data/test/functional/ft_75_context.rb +66 -0
  243. data/test/functional/ft_76_observer.rb +53 -0
  244. data/test/functional/ft_77_process_observer.rb +157 -0
  245. data/test/functional/ft_78_part_participant.rb +37 -0
  246. data/test/functional/ft_7_tags.rb +238 -50
  247. data/test/functional/ft_8_participant_consumption.rb +27 -21
  248. data/test/functional/ft_9_subprocesses.rb +48 -18
  249. data/test/functional/restart_base.rb +4 -6
  250. data/test/functional/rt_0_wait.rb +10 -10
  251. data/test/functional/rt_1_listen.rb +6 -6
  252. data/test/functional/rt_2_errors.rb +12 -12
  253. data/test/functional/rt_3_once.rb +17 -12
  254. data/test/functional/rt_4_cron.rb +17 -17
  255. data/test/functional/rt_5_timeout.rb +13 -13
  256. data/test/functional/signals.rb +103 -0
  257. data/test/functional/storage.rb +730 -0
  258. data/test/functional/storage_helper.rb +48 -35
  259. data/test/functional/test.rb +6 -2
  260. data/test/misc/idle.rb +21 -0
  261. data/test/misc/light.rb +29 -0
  262. data/test/path_helper.rb +1 -1
  263. data/test/test.rb +2 -5
  264. data/test/test_helper.rb +13 -0
  265. data/test/unit/test.rb +1 -4
  266. data/test/unit/ut_0_ruby_reader.rb +25 -9
  267. data/test/unit/ut_10_participants.rb +47 -0
  268. data/test/unit/ut_11_lookup.rb +59 -2
  269. data/test/unit/ut_12_wait_logger.rb +123 -0
  270. data/test/unit/ut_14_is_uri.rb +1 -1
  271. data/test/unit/ut_15_util.rb +1 -1
  272. data/test/unit/ut_16_reader.rb +136 -14
  273. data/test/unit/ut_17_merge.rb +155 -0
  274. data/test/unit/ut_19_part_template.rb +1 -1
  275. data/test/unit/ut_1_fei.rb +11 -2
  276. data/test/unit/ut_20_composite_storage.rb +27 -1
  277. data/test/unit/{ut_21_participant_list.rb → ut_21_svc_participant_list.rb} +2 -3
  278. data/test/unit/ut_22_filter.rb +231 -10
  279. data/test/unit/ut_23_svc_tracker.rb +48 -0
  280. data/test/unit/ut_24_radial_reader.rb +458 -0
  281. data/test/unit/ut_25_process_status.rb +143 -0
  282. data/test/unit/ut_26_deep.rb +131 -0
  283. data/test/unit/ut_2_dashboard.rb +114 -0
  284. data/test/unit/ut_3_worker.rb +54 -0
  285. data/test/unit/ut_4_expmap.rb +1 -1
  286. data/test/unit/ut_5_tree.rb +23 -23
  287. data/test/unit/ut_6_condition.rb +71 -29
  288. data/test/unit/ut_7_workitem.rb +18 -4
  289. data/test/unit/ut_8_tree_to_dot.rb +1 -1
  290. data/test/unit/ut_9_xml_reader.rb +1 -1
  291. metadata +142 -63
  292. data/jruby_issue.txt +0 -32
  293. data/lib/ruote/engine/process_status.rb +0 -403
  294. data/lib/ruote/log/pretty.rb +0 -165
  295. data/lib/ruote/log/test_logger.rb +0 -204
  296. data/lib/ruote/util/serializer.rb +0 -103
  297. data/phil.txt +0 -14
  298. data/test/functional/eft_33_let.rb +0 -31
  299. data/test/functional/ft_19_alias.rb +0 -33
  300. data/test/functional/ft_47_wfid_generator.rb +0 -54
  301. data/test/unit/storage.rb +0 -403
  302. data/test/unit/storages.rb +0 -37
  303. data/test/unit/ut_13_serializer.rb +0 -65
  304. data/test/unit/ut_18_engine.rb +0 -47
  305. data/test/unit/ut_3_wait_logger.rb +0 -39
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
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
@@ -48,7 +48,8 @@ module Ruote::Exp
48
48
  # it should iterate.
49
49
  #
50
50
  # The 'to' attribute takes two forms, :to_v, :to_var, :to_variable or
51
- # :to_f, :to_fld, :to_field.
51
+ # :to_f, :to_fld, :to_field. Finally, you can write :to => 'field_name',
52
+ # :to => 'f:field_name' or :to => 'v:variable_name'.
52
53
  #
53
54
  # The 'to' attribute instructs the iterator into which variable or field
54
55
  # it should place the current value (the value being iterated over).
@@ -62,7 +63,7 @@ module Ruote::Exp
62
63
  # The 'on' attribute can be replaced by a :time or a :branches attribute.
63
64
  #
64
65
  # pdef = Ruote.process_definition :name => 'test' do
65
- # iterator :times => '3'
66
+ # iterator :times => '3' do
66
67
  # participant 'accounting'
67
68
  # end
68
69
  # end
@@ -77,10 +78,24 @@ module Ruote::Exp
77
78
  # end
78
79
  # end
79
80
  #
81
+ # === variables and scope
82
+ #
83
+ # Starting with ruote 2.3.0, the iterator doesn't create a new scope for
84
+ # its variables, it uses the current scope.
85
+ #
86
+ # The old behaviour can be obtained by setting :scope => true, as in:
87
+ #
88
+ # iterator :on => [ 1, 2, 3 ], :to_v => 'x', :scope => true do
89
+ # # ...
90
+ # end
91
+ #
92
+ # A corollary: by default, the variables set by the iterator or within it
93
+ # stick in the current scope...
94
+ #
80
95
  #
81
96
  # == the classical case
82
97
  #
83
- # Iterating over a workitem field :
98
+ # Iterating over a workitem field:
84
99
  #
85
100
  # pdef = Ruote.process_definition :name => 'test' do
86
101
  # iterator :on_field => 'customers', :to_f => 'customer'
@@ -88,6 +103,17 @@ module Ruote::Exp
88
103
  # end
89
104
  # end
90
105
  #
106
+ # It's equivalent to:
107
+ #
108
+ # pdef = Ruote.process_definition :name => 'test' do
109
+ # iterator :on => '$f:customers', :to_f => 'customer'
110
+ # participant '${f:customer}'
111
+ # end
112
+ # end
113
+ #
114
+ # "$f:customers" yields the actual array, whereas "${f:customers}"
115
+ # yields the string representation of the array.
116
+ #
91
117
  #
92
118
  # == break/rewind/continue/skip/jump
93
119
  #
@@ -190,7 +216,7 @@ module Ruote::Exp
190
216
  h.to_v, h.to_f = determine_tos
191
217
  h.position = -1
192
218
 
193
- h.to_v = 'i' if h.to_v == nil && h.to_f == nil
219
+ h.to_v = 'i' unless h.to_v or h.to_f
194
220
 
195
221
  move_on
196
222
  end
@@ -199,34 +225,43 @@ module Ruote::Exp
199
225
 
200
226
  def move_on(workitem=h.applied_workitem)
201
227
 
202
- h.position += 1
228
+ current_position = h.position
229
+ h.position = 0 if h.position == -1
203
230
 
204
- com, arg = get_command(workitem)
231
+ child_id = workitem['fei'] == h.fei ?
232
+ 0 : Ruote::FlowExpressionId.new(workitem['fei']).child_id + 1
205
233
 
206
- return reply_to_parent(workitem) if com == 'break'
234
+ com, arg = get_command(workitem)
207
235
 
208
236
  case com
237
+
238
+ when 'break' then return reply_to_parent(workitem)
239
+
209
240
  when 'rewind', 'continue' then h.position = 0
210
- when 'skip' then h.position += arg
241
+ when 'skip' then h.position += (arg + 1)
211
242
  when 'jump' then h.position = arg
243
+
244
+ else
245
+ h.position = h.position + 1 if child_id >= tree_children.size
212
246
  end
213
247
 
214
248
  h.position = h.list.length + h.position if h.position < 0
215
249
 
250
+ return apply_child(child_id, workitem) if h.position == current_position
251
+
216
252
  val = h.list[h.position]
217
253
 
218
254
  return reply_to_parent(workitem) if val == nil
219
255
 
220
- (h.variables ||= {})['ii'] = h.position
256
+ set_variable('ii', h.position)
221
257
 
222
258
  if h.to_v
223
- h.variables[h.to_v] = val
259
+ set_variable(h.to_v, val)
224
260
  else #if h.to_f
225
261
  workitem['fields'][h.to_f] = val
226
262
  end
227
263
 
228
264
  apply_child(0, workitem)
229
- # persist is done in there
230
265
  end
231
266
  end
232
267
  end
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
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
@@ -88,6 +88,11 @@ module Ruote::Exp
88
88
  # and this copy is delivered to the expressions that are client to the
89
89
  # 'listen'.
90
90
  #
91
+ # :merge can be set to 'override' where the event's workitem fields are
92
+ # used or some value which isn't true or 'true', in which case the
93
+ # workitem fields of the 'listen' expression is used as is (as it was
94
+ # when the flow reached the 'listen' expression).
95
+ #
91
96
  # == :upon
92
97
  #
93
98
  # There are two kinds of main events in ruote, apply and reply. Thus,
@@ -118,6 +123,24 @@ module Ruote::Exp
118
123
  # * 'entering' 'phase_two'
119
124
  # * 'leaving' 'phase_two'
120
125
  #
126
+ # When listening to tags, absolute paths can be given.
127
+ #
128
+ # concurrence do
129
+ # sequence :tag => 'a' do
130
+ # alpha
131
+ # sequence :tag => 'b' do
132
+ # bravo
133
+ # end
134
+ # end
135
+ # sequence do
136
+ # listen :to => 'a/b', :upon => 'entering'
137
+ # charly
138
+ # end
139
+ # end
140
+ # end
141
+ #
142
+ # Charly will be next when the flow is about to reach bravo.
143
+ #
121
144
  #
122
145
  # == :to and :on
123
146
  #
@@ -165,6 +188,35 @@ module Ruote::Exp
165
188
  # The documentation about the dollar notation and the one about common
166
189
  # attributes :if and :unless applies for the :where attribute.
167
190
  #
191
+ #
192
+ # == listen :to => :errors
193
+ #
194
+ # The listen expression can be made to listen to errors.
195
+ #
196
+ # listen :to => errors do
197
+ # participant 'supervisor_sms', :task => 'verify system'
198
+ # end
199
+ #
200
+ # Whenever an error happens in the process with this listen stance,
201
+ # the listen will trigger.
202
+ #
203
+ # "listen :to => :errors" only works with errors in the same process instance
204
+ # (same wfid).
205
+ #
206
+ # "listen :to => :errors" doesn't trigger when the error is caught (via
207
+ # :on_error).
208
+ #
209
+ # === listen :to => :errors, :class => 'ArgumentError'
210
+ #
211
+ # One can restrict the listen to certain classes of errors.
212
+ # Passing a list of error classes separated by a comma is OK.
213
+ #
214
+ # === listen :to => :errors, :message => /x/
215
+ #
216
+ # One can restrict the error listening to errors matching a certain regex
217
+ # or equal to a certain string. The attribute is :message or :msg. The
218
+ # value is a String (strict equality) or a Regex (matching).
219
+ #
168
220
  class ListenExpression < FlowExpression
169
221
 
170
222
  names :listen, :receive, :intercept
@@ -176,9 +228,12 @@ module Ruote::Exp
176
228
 
177
229
  def apply
178
230
 
231
+ # gathering info
232
+
179
233
  h.to = attribute(:to) || attribute(:on)
180
234
 
181
235
  h.upon = UPONS[attribute(:upon) || 'apply']
236
+ h.upon = 'error_intercepted' if h.to == 'errors'
182
237
 
183
238
  h.lmerge = attribute(:merge).to_s
184
239
  h.lmerge = 'true' if h.lmerge == ''
@@ -186,19 +241,18 @@ module Ruote::Exp
186
241
  h.lwfid = attribute(:wfid).to_s
187
242
  h.lwfid = %w[ same current true ].include?(h.lwfid)
188
243
 
244
+ h.lwfid = true if h.to == 'errors'
245
+ # can only listen to errors in the same process instance
246
+
189
247
  persist_or_raise
190
248
 
191
- condition = if h.upon == 'dispatch' || h.upon == 'receive'
192
- { 'participant_name' => h.to }
193
- else
194
- { 'tag' => h.to }
195
- end
249
+ # adding a new tracker
196
250
 
197
251
  @context.tracker.add_tracker(
198
252
  h.lwfid ? h.fei['wfid'] : nil,
199
253
  h.upon,
200
254
  Ruote.to_storage_id(h.fei),
201
- condition,
255
+ determine_condition,
202
256
  { 'action' => 'reply',
203
257
  'fei' => h.fei,
204
258
  'workitem' => 'replace',
@@ -211,7 +265,7 @@ module Ruote::Exp
211
265
  # :where guard
212
266
 
213
267
  where = attribute(:where, workitem)
214
- return if where && ( ! Condition.true?(where))
268
+ return if where && Condition.false?(where)
215
269
 
216
270
  #
217
271
  # green for trigger
@@ -225,10 +279,16 @@ module Ruote::Exp
225
279
  #else don't touch
226
280
  end
227
281
 
228
- if tree_children.size > 0
282
+ if tree_children.any?
283
+
284
+ i, t = if tree_children.size == 1
285
+ [ "#{h.fei['expid']}_0", tree_children[0] ]
286
+ else
287
+ [ h.fei['expid'], [ 'sequence', {}, tree_children ] ]
288
+ end
289
+
290
+ launch_sub(i, t, :forget => true, :workitem => wi)
229
291
 
230
- launch_sub(
231
- "#{h.fei['expid']}_0", tree[2][0], :forget => true, :workitem => wi)
232
292
  else
233
293
 
234
294
  reply_to_parent(wi)
@@ -237,12 +297,37 @@ module Ruote::Exp
237
297
 
238
298
  protected
239
299
 
300
+ # Overriding the parent's #reply_to_parent to make sure the tracker is
301
+ # removed before (expression terminating, no need for it to track anything
302
+ # anymore).
303
+ #
240
304
  def reply_to_parent(workitem)
241
305
 
242
306
  @context.tracker.remove_tracker(h.fei)
243
307
 
244
308
  super(workitem)
245
309
  end
310
+
311
+ def determine_condition
312
+
313
+ if h.upon == 'dispatch' || h.upon == 'receive'
314
+
315
+ { 'participant_name' => h.to }
316
+
317
+ elsif h.upon == 'error_intercepted'
318
+
319
+ {
320
+ 'class' => Ruote.comma_split(attribute(:class) || ''),
321
+ 'message' => attribute(:message) || attribute(:msg)
322
+ }.delete_if { |k, v|
323
+ v == nil or v == []
324
+ }
325
+
326
+ else
327
+
328
+ { (h.to.match(/\//) ? 'full_tag' : 'tag') => h.to }
329
+ end
330
+ end
246
331
  end
247
332
  end
248
333
 
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
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
@@ -85,12 +85,29 @@ module Ruote::Exp
85
85
  # Probably produces definitions more compact than when using the 'lose'
86
86
  # expression.
87
87
  #
88
- # == forget vs lose
88
+ #
89
+ # == multi lose
90
+ #
91
+ # Losing multiple children:
92
+ #
93
+ # lose do
94
+ # alice :task => 'take out garbage'
95
+ # bob :task => 'clean living room'
96
+ # end
97
+ #
98
+ # will trigger alice's and bob's tasks together. The lose expression will
99
+ # never reply, unless cancelled (in which case alice and bob task get
100
+ # cancelled as well).
101
+ #
102
+ #
103
+ # == forget vs lose vs flank
89
104
  #
90
105
  # forget : replies to parent expression immediately, is not cancellable
91
106
  # (not reachable).
92
107
  #
93
- # lose : never replies to parent expression, is cancellable.
108
+ # lose : never replies to the parent expression, is cancellable.
109
+ #
110
+ # flank : immediately replies to the parent expression, is cancellable.
94
111
  #
95
112
  class LoseExpression < FlowExpression
96
113
 
@@ -98,7 +115,17 @@ module Ruote::Exp
98
115
 
99
116
  def apply
100
117
 
101
- apply_child(0, h.applied_workitem)
118
+ tree_children.each_with_index do |t, index|
119
+
120
+ msg = pre_apply_child(index, Ruote.fulldup(h.applied_workitem), false)
121
+ # forget ? false
122
+
123
+ @context.storage.put_msg('apply', msg)
124
+ end
125
+
126
+ persist_or_raise
127
+
128
+ # no reply to the parent expression
102
129
  end
103
130
 
104
131
  def reply(workitem)
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2005-2011, John Mettraux, jmettraux@gmail.com
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,109 @@
1
+ #--
2
+ # Copyright (c) 2005-2012, John Mettraux, jmettraux@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ # THE SOFTWARE.
21
+ #
22
+ # Made in Japan.
23
+ #++
24
+
25
+
26
+ module Ruote::Exp
27
+
28
+ #
29
+ # Up until ruote 2.3.0, 'on_error' was only an attribute
30
+ #
31
+ # sequence :on_error => 'error_handler' do
32
+ # # ...
33
+ # end
34
+ #
35
+ # This 'on_error' expression makes such definitions possible
36
+ #
37
+ # sequence do
38
+ # on_error /unknown participant/ => 'missing_participant'
39
+ # on_error 'decommission'
40
+ # # ...
41
+ # end
42
+ #
43
+ # where errors containing 'unknown participant' in their messages are handled
44
+ # by the participant or subprocess named 'missing participant', while
45
+ # the rest of the errors is handled by the participant or the subprocess
46
+ # named 'decommission'.
47
+ #
48
+ # Speaking of subprocesses, this is also possible
49
+ #
50
+ # sequence do
51
+ #
52
+ # on_error /unknown participant/ do
53
+ # admin :msg => 'there was an unknown participant'
54
+ # end
55
+ # on_error do
56
+ # # decommissioning...
57
+ # end
58
+ #
59
+ # # ...
60
+ # end
61
+ #
62
+ class OnErrorExpression < FlowExpression
63
+
64
+ names :on_error
65
+
66
+ def apply
67
+
68
+ regex = nil
69
+ handler = attribute_text
70
+
71
+ if handler == ''
72
+ regex = (attributes.keys - COMMON_ATT_KEYS).first
73
+ handler = attribute(regex)
74
+ end
75
+
76
+ if tree.last.size > 0
77
+ regex = handler
78
+ handler = [ 'sequence', {}, Ruote.fulldup(tree.last) ]
79
+ end
80
+
81
+ return reply_to_parent(h.applied_workitem) if regex.nil? && handler.nil?
82
+ # nothing to register, let's move on
83
+
84
+ par = parent
85
+ oe = par.h.on_error
86
+
87
+ if oe.is_a?(String) or Ruote.is_tree?(oe)
88
+ oe = [ nil, oe ]
89
+ end
90
+
91
+ oe = Array(par.h.on_error).compact
92
+ oe << [ regex, handler, fei.child_id ]
93
+
94
+ par.h.on_error = oe
95
+
96
+ if par.do_persist
97
+ reply_to_parent(h.applied_workitem) # success
98
+ else
99
+ apply # try again
100
+ end
101
+ end
102
+
103
+ def reply(workitem)
104
+
105
+ # never called
106
+ end
107
+ end
108
+ end
109
+