ruote 2.1.7 → 2.1.8

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 (74) hide show
  1. data/CHANGELOG.txt +13 -0
  2. data/CREDITS.txt +2 -1
  3. data/Rakefile +4 -3
  4. data/TODO.txt +11 -1
  5. data/lib/ruote/exp/fe_concurrence.rb +26 -2
  6. data/lib/ruote/exp/fe_participant.rb +1 -1
  7. data/lib/ruote/exp/merge.rb +16 -9
  8. data/lib/ruote/fei.rb +1 -1
  9. data/lib/ruote/parser.rb +2 -1
  10. data/lib/ruote/part/smtp_participant.rb +22 -41
  11. data/lib/ruote/part/storage_participant.rb +20 -1
  12. data/lib/ruote/part/template.rb +34 -18
  13. data/lib/ruote/storage/base.rb +2 -20
  14. data/lib/ruote/storage/composite_storage.rb +134 -0
  15. data/lib/ruote/storage/fs_storage.rb +15 -1
  16. data/lib/ruote/util/dollar.rb +1 -0
  17. data/lib/ruote/util/misc.rb +5 -1
  18. data/lib/ruote/util/time.rb +13 -3
  19. data/lib/ruote/version.rb +1 -1
  20. data/lib/ruote/worker.rb +2 -2
  21. data/ruote.gemspec +18 -12
  22. data/test/bm/seq_thousand.rb +1 -1
  23. data/test/functional/base.rb +6 -8
  24. data/test/functional/crunner.rb +2 -0
  25. data/test/functional/eft_0_process_definition.rb +2 -2
  26. data/test/functional/eft_10_cancel_process.rb +2 -2
  27. data/test/functional/eft_11_wait.rb +3 -3
  28. data/test/functional/eft_12_listen.rb +1 -1
  29. data/test/functional/eft_13_iterator.rb +14 -14
  30. data/test/functional/eft_14_cursor.rb +12 -12
  31. data/test/functional/eft_15_loop.rb +2 -2
  32. data/test/functional/eft_16_if.rb +11 -15
  33. data/test/functional/eft_17_equals.rb +2 -2
  34. data/test/functional/eft_18_concurrent_iterator.rb +35 -8
  35. data/test/functional/eft_1_echo.rb +1 -1
  36. data/test/functional/eft_21_restore.rb +3 -3
  37. data/test/functional/eft_22_noop.rb +1 -1
  38. data/test/functional/eft_23_apply.rb +9 -9
  39. data/test/functional/eft_25_command.rb +1 -1
  40. data/test/functional/eft_27_inc.rb +12 -12
  41. data/test/functional/eft_28_when.rb +4 -4
  42. data/test/functional/eft_2_sequence.rb +3 -3
  43. data/test/functional/eft_3_participant.rb +5 -5
  44. data/test/functional/eft_4_set.rb +12 -12
  45. data/test/functional/eft_5_subprocess.rb +8 -8
  46. data/test/functional/eft_6_concurrence.rb +17 -4
  47. data/test/functional/eft_7_forget.rb +1 -1
  48. data/test/functional/eft_8_undo.rb +3 -3
  49. data/test/functional/ft_0_worker.rb +17 -1
  50. data/test/functional/ft_10_dollar.rb +9 -9
  51. data/test/functional/ft_11_recursion.rb +2 -2
  52. data/test/functional/ft_13_variables.rb +4 -4
  53. data/test/functional/ft_17_conditional.rb +5 -5
  54. data/test/functional/ft_19_alias.rb +1 -1
  55. data/test/functional/ft_1_process_status.rb +1 -1
  56. data/test/functional/ft_20_storage_participant.rb +2 -0
  57. data/test/functional/ft_22_process_definitions.rb +11 -4
  58. data/test/functional/ft_24_block_participants.rb +13 -4
  59. data/test/functional/ft_27_var_indirection.rb +5 -5
  60. data/test/functional/ft_28_null_noop_participants.rb +1 -1
  61. data/test/functional/ft_29_part_template.rb +4 -23
  62. data/test/functional/ft_30_smtp_participant.rb +50 -4
  63. data/test/functional/ft_32_fs_history.rb +4 -8
  64. data/test/functional/ft_33_participant_subprocess_priority.rb +1 -1
  65. data/test/functional/ft_36_storage_history.rb +2 -2
  66. data/test/functional/ft_5_on_error.rb +5 -5
  67. data/test/functional/ft_8_participant_consumption.rb +2 -2
  68. data/test/path_helper.rb +1 -1
  69. data/test/test_helper.rb +17 -0
  70. data/test/unit/storage.rb +2 -17
  71. data/test/unit/ut_19_part_template.rb +76 -0
  72. data/test/unit/ut_1_fei.rb +13 -0
  73. data/test/unit/ut_20_composite_storage.rb +34 -0
  74. metadata +111 -55
