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
@@ -25,7 +25,6 @@
25
25
 
26
26
  require 'rufus/dollar' # gem 'rufus-dollar'
27
27
  require 'ruote/svc/treechecker'
28
- require 'ruote/util/lookup'
29
28
 
30
29
 
31
30
  module Ruote
@@ -65,10 +64,8 @@ module Ruote
65
64
 
66
65
  elsif text.is_a?(Hash)
67
66
 
68
- text.inject({}) { |h, (k, v)|
69
-
67
+ text.remap { |(k, v), h|
70
68
  h[s(k, flow_expression, workitem)] = s(v, flow_expression, workitem)
71
- h
72
69
  }
73
70
 
74
71
  else
@@ -90,7 +87,7 @@ module Ruote
90
87
 
91
88
  # If the final text is of the form "$f:x" or "$v:y" will lookup the
92
89
  # x field or the y variable. If the lookup is successful (not nil) will
93
- # return the, not the text.
90
+ # return the value, not the text (the value.to_s).
94
91
  #
95
92
  def literal_sub(s, fexp, wi)
96
93
 
@@ -123,9 +120,9 @@ module Ruote
123
120
  attr_reader :fexp
124
121
  attr_reader :workitem
125
122
 
126
- def initialize(flowexpression, workitem)
123
+ def initialize(flow_expression, workitem)
127
124
 
128
- @fexp = flowexpression
125
+ @fexp = flow_expression
129
126
  @workitem = workitem
130
127
  end
131
128
 
@@ -137,6 +134,11 @@ module Ruote
137
134
  return @fexp.fei.subid if key == 'sub_wfid' # deprecated in 2.1.12
138
135
  return @fexp.fei.expid if key == 'expid'
139
136
  return @fexp.fei.engine_id if key == 'engine_id'
137
+ return @fexp.fei.mnemo_id if key == 'mnemo_id'
138
+
139
+ return @workitem['fields']['__tags__'] if key == 'tags'
140
+ return (@workitem['fields']['__tags__'] || []).last if key == 'tag'
141
+ return (@workitem['fields']['__tags__'] || []).join('/') if key == 'full_tag'
140
142
 
141
143
  pr, k = extract_prefix(key)
142
144
 
@@ -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
@@ -26,7 +26,21 @@
26
26
  module Ruote
27
27
 
28
28
  #
29
- # A ruote service for turning exceptions into process errors (or letting
29
+ # For errors occuring when handling errors.
30
+ #
31
+ class MetaError < StandardError
32
+
33
+ attr_reader :error
34
+
35
+ def initialize(message, error)
36
+
37
+ super("#{message}: #{error.to_s}")
38
+ @error = error
39
+ end
40
+ end
41
+
42
+ #
43
+ # A ruote service for turning errors into process errors (or letting
30
44
  # those error fire any potential :on_error attributes in the process
31
45
  # definition).
32
46
  #
@@ -42,18 +56,36 @@ module Ruote
42
56
 
43
57
  # As used by the dispatch pool and the worker.
44
58
  #
45
- def msg_handle(msg, exception)
59
+ def msg_handle(msg, err)
46
60
 
47
61
  fexp = Ruote::Exp::FlowExpression.fetch(
48
62
  @context, msg['fei'] || msg['workitem']['fei']
49
63
  ) rescue nil
50
64
 
51
- handle(msg, fexp, exception)
65
+ handle(msg, fexp, err)
66
+ end
67
+
68
+ # Packages the error in a 'raise' msg and places it in the storage,
69
+ # for a worker to pick it up.
70
+ #
71
+ def msg_raise(msg, err)
72
+
73
+ fei = msg['fei']
74
+ wfid = msg['wfid'] || msg.fetch('fei', {})['wfid']
75
+
76
+ @context.storage.put_msg(
77
+ 'raise',
78
+ 'fei' => fei,
79
+ 'wfid' => wfid,
80
+ 'msg' => msg,
81
+ 'error' => deflate(err, fei))
52
82
  end
53
83
 
54
84
  # As used by some receivers (see ruote-beanstalk's receiver).
55
85
  #
56
- def action_handle(action, fei, exception)
86
+ # TODO: at some point, merge that with #msg_raise
87
+ #
88
+ def action_handle(action, fei, err)
57
89
 
58
90
  fexp = Ruote::Exp::FlowExpression.fetch(@context, fei)
59
91
 
@@ -61,74 +93,98 @@ module Ruote
61
93
  'action' => action,
62
94
  'fei' => fei,
63
95
  'participant_name' => fexp.h.participant_name,
64
- 'workitem' => fexp.h.applied_workitem }
96
+ 'workitem' => fexp.h.applied_workitem,
97
+ 'put_at' => Ruote.now_to_utc_s }
65
98
 
