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
@@ -33,8 +33,8 @@ module Ruote
33
33
  #
34
34
  # opts = {}
35
35
  #
36
- # engine =
37
- # Ruote::Engine.new(
36
+ # dashboard =
37
+ # Ruote::Dashboard.new(
38
38
  # Ruote::Worker.new(
39
39
  # Ruote::CompositeStorage.new(
40
40
  # Ruote::FsStorage.new('ruote_work', opts),
@@ -51,58 +51,58 @@ module Ruote
51
51
 
52
52
  @default_storage = default_storage
53
53
  @storages = storages
54
-
55
- prepare_base_methods
56
- end
57
-
58
- def put(doc, opts={})
59
-
60
- storage(doc['type']).put(doc, opts)
61
- end
62
-
63
- def get(type, key)
64
-
65
- storage(type).get(type, key)
66
- end
67
-
68
- def delete(doc)
69
-
70
- storage(doc['type']).delete(doc)
71
- end
72
-
73
- def get_many(type, key=nil, opts={})
74
-
75
- storage(type).get_many(type, key, opts)
76
- end
77
-
78
- def ids(type)
79
-
80
- storage(type).ids(type)
81
54
  end
82
55
 
83
- def purge!
56
+ # A class method 'delegate', to tell this storage how to deal with
57
+ # each method composing a storage.
58
+ #
59
+ # Followed by a list of 'delegations'.
60
+ #
61
+ def self.delegate(method_name, type=nil)
84
62
 
85
- TYPES.collect { |t| storage(t) }.uniq.each { |s| s.purge! }
63
+ if type == nil
64
+ define_method(method_name) do |*args|
65
+ storage_for(args.first['type']).send(method_name, *args)
66
+ end
67
+ elsif type.is_a?(Fixnum)
68
+ define_method(method_name) do |*args|
69
+ storage_for(args[type]).send(method_name, *args)
70
+ end
71
+ else
72
+ type = type.to_s
73
+ define_method(method_name) do |*args|
74
+ storage_for(type).send(method_name, *args)
75
+ end
76
+ end
86
77
  end
87
78
 
88
- def purge_type!(type)
89
-
90
- storage(type).purge_type!(type)
79
+ delegate :put
80
+ delegate :get, 0
81
+ delegate :get_many, 0
82
+ delegate :delete
83
+
84
+ delegate :reserve
85
+ delegate :ids, 0
86
+ delegate :purge_type!, 0
87
+ delegate :empty?, 0
88
+
89
+ delegate :put_msg, :msgs
90
+ delegate :get_msgs, :msgs
91
+ delegate :put_schedule, :schedules
92
+ delegate :get_schedules, :schedules
93
+ delegate :delete_schedule, :schedules
94
+ delegate :find_root_expression, :expressions
95
+ delegate :expression_wfids, :expressions
96
+ delegate :get_trackers, :variables
97
+ delegate :get_engine_variable, :variables
98
+ delegate :put_engine_variable, :variables
99
+
100
+ # The dilemma for the CompositeStorage with add_type is "to which
101
+ # real storage should the new type get added". The solution: do nothing.
102
+ #
103
+ def add_type(type)
91
104
  end
92
105
 
93
- #def add_type (type)
94
- #end
95
-
96
- protected
97
-
98
- STORAGE_BASE_METHODS = {
99
- 'put_msg' => 'msgs',
100
- 'get_msgs' => 'msgs',
101
- 'find_root_expression' => 'expressions',
102
- 'get_schedules' => 'schedules',
103
- 'put_schedule' => 'schedules'
104
- }
105
-
106
106
  TYPES = %w[
107
107
  variables
108
108
  msgs
@@ -113,19 +113,9 @@ module Ruote
113
113
  workitems
114
114
  ]
115
115
 
116
- def prepare_base_methods
117
-
118
- singleton = class << self; self; end
119
-
120
- STORAGE_BASE_METHODS.each do |method, type|
121
-
122
- singleton.send(:define_method, method) do |*args|
123
- storage(type).send(method, *args)
124
- end
125
- end
126
- end
116
+ protected
127
117
 
128
- def storage(type)
118
+ def storage_for(type)
129
119
 
130
120
  @storages[type] || @default_storage
131
121
  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
@@ -22,18 +22,9 @@
22
22
  # Made in Japan.
23
23
  #++
24
24
 
25
- begin
26
- require 'yajl'
27
- rescue LoadError
28
- require 'json'
29
- end
30
- # gem install yajl-ruby OR json OR json_pure OR json-jruby
31
-
32
- require 'rufus/json'
33
- Rufus::Json.detect_backend
34
25
 
35
- require 'rufus/cloche'
36
- # gem install rufus-cloche
26
+ require 'rufus-json/automatic'
27
+ require 'rufus-cloche'
37
28
 