@@ -0,0 +1,134 @@
1
+ #--
2
+ # Copyright (c) 2005-2010, 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
+ require 'ruote/storage/base'
26
+
27
+
28
+ module Ruote
29
+
30
+ #
31
+ # This storage allows for mixing of storage implementation or simply
32
+ # mixing of storage physical backend.
33
+ #
34
+ # opts = {}
35
+ #
36
+ # engine =
37
+ # Ruote::Engine.new(
38
+ # Ruote::Worker.new(
39
+ # Ruote::CompositeStorage.new(
40
+ # Ruote::FsStorage.new('ruote_work', opts),
41
+ # 'msgs' => Ruote::HashStorage.new(opts))))
42
+ #
43
+ # In this example, everything goes to the FsStorage, except the messages
44
+ # (msgs) that go to an in-memory storage.
45
+ #
46
+ class CompositeStorage
47
+
48
+ include StorageBase
49
+
50
+ def initialize (default_storage, storages)
51
+
52
+ @default_storage = default_storage
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(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
+ end
82
+
83
+ def purge!
84
+
85
+ TYPES.collect { |t| storage(t) }.uniq.each { |s| s.purge! }
86
+ end
87
+
88
+ def purge_type! (type)
89
+
90
+ storage(type).purge_type!(type)
91
+ end
92
+
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
+ TYPES = %w[
107
+ variables
108
+ msgs
109
+ expressions
110
+ errors
111
+ schedules
112
+ configurations
113
+ workitems
114
+ ]
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
127
+
128
+ def storage (type)
129
+
130
+ @storages[type] || @default_storage
131
+ end
132
+ end
133
+ end
134
+
@@ -38,15 +38,29 @@ require 'rufus/cloche'
38
38
 
39
39
  module Ruote
40
40
 
41
+ # A basic FS-bound ruote storage. Leverages rufus-cloche
42
+ # (http://github.com/jmettraux/rufus-cloche).
43
+ #
44
+ # Warning : for JRuby 1.4.0 on Ubuntu, passing the cloche_nolock option set
45
+ # to true seems necessary.
46
+ # See http://groups.google.com/group/openwferu-users/t/d82516ed3bdd8f23
47
+ #
41
48
  class FsStorage
42
49
 
43
50
  include StorageBase
44
51
 
52
+ # Creates a FsStorage pointing to the given dir.
53
+ #
54
+ # The options are classical engine configuration, but the 'cloche_nolock'
55
+ # option is read by the storage and followed.
56
+ #
45
57
  def initialize (dir, options={})
46
58
 
47
59
  FileUtils.mkdir_p(dir)
48
60
 
49
- @cloche = Rufus::Cloche.new(:dir => dir)
61
+ @cloche = Rufus::Cloche.new(
62
+ :dir => dir, :nolock => options['cloche_nolock'])
63
+
50
64
  @options = options
51
65
 
52
66
  @cloche.put(@options.merge('type' => 'configurations', '_id' => 'engine'))
@@ -24,6 +24,7 @@
24
24
 
25
25
 
26
26
  require 'rufus/dollar' # gem 'rufus-dollar'
27
+ require 'ruote/util/lookup'
27
28
  require 'ruote/util/treechecker'
28
29
 
29
30
 
@@ -27,7 +27,11 @@ module Ruote
27
27
 
28
28
  # Will be set to true if the Ruby runtime is on Windows
29
29
  #
30
- WIN = RUBY_PLATFORM.match(/mswin|mingw/) != nil
30
+ WIN = (RUBY_PLATFORM.match(/mswin|mingw/) != nil)
31
+
32
+ # Will be set to true if the Ruby runtime is JRuby
33
+ #
34
+ JAVA = (RUBY_PLATFORM.match(/java/) != nil)
31
35
 
32
36
  # Prints the current call stack to stdout
33
37
  #
@@ -75,9 +75,7 @@ module Ruote
75
75
  #
76
76
  # duration
77
77
 
78
- duration = s.to_f rescue Rufus.parse_time_string(s)
79
-
80
- Time.now.utc.to_f + duration
78
+ Time.now.utc.to_f + Rufus.parse_time_string(s)
81
79
  end
82
80
 
83
81
  case at
@@ -86,5 +84,17 @@ module Ruote
86
84
  else at
87
85
  end
88
86
  end
87
+
88
+ # Waiting for a better implementation of it in rufus-scheduler 2.0.4
89
+ #
90
+ def self.is_cron_string (s)
91
+
92
+ ss = s.split(' ')
93
+
94
+ return false if ss.size < 5 || ss.size > 6
95
+ return false if s.match(/\d{4}/)
96
+
97
+ true
98
+ end
89
99
  end
90
100
 
data/lib/ruote/version.rb CHANGED
@@ -23,6 +23,6 @@
23
23
  #++
24
24
 
25
25
  module Ruote
26
- VERSION = '2.1.7'
26
+ VERSION = '2.1.8'
27
27
  end
28
28
 
data/lib/ruote/worker.rb CHANGED
@@ -201,7 +201,7 @@ module Ruote
201
201
 
202
202
  msg = Ruote.fulldup(schedule['msg'])
203
203
 
204
- return false unless @storage.reserve(schedule)
204
+ return false unless @storage.delete(schedule).nil?
205
205
 
206
206
  @storage.put_msg(msg.delete('action'), msg)
207
207
 
@@ -212,7 +212,7 @@ module Ruote
212
212
 
213
213
  return false if cannot_handle(msg)
214
214
 
215
- return false unless @storage.reserve(msg)
215
+ return false unless @storage.delete(msg).nil?
216
216
 
217
217
  begin
218
218
 
data/ruote.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruote}
8
- s.version = "2.1.7"
8
+ s.version = "2.1.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["John Mettraux", "Kenneth Kalmer", "Torsten Schoenebaum"]
12
- s.date = %q{2010-02-15}
12
+ s.date = %q{2010-03-15}
13
13
  s.description = %q{
14
14
  ruote is an open source ruby workflow engine.
15
15
  }