66
- handle(msg, fexp, exception)
99
+ handle(msg, fexp, err)
67
100
  end
68
101
 
69
102
  protected
70
103
 
71
- # As used by the worker.
104
+ # Called by msg_handle or action_handle.
72
105
  #
73
- def handle(msg, fexp, exception)
106
+ def handle(msg, fexp, err)
74
107
 
75
- wfid = msg['wfid'] || (msg['fei']['wfid'] rescue nil)
76
- fei = msg['fei'] || (fexp.h.fei rescue nil)
108
+ err = RaisedError.new(err) unless err.respond_to?(:backtrace)
77
109
 
78
- backtrace = exception.backtrace || []
79
-
80
- # debug only
81
-
82
- if $DEBUG || ARGV.include?('-d')
83
-
84
- puts "\n== worker intercepted error =="
85
- puts
86
- p exception
87
- puts backtrace[0, 20].join("\n")
88
- puts "..."
89
- puts
90
- puts "-- msg --"
91
- key_length = msg.keys.collect { |k| k.length }.max + 1
92
- msg.keys.sort.each { |k|
93
- v = msg[k]
94
- v = (Ruote.sid(v) rescue nil) if k == 'fei' || k == 'parent_id'
95
- printf("%*s : %s\n", key_length, k, v.inspect)
96
- }
97
- puts "-- . --"
98
- puts
99
- end
110
+ meta = err.is_a?(Ruote::MetaError)
111
+
112
+ fei = msg['fei'] || (fexp.h.fei rescue nil)
113
+ wfid = msg['wfid'] || (fei || {})['wfid']
100
114
 
101
115
  # on_error ?
102
116
 
103
- return if fexp && fexp.handle_on_error(msg, exception)
117
+ return if ( ! meta) && fexp && fexp.handle_on_error(msg, err)
104
118
 
105
119
  # emit 'msg'
106
120
  #
107
121
  # (this message might get intercepted by a tracker)
108
122
 
109
- @context.storage.put_msg(
110
- 'error_intercepted',
111
- 'error' => {
112
- 'fei' => fei,
113
- 'at' => Ruote.now_to_utc_s,
114
- 'class' => exception.class.name,
115
- 'message' => exception.message,
116
- 'trace' => backtrace
117
- },
118
- 'wfid' => wfid,
119
- 'fei' => fei,
120
- 'msg' => msg)
123
+ herr = deflate(err, fei, fexp)
121
124
 
122
125
  # fill error in the error journal
123
126
 
124
127
  @context.storage.put(
125
- 'type' => 'errors',
126
- '_id' => "err_#{Ruote.to_storage_id(fei)}",
127
- 'message' => exception.inspect,
128
- 'trace' => backtrace.join("\n"),
129
- 'fei' => fei,
130
- 'msg' => msg
128
+ herr.merge(
129
+ 'type' => 'errors',
130
+ '_id' => "err_#{Ruote.to_storage_id(fei)}",
131
+ 'message' => err.inspect, # :-(
132
+ 'trace' => (err.backtrace || []).join("\n"), # :-(
133
+ 'msg' => msg)
131
134
  ) if fei