38
29
  require 'ruote/storage/base'
39
30
 
@@ -59,19 +50,31 @@ module Ruote
59
50
  #
60
51
  def initialize(dir, options={})
61
52
 
53
+ if dir.is_a?(Hash) && options == {}
54
+ options = dir
55
+ dir = options.delete('dir')
56
+ end
57
+
62
58
  FileUtils.mkdir_p(dir)
63
59
 
64
60
  @cloche = Rufus::Cloche.new(
65
61
  :dir => dir, :nolock => options['cloche_nolock'])
66
62
 
67
- @options = options
63
+ replace_engine_configuration(options)
64
+ end
65
+
66
+ def dir
68
67
 
69
- @cloche.put(@options.merge('type' => 'configurations', '_id' => 'engine'))
68
+ @cloche.dir
70
69
  end
71
70
 
72
71
  def put(doc, opts={})
73
72
 
74
- @cloche.put(doc.merge!('put_at' => Ruote.now_to_utc_s), opts)
73
+ doc = doc.send(
74
+ opts[:update_rev] ? 'merge!' : 'merge',
75
+ 'put_at' => Ruote.now_to_utc_s)
76
+
77
+ @cloche.put(doc, opts)
75
78
  end
76
79
 
77
80
  def get(type, key)
@@ -86,13 +89,13 @@ module Ruote
86
89
 
87
90
  def get_many(type, key=nil, opts={})
88
91
 
89
- if key
90
- key = Array(key)
91
- key = key.map { |k| "!#{k}" } if key.first.is_a?(String)
92
- end
93
- # assuming /!#{wfid}$/...
92
+ keys = key ? Array(key) : nil
93
+
94
+ keys = keys.map { |k|
95
+ type == 'schedules' ? /!#{k}-\d+$/ : "!#{k}"
96
+ } if keys && keys.first.is_a?(String)
94
97
 
95
- @cloche.get_many(type, key, opts)
98
+ @cloche.get_many(type, keys, opts)
96
99
  end
97
100
 
98
101
  def ids(type)
@@ -107,7 +110,7 @@ module Ruote
107
110
  FileUtils.rm_rf(@cloche.dir)
108
111
  end
109
112
 
110
- # No need for that here (FsStorage adds type on the fly).
113
+ # No need for that here (FsStorage can add types on the fly).
111
114
  #
112
115
  def add_type(type)
113
116
  end
@@ -117,18 +120,6 @@ module Ruote
117
120
  @cloche.purge_type!(type)
118
121
  end
119
122
 
120
- def dump(type)
121
-
122
- s = "=== #{type} ===\n"
123
-
124
- @cloche.get_many(type).inject(s) do |s1, e|
125
- s1 << "\n"
126
- e.keys.sort.inject(s1) do |s2, k|
127
- s2 << " #{k} => #{e[k].inspect}\n"
128
- end
129
- end
130
- end
131
-
132
123
  # Shuts this storage down.
133
124
  #
134
125
  def shutdown
@@ -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
@@ -30,8 +30,11 @@ require 'monitor'
30
30
 
31
31
  module Ruote
32
32
 
33
+ #
33
34
  # An in-memory storage.
34
35
  #
36
+ # Useful for testing or for transient engines.
37
+ #
35
38
  class HashStorage
36
39
 
37
40
  include StorageBase
@@ -47,14 +50,13 @@ module Ruote
47
50
  @options = options
48
51
 
49
52
  purge!
53
+ # which initializes @h
50
54
 
51
- put(options.merge('type' => 'configurations', '_id' => 'engine'))
55
+ replace_engine_configuration(options)
52
56
  end
53
57
 
54
58
  def put(doc, opts={})
55
59
 
56
- i = @h.size
57
-
58
60
  synchronize do
59
61
 
60
62
  pre = get(doc['type'], doc['_id'])
@@ -68,8 +70,7 @@ module Ruote
68
70
  end
69
71
 
70
72
  doc = if opts[:update_rev]
71
- doc['_rev'] = pre ? pre['_rev'] : -1
72
- doc
73
+ doc.merge!('_rev' => pre ? pre['_rev'] : -1)
73
74
  else
74
75
  doc.merge('_rev' => doc['_rev'] || -1)
75
76
  end
@@ -82,12 +83,12 @@ module Ruote
82
83
  nil
83
84
  end
84
85
 
85
- rescue => e
86
- puts "=" * 80
87
- File.open('doc.json', 'wb') do |f|
88
- f.puts Rufus::Json.pretty_encode(doc)
89
- end
90
- raise e
86
+ #rescue => e
87
+ # puts "=" * 80
88
+ # File.open('doc.json', 'wb') do |f|
89
+ # f.puts Rufus::Json.pretty_encode(doc)
90
+ # end
91
+ # raise e
91
92
  end