@@ -100,6 +100,7 @@ ruote is an open source ruby workflow engine.
100
100
  "lib/ruote/participant.rb",
101
101
  "lib/ruote/receiver/base.rb",
102
102
  "lib/ruote/storage/base.rb",
103
+ "lib/ruote/storage/composite_storage.rb",
103
104
  "lib/ruote/storage/fs_storage.rb",
104
105
  "lib/ruote/storage/hash_storage.rb",
105
106
  "lib/ruote/subprocess.rb",
@@ -226,7 +227,9 @@ ruote is an open source ruby workflow engine.
226
227
  "test/unit/ut_15_util.rb",
227
228
  "test/unit/ut_16_parser.rb",
228
229
  "test/unit/ut_18_engine.rb",
230
+ "test/unit/ut_19_part_template.rb",
229
231
  "test/unit/ut_1_fei.rb",
232
+ "test/unit/ut_20_composite_storage.rb",
230
233
  "test/unit/ut_2_wfidgen.rb",
231
234
  "test/unit/ut_3_wait_logger.rb",
232
235
  "test/unit/ut_4_expmap.rb",
@@ -240,7 +243,7 @@ ruote is an open source ruby workflow engine.
240
243
  s.rdoc_options = ["--charset=UTF-8"]
241
244
  s.require_paths = ["lib"]
242
245
  s.rubyforge_project = %q{ruote}
243
- s.rubygems_version = %q{1.3.5}
246
+ s.rubygems_version = %q{1.3.6}
244
247
  s.summary = %q{an open source ruby workflow engine}