135
+
136
+ # advertise 'error_intercepted'
137
+
138
+ @context.storage.put_msg(
139
+ 'error_intercepted',
140
+ 'error' => herr, 'wfid' => wfid, 'fei' => fei, 'msg' => msg)
141
+
142
+ rescue => e
143
+
144
+ raise e unless @context.worker
145
+
146
+ @context.worker.send(
147
+ :handle_step_error,
148
+ e,
149
+ { 'action' => 'error_intercepted',
150
+ 'error' => deflate(err, fei),
151
+ 'fei' => fei,
152
+ 'wfid' => wfid,
153
+ 'msg' => msg })
154
+ end
155
+
156
+ # Returns a serializable hash with all the details of the error.
157
+ #
158
+ def deflate(err, fei, fexp=nil)
159
+
160
+ return err unless err.respond_to?(:backtrace)
161
+
162
+ fexp ||=
163
+ Ruote::Exp::FlowExpression.dummy('fei' => fei, 'original_tree' => nil)
164
+
165
+ fexp.deflate(err)
166
+ end
167
+
168
+ # The 'raise' action/msg passes deflated errors. This wrapper class
169
+ # "inflates" them.
170
+ #
171
+ class RaisedError
172
+ def initialize(h)
173
+ @h = h
174
+ end
175
+ def class
176
+ Ruote.constantize(@h['class'])
177
+ end
178
+ def message
179
+ @h['message']
180
+ end
181
+ def backtrace
182
+ @h['trace']
183
+ end
184
+ def to_s
185
+ "raised: #{@h['class']}: #{@h['message']}"
186
+ end
187
+ alias inspect to_s
132
188
  end
133
189
  end
134
190
  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
@@ -29,12 +29,12 @@ module Exp
29
29
  end
30
30
  end
31
31
 
32
- require 'ruote/exp/flowexpression'
32
+ require 'ruote/exp/flow_expression'
33
33
 
34
34
 
35
35
  exppath = File.join(File.dirname(__FILE__), '..', 'exp')
36
36
 
37
- Dir.new(exppath).entries.each do |pa|
37
+ Dir.new(exppath).entries.sort.each do |pa|
38
38
  require(File.join('ruote', 'exp', pa)) if pa.match(/^fe_.*\.rb$/)
39
39
  end
40
40
 
@@ -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
@@ -24,7 +24,10 @@
24
24
 
25
25
 
26
26
  require 'sourcify'
27
+
28
+ require 'ruote/part/local_participant'
27
29
  require 'ruote/part/block_participant'
30
+ require 'ruote/part/code_participant'
28
31
 
29
32
 
30
33
  module Ruote
@@ -38,41 +41,75 @@ module Ruote
38
41
  #
39
42
  class ParticipantList
40
43
 
44
+ # Vanilla service #initialize.
45
+ #
41
46
  def initialize(context)
42
47
 
43
48
  @context = context
44
49
  end
45
50
 
46
- # Registers a participant. Called by Engine#register_participant.
51
+ # Used by #register and by Ruote::ParticipantRegistrationProxy
47
52
  #
48
- def register(name, participant, options, block)
53
+ def to_entry(name, participant, options, block)
49
54
 
50
55
  raise(
51
56
  ArgumentError.new(
52
- "can only accept strings (classnames) or classes as participant arg")
57
+ 'can only accept strings (classnames) or classes as participant arg')
53
58
  ) unless [ String, Class, NilClass ].include?(participant.class)
54
59
 
55
60
  klass = (participant || Ruote::BlockParticipant).to_s
56
61
 