92
93
 
93
94
  def get(type, key)
@@ -125,19 +126,16 @@ module Ruote
125
126
 
126
127
  synchronize do
127
128
 
128
- keys = key ?
129
- Array(key).map { |k| k.is_a?(String) ? "!#{k}" : k } : nil
130
-
131
- docs = keys ?
132
- @h[type].values.select { |doc|
133
- Ruote::StorageBase.key_match?(keys, doc)
134
- } :
129
+ docs = if key
130
+ keys = Array(key).map { |k| k.is_a?(String) ? "!#{k}" : k }
131
+ @h[type].values.select { |doc| key_match?(type, keys, doc) }
132
+ else
135
133
  @h[type].values
136
-
137
- docs = docs.sort_by { |d| d['_id'] }
134
+ end
138
135
 
139
136
  return docs.size if opts[:count]
140
137
 
138
+ docs = docs.sort_by { |d| d['_id'] }
141
139
  docs = docs.reverse if opts[:descending]
142
140
 
143
141
  skip = opts[:skip] || 0
@@ -154,6 +152,24 @@ module Ruote
154
152
  @h[type].keys.sort
155
153
  end
156
154
 
155
+ #--
156
+ # keeping it commented out... using it for documentation efforts
157
+ #class NoisyHash < Hash
158
+ # def initialize(type)
159
+ # @type = type
160
+ # super()
161
+ # end
162
+ # def []=(k, v)
163
+ # puts " + #{@type}.put #{k} #{v['_rev']}"
164
+ # super
165
+ # end
166
+ # def delete(k)
167
+ # puts " - #{@type}.del #{k} "
168
+ # super
169
+ # end
170
+ #end
171
+ #++
172
+
157
173
  # Purges the storage completely.
158
174
  #
159
175
  def purge!
@@ -169,9 +185,8 @@ module Ruote
169
185
  configurations
170
186
  workitems
171
187
 
172
- ].inject({}) { |h, k|
188
+ ].each_with_object({}) { |k, h|
173
189
  h[k] = {}
174
- h
175
190
  }
176
191
 
177
192
  @h['configurations']['engine'] = @options
@@ -187,19 +202,6 @@ module Ruote
187
202
  @h[type] = {}
188
203
  end
189
204
 
190
- def dump(type)
191
-
192
- s = "=== #{type} ===\n"
193
-
194
- @h[type].inject(s) do |s1, (k, v)|
195
- s1 << "\n"
196
- s1 << "#{k} :\n"
197
- v.keys.sort.inject(s1) do |s2, k1|
198
- s2 << " #{k1} => #{v[k1].inspect}\n"
199
- end
200
- end
201
- end
202
-
203
205
  # Shuts this storage down.
204
206
  #
205
207
  def shutdown
@@ -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
@@ -42,48 +42,28 @@ module Ruote
42
42
  def handle(msg)
43
43
 
44
44
  case msg['action']
45
- when 'dispatch'
46
- dispatch(msg)
47
- when 'dispatch_cancel'
48
- dispatch_cancel(msg)
49
- else
50
- # simply discard the message
45
+ when 'dispatch' then dispatch(msg)
46
+ when 'dispatch_cancel' then dispatch_cancel(msg)
47
+ when 'dispatch_pause', 'dispatch_resume' then dispatch_pause(msg)
48
+ else # simply discard the message
51
49
  end
52
50
  end
53
51
 
54
52
  protected
55
53
 
56
- def dispatch_cancel(msg)
57
-
58
- flavour = msg['flavour']
59
-
60
- participant = @context.plist.instantiate(msg['participant'])
61
-
62
- begin
63
- participant.cancel(Ruote::FlowExpressionId.new(msg['fei']), flavour)
64
- rescue => e
65
- raise(e) if flavour != 'kill'
66
- end
67
-
68
- @context.storage.put_msg(
69
- 'reply',
70
- 'fei' => msg['fei'],
71
- 'workitem' => msg['workitem'])
72
- end
73
-
74
54
  def dispatch(msg)
75
55
 
76
56
  participant = @context.plist.lookup(
77
57
  msg['participant'] || msg['participant_name'], msg['workitem'])
78
58
 
79
- if do_not_thread(participant, msg)
59
+ if (@context['participant_threads_enabled'] == false) || do_not_thread?(participant, msg)
80
60
  do_dispatch(participant, msg)
81
61
  else
82
62
  do_threaded_dispatch(participant, msg)
83
63
  end
84
64
  end
85
65
 
86
- # The actual dispatching (call to Participant#consume).
66
+ # The actual dispatching (call to Participant#consume or #on_workitem).
87
67
  #