245
248
  s.test_files = [
246
249
  "test/test.rb"
@@ -252,41 +255,44 @@ ruote is an open source ruby workflow engine.
252
255
 
253
256
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
254
257
  s.add_runtime_dependency(%q<rufus-json>, [">= 0.2.0"])
255
- s.add_runtime_dependency(%q<rufus-cloche>, [">= 0.1.14"])
258
+ s.add_runtime_dependency(%q<rufus-cloche>, [">= 0.1.16"])
256
259
  s.add_runtime_dependency(%q<rufus-dollar>, [">= 0"])
257
260
  s.add_runtime_dependency(%q<rufus-lru>, [">= 0"])
258
261
  s.add_runtime_dependency(%q<rufus-mnemo>, [">= 1.1.0"])
259
- s.add_runtime_dependency(%q<rufus-scheduler>, [">= 2.0.3"])
262
+ s.add_runtime_dependency(%q<rufus-scheduler>, [">= 2.0.5"])
260
263
  s.add_runtime_dependency(%q<rufus-treechecker>, [">= 1.0.3"])
261
- s.add_development_dependency(%q<json>, [">= 0"])
264
+ s.add_development_dependency(%q<rake>, [">= 0"])
262
265
  s.add_development_dependency(%q<yard>, [">= 0"])
266
+ s.add_development_dependency(%q<json>, [">= 0"])
263
267
  s.add_development_dependency(%q<builder>, [">= 0"])
264
268
  s.add_development_dependency(%q<mailtrap>, [">= 0"])
265
269
  s.add_development_dependency(%q<jeweler>, [">= 0"])
266
270
  else
267
271
  s.add_dependency(%q<rufus-json>, [">= 0.2.0"])
268
- s.add_dependency(%q<rufus-cloche>, [">= 0.1.14"])
272
+ s.add_dependency(%q<rufus-cloche>, [">= 0.1.16"])
269
273
  s.add_dependency(%q<rufus-dollar>, [">= 0"])
270
274
  s.add_dependency(%q<rufus-lru>, [">= 0"])
271
275
  s.add_dependency(%q<rufus-mnemo>, [">= 1.1.0"])
272
- s.add_dependency(%q<rufus-scheduler>, [">= 2.0.3"])
276
+ s.add_dependency(%q<rufus-scheduler>, [">= 2.0.5"])
273
277
  s.add_dependency(%q<rufus-treechecker>, [">= 1.0.3"])
274
- s.add_dependency(%q<json>, [">= 0"])
278
+ s.add_dependency(%q<rake>, [">= 0"])
275
279
  s.add_dependency(%q<yard>, [">= 0"])
280
+ s.add_dependency(%q<json>, [">= 0"])
276
281
  s.add_dependency(%q<builder>, [">= 0"])
277
282
  s.add_dependency(%q<mailtrap>, [">= 0"])
278
283
  s.add_dependency(%q<jeweler>, [">= 0"])
279
284
  end
280
285
  else
281
286
  s.add_dependency(%q<rufus-json>, [">= 0.2.0"])
282
- s.add_dependency(%q<rufus-cloche>, [">= 0.1.14"])
287
+ s.add_dependency(%q<rufus-cloche>, [">= 0.1.16"])
283
288
  s.add_dependency(%q<rufus-dollar>, [">= 0"])
284
289
  s.add_dependency(%q<rufus-lru>, [">= 0"])
285
290
  s.add_dependency(%q<rufus-mnemo>, [">= 1.1.0"])
286
- s.add_dependency(%q<rufus-scheduler>, [">= 2.0.3"])
291
+ s.add_dependency(%q<rufus-scheduler>, [">= 2.0.5"])
287
292
  s.add_dependency(%q<rufus-treechecker>, [">= 1.0.3"])
288
- s.add_dependency(%q<json>, [">= 0"])
293
+ s.add_dependency(%q<rake>, [">= 0"])
289
294
  s.add_dependency(%q<yard>, [">= 0"])
295
+ s.add_dependency(%q<json>, [">= 0"])
290
296
  s.add_dependency(%q<builder>, [">= 0"])
291
297
  s.add_dependency(%q<mailtrap>, [">= 0"])
292
298
  s.add_dependency(%q<jeweler>, [">= 0"])
@@ -25,7 +25,7 @@ class BmSeqThousandTest < Test::Unit::TestCase
25
25
 
26
26
  noisy
27
27
 
28
- assert_trace pdef, [ 'a' ] * n
28
+ assert_trace [ 'a' ] * n, pdef
29
29
  end
30
30
  end
31
31
 
@@ -51,16 +51,14 @@ module FunctionalBase
51
51
  assert_equal count, c
52
52
  end
53
53
 
54
- # assert_trace(pdef, *expected_traces)
55
- # assert_trace(pdef, fields, *expected_traces)
54
+ # assert_trace(*expected_traces, pdef)
55
+ # assert_trace(*expected_traces, fields, pdef)
56
56
  #
57
- def assert_trace (pdef, *expected_traces)
57
+ def assert_trace (*args)
58
58
 
59
- fields = expected_traces.first.is_a?(Hash) ? expected_traces.shift : {}
60
-
61
- expected_traces = expected_traces.collect do |et|
62
- et.is_a?(Array) ? et.join("\n") : et
63
- end
59
+ pdef = args.pop
60
+ fields = args.last.is_a?(Hash) ? args.pop : {}
61
+ expected_traces = args.collect { |et| et.is_a?(Array) ? et.join("\n") : et }
64
62
 
65
63
  wfid = @engine.launch(pdef, fields)
66
64
 
@@ -4,6 +4,8 @@ tnumber = ARGV.find { |a| a.match(/^\d+/) } || 2
4
4
 
5
5
  i = 0
6
6
 
7
+ puts `ruby -v`
8
+
7
9
  loop do
8
10
 
9
11
  t = Dir["test/functional/ct_#{tnumber}_*.rb"].first
@@ -16,8 +16,8 @@ class EftProcessDefinitionTest < Test::Unit::TestCase
16
16
  def test_empty_procdef
17
17
 
18
18
  assert_trace(
19
- Ruote.define(:name => 'test_1') { },
20
- '')
19
+ '',
20
+ Ruote.define(:name => 'test_1') { })
21
21
  end