57
- options = options.inject({}) { |h, (k, v)|
58
- h[k.to_s] = v.is_a?(Symbol) ? v.to_s : v
59
- h
62
+ options = options.remap { |(k, v), h|
63
+ h[k.to_s] = case v
64
+ when Symbol then v.to_s
65
+ when Proc then v.to_raw_source
66
+ else v
67
+ end
60
68
  }
61
69
 
62
- if block
63
- options['block'] = block.to_source
64
- @context.treechecker.block_check(options['block'])
70
+ extract_blocks(block).each do |meth, code|
71
+ @context.treechecker.block_check(code)
72
+ options[meth] = code
65
73
  end
66
74
 
67
- key = (name.is_a?(Regexp) ? name : Regexp.new("^#{name}$")).source
75
+ [
76
+ (name.is_a?(Regexp) ? name : Regexp.new("^#{name}$")).source,
77
+ [ klass, options ]
78
+ ]
79
+ end
80
+
81
+ # Registers a participant. Called by Engine#register_participant.
82
+ #
83
+ def register(name, participant, options, block)
84
+
85
+ entry = to_entry(name, participant, options, block)
68
86
 
69
- entry = [ key, [ klass, options ] ]
87
+ key = entry.first
88
+ options = entry.last.last
70
89
 
71
90
  list = get_list
72
91
 
73
- list['list'].delete_if { |e| e.first == key }
92
+ position = options['position'] || options['pos'] || 'last'
93
+
94
+ if position == 'before'
95
+
96
+ position = list['list'].index { |e| e.first == key } || -1
97
+
98
+ elsif position == 'after'
99
+
100
+ position = (list['list'].rindex { |e| e.first == key } || -2) + 1
101
+
102
+ elsif position == 'over'
103
+
104
+ position = list['list'].index { |e| e.first == key } || -1
105
+ list['list'].delete_at(position) unless position == -1
106
+
107
+ elsif options.delete('override') != false
108
+
109
+ list['list'].delete_if { |e| e.first == key }
110
+ # enforces only one instance of a participant per key/regex
111
+ end
74
112
 
75
- position = options['position'] || 'last'
76
113
  case position
77
114
  when 'last' then list['list'] << entry
78
115
  when 'first' then list['list'].unshift(entry)
@@ -147,6 +184,10 @@ module Ruote
147
184
  #
148
185
  def lookup_info(pname, workitem)
149
186
 
187
+ wi = workitem ?
188
+ Ruote::Workitem.new(workitem.merge('participant_name' => pname)) :
189
+ nil
190
+
150
191
  get_list['list'].each do |regex, pinfo|
151
192
 
152
193
  next unless pname.match(regex)
@@ -156,12 +197,11 @@ module Ruote
156
197
  pa = instantiate(pinfo, :if_respond_to? => :accept?)
157
198
 
158
199
  return pinfo if pa.nil?
159
-
160
- return pinfo if pa.accept?(
161
- Ruote::Workitem.new(workitem.merge('participant_name' => pname))
162
- )
200
+ return pinfo if Ruote.participant_send(pa, :accept?, 'workitem' => wi)
163
201
  end
164
202
 
203
+ # nothing found...
204
+
165
205
  nil
166
206
  end
167
207
 
@@ -169,13 +209,6 @@ module Ruote
169
209
  #
170
210
  def instantiate(pinfo, opts={})
171
211
 
172
- #pinfo = @instantiated_participants[pinfo] if pinfo.is_a?(String)
173
- #if pinfo.respond_to?(:consume)
174
- # return (pinfo.respond_to?(irt) ? pinfo : nil) if irt
175
- # return pinfo
176
- #end
177
- #return nil unless pinfo
178
-
179
212
  pa_class_name, options = pinfo
180
213
 
181
214
  if rp = options['require_path']
@@ -251,6 +284,7 @@ module Ruote
251
284
  def list=(pl)
252
285
 
253
286
  list = get_list
287
+
254
288
  list['list'] = pl.collect { |e|
255
289
  ParticipantEntry.read(e)
256
290
  }.collect { |e|
@@ -262,12 +296,73 @@ module Ruote
262
296
  #
263
297
  # put failed, have to redo it
264
298
  #
265
- list=(pl)
299
+ self.list=(pl)
266
300
  end
267
301
  end
268
302
 
303
+ # Clears this participant list.
304
+ #
305
+ # Used by Engine#register(&block)
306
+ #
307
+ def clear
308
+
309
+ self.list=([])
310
+ end
311
+
269
312
  protected
270
313
 
314
+ # Used by #extract_blocks when evaluating sub-blocks.
315
+ #
316
+ class BlockParticipantContext
317
+ attr_reader :blocks
318
+ def initialize
319
+ @blocks = {}
320
+ end
321
+ def method_missing(m, *args, &block)
322
+ @blocks[m.to_s] = block.to_raw_source
323
+ end
324
+ end
325
+
326
+ # If the given block is nil, will return {}, else tries to determine
327
+ # if it's a single "on_workitem" block or a block that has sub-blocks,
328
+ # like in
329
+ #
330
+ # dashboard.register 'toto' do
331
+ # on_workitem do
332
+ # puts "hey I'm toto"
333
+ # end
334
+ # accept? do
335
+ # workitem.fields.length > 3
336
+ # end
337
+ # end
338
+ #
339
+ def extract_blocks(block)
340
+
341
+ return {} unless block
342
+
343
+ source = block.to_raw_source
344
+ tree = Ruote.parse_ruby(source)
345
+
346
+ multi =
347
+ tree[0, 3] == [ :iter, [ :call, nil, :proc, [ :arglist ] ], nil ] &&
348
+ tree[3].is_a?(Array) &&
349
+ tree[3].first == :block &&
350
+ tree[3][1..-1].all? { |e|
351
+ e[0] == :iter &&
352
+ e[2] == nil &&
353
+ e[1][0, 2] == [ :call, nil ] &&
354
+ e[1][3] == [ :arglist ]
355
+ }
356
+
357
+ if multi
358
+ bpc = BlockParticipantContext.new
359
+ bpc.instance_eval(&block)
360
+ bpc.blocks
361
+ else
362
+ { 'on_workitem' => source }
363
+ end
364
+ end
365
+
271
366
  # Fetches and returns the participant list in the storage.
272
367
  #
273
368
  def get_list
@@ -302,13 +397,13 @@ module Ruote
302
397
  attr_accessor :regex, :classname, :options
303
398
 
304
399
  def initialize(a)
400
+
305
401
  @regex = a.first
306
- if a.last.is_a?(Array)
307
- @classname = a.last.first
308
- @options = a.last.last
402
+
403
+ @classname, @options = if a.last.is_a?(Array)
404
+ [ a.last.first, a.last.last ]
309
405
  else
310
- @classname = a.last
311
- @options = nil
406
+ [ a.last, nil ]
312
407
  end
313
408
  end
314
409
 
@@ -328,39 +423,49 @@ module Ruote
328
423
  #
329
424
  def self.read(elt)
330
425
 
331
- return elt.to_a if elt.is_a?(ParticipantEntry)
426
+ case elt
332
427
 
333
- if elt.is_a?(Hash)
428
+ when ParticipantEntry
334
429
 
335
- options = elt['options'] || elt.reject { |k, v|
336
- %w[ name regex regexp class classname ].include?(k)
337
- }
430
+ elt.to_a
338
431
 
339
- name = elt.find { |k, v| v == nil }
340
- if name
341
- name = name.first
342
- elt.delete(name)
343
- options.delete(name)
344
- end
345
- name = name || elt['name']
346
- name = Ruote.regex_or_s(name)
432
+ when Hash
347
433
 
348
- regex = name
349
- unless name
350
- regex = Ruote.regex_or_s(elt['regex'] || elt['regexp'])
351
- regex = regex.is_a?(String) ? Regexp.new(regex) : regex
352
- end
434
+ options = elt['options'] || elt.reject { |k, v|
435
+ %w[ name regex regexp class classname ].include?(k)
436
+ }
353
437
 
354
- klass = elt['classname'] || elt['class']
438
+ name, _ = elt.find { |k, v| v == nil }
439
+ if name
440
+ elt.delete(name)
441
+ options.delete(name)
442
+ end
443
+ name = name || elt['name']
444
+ name = Ruote.regex_or_s(name)
355
445
 
356
- return [ regex, [ klass, options ] ]
357
- end
446
+ regex = name
447
+ if name.nil?
448
+ regex = Ruote.regex_or_s(elt['regex'] || elt['regexp'])
449
+ regex = regex.is_a?(String) ? Regexp.new(regex) : regex
450
+ end
451
+
452
+ klass = (elt['classname'] || elt['class']).to_s
358
453
 
359
- # else elt is a Array
454
+ [ regex, [ klass, options ] ]
360
455
 
361
- return [ Ruote.regex_or_s(elt[0]), [ elt[1], elt[2] ] ] if elt.size == 3
456
+ when Array
362
457
 
363
- [ Ruote.regex_or_s(elt[0]), elt[1] ]
458
+ if elt.size == 3
459
+ [ Ruote.regex_or_s(elt[0]), [ elt[1].to_s, elt[2] ] ]
460
+ else
461
+ [ Ruote.regex_or_s(elt[0]), elt[1] ]
462
+ end
463
+
464
+ else
465
+
466
+ raise ArgumentError.new(
467
+ "cannot read participant out of #{elt.inspect} (#{elt.class})")
468
+ end
364
469
  end
365
470
  end
366
471
  end