88
68
  def do_dispatch(participant, msg)
89
69
 
@@ -91,12 +71,14 @@ module Ruote
91
71
 
92
72
  workitem.fields['dispatched_at'] = Ruote.now_to_utc_s
93
73
 
94
- participant.consume(workitem)
74
+ Ruote.participant_send(
75
+ participant, [ :on_workitem, :consume ], 'workitem' => workitem)
95
76
 
96
77
  @context.storage.put_msg(
97
78
  'dispatched',
98
79
  'fei' => msg['fei'],
99
- 'participant_name' => workitem.participant_name)
80
+ 'participant_name' => workitem.participant_name,
81
+ 'workitem' => msg['workitem'])
100
82
  # once the consume is done, asynchronously flag the
101
83
  # participant expression as 'dispatched'
102
84
  end
@@ -129,16 +111,103 @@ module Ruote
129
111
  # Returns true if the participant doesn't want the #consume to happen
130
112
  # in a new Thread.
131
113
  #
132
- def do_not_thread(participant, msg)
114
+ def do_not_thread?(participant, msg)
133
115
 
134
- return false unless participant.respond_to?(:do_not_thread)
116
+ # :default => false makes participant_send return false if no method
117
+ # were found (else it would raise a NoMethodError)
135
118
 
136
- if participant.method(:do_not_thread).arity == 0
137
- participant.do_not_thread
138
- else
139
- participant.do_not_thread(Ruote::Workitem.new(msg['workitem']))
119
+ Ruote.participant_send(
120
+ participant,
121
+ [ :do_not_thread, :do_not_thread?, :dont_thread, :dont_thread? ],
122
+ 'workitem' => Ruote::Workitem.new(msg['workitem']), :default => false)
123
+ end
124
+
125
+ # Instantiates the participant and calls its cancel method.
126
+ #
127
+ def dispatch_cancel(msg)
128
+
129
+ flavour = msg['flavour']
130
+
131
+ participant = @context.plist.instantiate(msg['participant'])
132
+
133
+ result = begin
134
+
135
+ Ruote.participant_send(
136
+ participant,
137
+ [ :on_cancel, :cancel ],
138
+ 'fei' => Ruote::FlowExpressionId.new(msg['fei']),
139
+ 'flavour' => flavour)
140
+
141
+ rescue => e
142
+ raise(e) if flavour != 'kill'
140
143
  end
144
+
145
+ @context.storage.put_msg(
146
+ 'reply',
147
+ 'fei' => msg['fei'],
148
+ 'workitem' => msg['workitem']
149
+ ) if result != false
150
+ end
151
+
152
+ # Instantiates the participant and calls its on_pause (or on_resume) method.
153
+ #
154
+ def dispatch_pause(msg)
155
+
156
+ action = (msg['action'] == 'dispatch_resume' ? :on_resume : :on_pause)
157
+
158
+ participant = @context.plist.instantiate(
159
+ msg['participant'], :if_respond_to? => action)
160
+
161
+ return unless participant
162
+
163
+ Ruote.participant_send(
164
+ participant,
165
+ action,
166
+ 'fei' => Ruote::FlowExpressionId.new(msg['fei']), :default => false)
167
+ end
168
+ end
169
+
170
+ # Given a participant, a method name or an array of method names and
171
+ # a hash of arguments, will do its best to set the instance variables
172
+ # corresponding to the arguments (if possible) and to call the
173
+ # method with the right number of arguments...
174
+ #
175
+ # Made it a Ruote module method so that RevParticipant might use it
176
+ # independently.
177
+ #
178
+ # If the arguments hash contains a value keyed :default, that value is
179
+ # returned when none of the methods is responded to by the participant.
180
+ # Else if :default is not set or is set to nil, a NoMethodError.
181
+ #
182
+ def self.participant_send(participant, methods, arguments)
183
+
184
+ default = arguments.delete(:default)
185
+
186
+ # set instance variables if possible
187
+
188
+ arguments.each do |key, value|
189
+ setter = "#{key}="
190
+ participant.send(setter, value) if participant.respond_to?(setter)
141
191
  end
192
+
193
+ # call the method, with the right arity
194
+
195
+ Array(methods).each do |method|
196
+
197
+ next unless participant.respond_to?(method)
198
+
199
+ return participant.send(method) if participant.method(method).arity == 0
200
+
201
+ args = arguments.keys.sort.collect { |k| arguments[k] }
202
+ # luckily, our arg keys are in the alphabetical order (fei, flavour)
203
+
204
+ return participant.send(method, *args)
205
+ end
206
+
207
+ return default unless default == nil
208
+
209
+ raise NoMethodError.new(
210
+ "undefined method `#{methods.first}' for #{participant.class}")
142
211
  end
143
212
  end
144
213