22
22
 
23
23
  def test_sub_definition
@@ -23,7 +23,7 @@ class EftCancelProcessTest < Test::Unit::TestCase
23
23
 
24
24
  #noisy
25
25
 
26
- assert_trace(pdef, 'a')
26
+ assert_trace('a', pdef)
27
27
 
28
28
  #assert_equal 3, logger.log.select { |e| e[1] == :entered_tag }.size
29
29
  end
@@ -40,7 +40,7 @@ class EftCancelProcessTest < Test::Unit::TestCase
40
40
 
41
41
  #noisy
42
42
 
43
- assert_trace(pdef, "a\nb")
43
+ assert_trace("a\nb", pdef)
44
44
  end
45
45
  end
46
46
 
@@ -27,7 +27,7 @@ class EftWaitTest < Test::Unit::TestCase
27
27
  ts = []
28
28
  @engine.register_participant(:alpha) { ts << Time.now }
29
29
 
30
- assert_trace pdef, 'done.'
30
+ assert_trace 'done.', pdef
31
31
 
32
32
  #p [ ts[1].sec, ts[0].sec ]
33
33
  assert [ 2, 3 ].include?((ts[1].sec - ts[0].sec) % 60)
@@ -73,7 +73,7 @@ class EftWaitTest < Test::Unit::TestCase
73
73
  ts = []
74
74
  @engine.register_participant(:alpha) { ts << Time.now }
75
75
 
76
- assert_trace pdef, 'done.'
76
+ assert_trace 'done.', pdef
77
77
 
78
78
  #p ts
79
79
  assert ts[1] - ts[0] > 1.0, "#{ts[1] - ts[0]} should be > 1.0"
@@ -91,7 +91,7 @@ class EftWaitTest < Test::Unit::TestCase
91
91
 
92
92
  #noisy
93
93
 
94
- assert_trace pdef, %w[ a b ]
94
+ assert_trace %w[ a b ], pdef
95
95
  end
96
96
  end
97
97
 
@@ -148,7 +148,7 @@ class EftListenTest < Test::Unit::TestCase
148
148
  @tracer << "other:#{wi.fields['other']}\n"
149
149
  end
150
150
 
151
- assert_trace(pdef, "alpha\nname:William Mandella other:nothing")
151
+ assert_trace("alpha\nname:William Mandella other:nothing", pdef)
152
152
  end
153
153
 
154
154
  def test_where