ruote 2.1.9 → 2.1.10

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 (81) hide show
  1. data/CHANGELOG.txt +32 -0
  2. data/CREDITS.txt +3 -0
  3. data/Rakefile +4 -4
  4. data/TODO.txt +55 -11
  5. data/examples/barley.rb +2 -1
  6. data/examples/flickr_report.rb +5 -6
  7. data/examples/web_first_page.rb +11 -0
  8. data/lib/ruote/context.rb +36 -13
  9. data/lib/ruote/engine.rb +88 -56
  10. data/lib/ruote/engine/process_error.rb +13 -0
  11. data/lib/ruote/engine/process_status.rb +33 -1
  12. data/lib/ruote/error_handler.rb +122 -0
  13. data/lib/ruote/evt/tracker.rb +27 -10
  14. data/lib/ruote/exp/fe_apply.rb +69 -0
  15. data/lib/ruote/exp/fe_participant.rb +33 -5
  16. data/lib/ruote/exp/flowexpression.rb +37 -5
  17. data/lib/ruote/exp/ro_persist.rb +8 -4
  18. data/lib/ruote/exp/ro_variables.rb +2 -2
  19. data/lib/ruote/fei.rb +59 -7
  20. data/lib/ruote/log/storage_history.rb +2 -0
  21. data/lib/ruote/log/test_logger.rb +28 -19
  22. data/lib/ruote/log/wait_logger.rb +4 -2
  23. data/lib/ruote/parser.rb +2 -1
  24. data/lib/ruote/part/dispatch_pool.rb +10 -10
  25. data/lib/ruote/part/engine_participant.rb +2 -2
  26. data/lib/ruote/part/local_participant.rb +99 -7
  27. data/lib/ruote/part/participant_list.rb +18 -7
  28. data/lib/ruote/part/storage_participant.rb +9 -6
  29. data/lib/ruote/receiver/base.rb +109 -10
  30. data/lib/ruote/storage/base.rb +118 -41
  31. data/lib/ruote/storage/fs_storage.rb +1 -0
  32. data/lib/ruote/storage/hash_storage.rb +2 -1
  33. data/lib/ruote/util/lookup.rb +22 -2
  34. data/lib/ruote/util/misc.rb +5 -5
  35. data/lib/ruote/version.rb +1 -1
  36. data/lib/ruote/worker.rb +50 -63
  37. data/lib/ruote/workitem.rb +64 -0
  38. data/ruote.gemspec +17 -12
  39. data/test/functional/base.rb +3 -1
  40. data/test/functional/concurrent_base.rb +35 -29
  41. data/test/functional/crunner.sh +19 -0
  42. data/test/functional/ct_0_concurrence.rb +17 -30
  43. data/test/functional/ct_1_iterator.rb +20 -17
  44. data/test/functional/ct_2_cancel.rb +32 -25
  45. data/test/functional/eft_12_listen.rb +2 -1
  46. data/test/functional/eft_23_apply.rb +23 -0
  47. data/test/functional/eft_3_participant.rb +27 -0
  48. data/test/functional/ft_11_recursion.rb +1 -1
  49. data/test/functional/ft_13_variables.rb +22 -0
  50. data/test/functional/ft_14_re_apply.rb +3 -0
  51. data/test/functional/ft_15_timeout.rb +1 -0
  52. data/test/functional/ft_20_storage_participant.rb +20 -2
  53. data/test/functional/ft_21_forget.rb +30 -0
  54. data/test/functional/ft_22_process_definitions.rb +2 -1
  55. data/test/functional/ft_24_block_participants.rb +1 -1
  56. data/test/functional/ft_25_receiver.rb +83 -1
  57. data/test/functional/ft_26_participant_timeout.rb +1 -1
  58. data/test/functional/ft_2_errors.rb +2 -5
  59. data/test/functional/ft_30_smtp_participant.rb +47 -45
  60. data/test/functional/ft_36_storage_history.rb +4 -4
  61. data/test/functional/ft_37_engine_participant.rb +14 -10
  62. data/test/functional/ft_38_participant_more.rb +178 -0
  63. data/test/functional/ft_39_wait_for.rb +100 -0
  64. data/test/functional/ft_40_participant_on_reply.rb +87 -0
  65. data/test/functional/ft_41_participants.rb +65 -0
  66. data/test/functional/ft_42_storage_copy.rb +67 -0
  67. data/test/functional/ft_5_on_error.rb +103 -0
  68. data/test/functional/ft_9_subprocesses.rb +2 -1
  69. data/test/functional/storage_helper.rb +5 -1
  70. data/test/functional/test.rb +4 -1
  71. data/test/functional/vertical.rb +46 -0
  72. data/test/unit/storage.rb +17 -1
  73. data/test/unit/storages.rb +27 -7
  74. data/test/unit/ut_11_lookup.rb +36 -0
  75. data/test/unit/ut_16_parser.rb +43 -0
  76. data/test/unit/ut_1_fei.rb +28 -1
  77. data/test/unit/ut_7_workitem.rb +23 -0
  78. metadata +67 -105
  79. data/lib/ruote/log/fs_history.rb +0 -182
  80. data/test/functional/ft_32_fs_history.rb +0 -188
  81. data/test/mpc_test.rb +0 -29
@@ -150,6 +150,7 @@ class FtTimeoutTest < Test::Unit::TestCase
150
150
  wait_for(:alpha)
151
151
 
152
152
  assert_equal 1, alpha.size
153
+ assert_not_nil alpha.first.fields['__timed_out__']
153
154
  end
154
155
 
155
156
  def test_deep_on_timeout_error
@@ -37,7 +37,6 @@ class FtStorageParticipantTest < Test::Unit::TestCase
37
37
  assert_equal Ruote::Workitem, wi.class
38
38
 
39
39
  wi = alpha[alpha.first.fei]
40
-
41
40
  assert_equal Ruote::Workitem, wi.class
42
41
 
43
42
  alpha.reply(wi)
@@ -131,6 +130,7 @@ class FtStorageParticipantTest < Test::Unit::TestCase
131
130
 
132
131
  assert_equal 2, @part.size
133
132
  #@part.by_participant('alpha').each { |wi| p wi }
133
+ assert_equal Ruote::Workitem, @part.by_participant('alpha').first.class
134
134
  assert_equal 1, @part.by_participant('alpha').size
135
135
  assert_equal 1, @part.by_participant('bravo').size
136
136
  end
@@ -140,6 +140,7 @@ class FtStorageParticipantTest < Test::Unit::TestCase
140
140
  prepare_al_bravo
141
141
 
142
142
  assert_equal 2, @part.size
143
+ assert_equal Ruote::Workitem, @part.by_field('place').first.class
143
144
  assert_equal 2, @part.by_field('place').size
144
145
  assert_equal 2, @part.by_field('character').size
145
146
  assert_equal 1, @part.by_field('adversary').size
@@ -174,7 +175,7 @@ class FtStorageParticipantTest < Test::Unit::TestCase
174
175
 
175
176
  assert_equal(
176
177
  1,
177
- @part.query(:place => 'heiankyou', :adversary => 'B').size)
178
+ @part.query(:adversary => 'B', :place => 'heiankyou').size)
178
179
 
179
180
  assert_equal 2, @part.query('place' => 'heiankyou', :limit => 2).size
180
181
  assert_equal 4, @part.query('place' => 'heiankyou', :limit => 20).size
@@ -291,5 +292,22 @@ class FtStorageParticipantTest < Test::Unit::TestCase
291
292
 
292
293
  assert_equal [], pa.all
293
294
  end
295
+
296
+ def test_various_args
297
+
298
+ sp = @engine.register_participant 'alpha', Ruote::StorageParticipant
299
+
300
+ wfid = @engine.launch(Ruote.process_definition { alpha })
301
+
302
+ wait_for(:alpha)
303
+
304
+ wi = sp.first
305
+
306
+ assert_equal wi, sp[wi]
307
+ assert_equal wi, sp[wi.fei]
308
+ assert_equal wi, sp[wi.to_h]
309
+ assert_equal wi, sp[wi.fei.to_h]
310
+ assert_equal wi, sp[wi.fei.to_storage_id]
311
+ end
294
312
  end
295
313
 
@@ -7,6 +7,8 @@
7
7
 
8
8
  require File.join(File.dirname(__FILE__), 'base')
9
9
 
10
+ require 'ruote/part/storage_participant'
11
+
10
12
 
11
13
  class FtForgetTest < Test::Unit::TestCase
12
14
  include FunctionalBase
@@ -38,5 +40,33 @@ class FtForgetTest < Test::Unit::TestCase
38
40
  assert_equal 1, logger.log.select { |e| e['action'] == 'ceased' }.size
39
41
  assert_equal 1, logger.log.select { |e| e['action'] == 'terminated' }.size
40
42
  end
43
+
44
+ def test_forgotten_tree
45
+
46
+ sp = @engine.register_participant :alpha, Ruote::StorageParticipant
47
+
48
+ pdef = Ruote.process_definition do
49
+ sequence do
50
+ alpha :forget => true
51
+ end
52
+ end
53
+
54
+ wfid = @engine.launch(pdef)
55
+
56
+ wait_for(wfid)
57
+
58
+ ps = @engine.process(wfid)
59
+
60
+ assert_not_nil ps
61
+ assert_equal 0, ps.errors.size
62
+ assert_equal 1, ps.expressions.size
63
+
64
+ fei = ps.expressions.first.fei
65
+ assert_equal fei, ps.root_expression_for(fei).fei
66
+
67
+ #puts "not sure..."
68
+ #p ps.original_tree
69
+ #p ps.current_tree
70
+ end
41
71
  end
42
72
 
@@ -51,7 +51,8 @@ class FtProcessDefinitionTest < Test::Unit::TestCase
51
51
 
52
52
  prev = Rufus::Json.backend
53
53
 
54
- require 'json'
54
+ #require 'json' # json 1.4.3 being buggy...
55
+ require 'json/pure'
55
56
  Rufus::Json.backend = :json
56
57
 
57
58
  #pdef = Ruote.process_definition :name => 'test' do
@@ -75,7 +75,7 @@ class FtBlockParticipantTest < Test::Unit::TestCase
75
75
  #assert_trace TEST_BLOCK, Ruote.time_to_utc_s(t)
76
76
 
77
77
  expected = if defined?(DataMapper)
78
- ''
78
+ DataMapper::VERSION >= '1.0.0' ? t.to_s : ''
79
79
  elsif Ruote::JAVA
80
80
  ''
81
81
  else
@@ -49,11 +49,38 @@ class FtReceiverTest < Test::Unit::TestCase
49
49
  end
50
50
 
51
51
  class MyReceiver < Ruote::Receiver
52
+ attr_reader :context
52
53
  end
53
54
 
54
- def test_my_receiver
55
+ def test_my_receiver_init
56
+
57
+ cid = @engine.context.object_id
58
+
59
+ receiver = MyReceiver.new(@engine)
60
+ assert_equal cid, receiver.context.object_id
61
+ assert_not_nil receiver.context.storage
62
+
63
+ receiver = MyReceiver.new(@engine.context)
64
+ assert_equal cid, receiver.context.object_id
65
+ assert_not_nil receiver.context.storage
66
+
67
+ receiver = MyReceiver.new(@engine.worker)
68
+ assert_equal cid, receiver.context.object_id
69
+ assert_not_nil receiver.context.storage
55
70
 
56
71
  receiver = MyReceiver.new(@engine.storage)
72
+ assert_equal cid, receiver.context.object_id
73
+ assert_not_nil receiver.context.storage
74
+
75
+ @engine.storage.instance_variable_set(:@context, nil)
76
+ receiver = MyReceiver.new(@engine.storage)
77
+ assert_not_equal cid, receiver.context.object_id
78
+ assert_not_nil receiver.context.storage
79
+ end
80
+
81
+ def test_my_receiver
82
+
83
+ receiver = MyReceiver.new(@engine.context)
57
84
 
58
85
  #noisy
59
86
 
@@ -91,5 +118,60 @@ class FtReceiverTest < Test::Unit::TestCase
91
118
  rcv = logger.log.select { |e| e['action'] == 'receive' }.first
92
119
  assert_equal 'Ruote::Engine', rcv['receiver']
93
120
  end
121
+
122
+ class MyOtherParticipant
123
+ def initialize (receiver)
124
+ @receiver = receiver
125
+ end
126
+ def consume (workitem)
127
+ @receiver.pass(workitem.to_h)
128
+ end
129
+ end
130
+ class MyOtherReceiver < Ruote::Receiver
131
+ def initialize (context, opts={})
132
+ super(context, opts)
133
+ @count = 0
134
+ end
135
+ def pass (workitem)
136
+ if @count < 1
137
+ @context.error_handler.action_handle(
138
+ 'dispatch', workitem['fei'], RuntimeError.new('something went wrong'))
139
+ else
140
+ reply(workitem)
141
+ end
142
+ @count = @count + 1
143
+ end
144
+ end
145
+
146
+ def test_receiver_triggered_dispatch_error
147
+
148
+ receiver = MyOtherReceiver.new(@engine)
149
+
150
+ @engine.register_participant :alpha, MyOtherParticipant.new(receiver)
151
+
152
+ pdef = Ruote.process_definition do
153
+ alpha
154
+ end
155
+
156
+ #noisy
157
+
158
+ wfid = @engine.launch(pdef)
159
+
160
+ wait_for(wfid)
161
+
162
+ ps = @engine.process(wfid)
163
+ err = ps.errors.first
164
+
165
+ assert_equal 1, ps.errors.size
166
+ assert_equal '#<RuntimeError: something went wrong>', err.message
167
+
168
+ @engine.replay_at_error(err)
169
+
170
+ wait_for(wfid)
171
+
172
+ ps = @engine.process(wfid)
173
+
174
+ assert_nil ps
175
+ end
94
176
  end
95
177
 
@@ -34,7 +34,7 @@ class FtParticipantTimeoutTest < Test::Unit::TestCase
34
34
  #noisy
35
35
 
36
36
  wfid = @engine.launch(pdef)
37
- wait_for(12)
37
+ wait_for(13)
38
38
 
39
39
  assert_equal 0, alpha.size
40
40
  assert_equal 1, bravo.size
@@ -153,15 +153,12 @@ class FtErrorsTest < Test::Unit::TestCase
153
153
 
154
154
  wait_for(wfid)
155
155
 
156
+ sleep 0.250 # grrr...
157
+
156
158
  ps = @engine.process(wfid)
157
159
 
158
160
  assert_equal 1, ps.errors.size
159
161
 
160
- #p ps.expressions.size
161
- #ps.expressions.each do |e|
162
- # p [ e.fei.to_s, e.class, e.state ]
163
- #end
164
-
165
162
  @engine.replay_at_error(ps.errors.first)
166
163
 
167
164
  wait_for(wfid)
@@ -24,49 +24,50 @@ class NftSmtpParticipantTest < Test::Unit::TestCase
24
24
  end
25
25
  end
26
26
 
27
- def _test_smtp
28
-
29
- return if Ruote::JAVA
30
-
31
- pdef = Ruote.process_definition :name => 'test' do
32
- sequence do
33
- set 'f:item' => 'cat food'
34
- alpha
35
- end
36
- end
37
-
38
- trapfile = Ruote::WIN ? 'ruote_mailtrap.txt' : '/tmp/ruote_mailtrap.txt'
39
- FileUtils.rm_f(trapfile)
40
-
41
- t = Thread.new do
42
- Trap.new('127.0.0.1', 2525, true, trapfile)
43
- end
44
- sleep 0.040
45
- # give it some time to start listening
46
-
47
- @engine.register_participant(
48
- :alpha,
49
- Ruote::SmtpParticipant.new(
50
- :server => '127.0.0.1',
51
- :port => 2525,
52
- :to => 'toto@cloudwhatever.ch',
53
- :from => 'john@outoftheblue.ch',
54
- :notification => true,
55
- :template => %{
56
- Hello, do you want ${f:item} ?
57
- }))
58
-
59
- #noisy
60
-
61
- wfid = @engine.launch(pdef)
62
-
63
- sleep 0.450
64
-
65
- assert_match(/cat food/, File.read(trapfile))
66
- assert_nil @engine.process(wfid)
67
-
68
- t.kill
69
- end
27
+ # def test_smtp
28
+ #
29
+ # return if Ruote::JAVA
30
+ #
31
+ # pdef = Ruote.process_definition :name => 'test' do
32
+ # sequence do
33
+ # set 'f:item' => 'cat food'
34
+ # alpha
35
+ # end
36
+ # end
37
+ #
38
+ # trapfile = Ruote::WIN ? 'ruote_mailtrap.txt' : '/tmp/ruote_mailtrap.txt'
39
+ # FileUtils.rm_f(trapfile)
40
+ #
41
+ # t = Thread.new do
42
+ # Trap.new('127.0.0.1', 2525, true, trapfile)
43
+ # end
44
+ # sleep 0.040
45
+ # # give it some time to start listening
46
+ #
47
+ # @engine.register_participant(
48
+ # :alpha,
49
+ # Ruote::SmtpParticipant.new(
50
+ # :server => '127.0.0.1',
51
+ # :port => 2525,
52
+ # :to => 'toto@cloudwhatever.ch',
53
+ # :from => 'john@outoftheblue.ch',
54
+ # :notification => true,
55
+ # :template => %{
56
+ # Hello, do you want ${f:item} ?
57
+ # }))
58
+ #
59
+ # #noisy
60
+ #
61
+ # wfid = @engine.launch(pdef)
62
+ #
63
+ # #sleep 0.450
64
+ # wait_for(wfid)
65
+ #
66
+ # assert_match(/cat food/, File.read(trapfile))
67
+ # assert_nil @engine.process(wfid)
68
+ #
69
+ # t.kill
70
+ # end
70
71
 
71
72
  def test_smtp_non_instance_participant
72
73
 
@@ -104,9 +105,10 @@ class NftSmtpParticipantTest < Test::Unit::TestCase
104
105
 
105
106
  wfid = @engine.launch(pdef)
106
107
 
107
- sleep 0.450
108
+ #sleep 0.450
109
+ wait_for(wfid)
108
110
 
109
- assert_match(/cat food/, File.read(trapfile))
111
+ assert_match(/want cat food/, File.read(trapfile))
110
112
  assert_nil @engine.process(wfid)
111
113
 
112
114
  t.kill
@@ -7,7 +7,7 @@
7
7
 
8
8
  require File.join(File.dirname(__FILE__), 'base')
9
9
 
10
- require 'ruote/log/fs_history'
10
+ #require 'ruote/log/fs_history'
11
11
  require 'ruote/part/no_op_participant'
12
12
 
13
13
 
@@ -33,17 +33,17 @@ class FtStorageHistoryTest < Test::Unit::TestCase
33
33
 
34
34
  sleep 0.100
35
35
 
36
- assert_equal 17, @engine.storage.get_many('history').size
36
+ assert_equal 19, @engine.storage.get_many('history').size
37
37
 
38
38
  h = @engine.context.history.by_process(wfid0)
39
39
  #h.each { |r| p r }
40
- assert_equal 8, h.size
40
+ assert_equal 9, h.size
41
41
 
42
42
  # testing record.to_h
43
43
 
44
44
  h = @engine.context.history.by_process(wfid1)
45
45
  #h.each { |r| p r }
46
- assert_equal 8, h.size
46
+ assert_equal 9, h.size
47
47
 
48
48
  history.clear!
49
49
 
@@ -20,18 +20,21 @@ class FtEngineParticipantTest < Test::Unit::TestCase
20
20
 
21
21
  def setup
22
22
 
23
+ @dir0 = "work0_#{$$}_#{self.object_id}_#{Time.now.to_f}"
24
+ @dir1 = "work1_#{$$}_#{self.object_id}_#{Time.now.to_f}"
25
+
23
26
  @engine0 =
24
27
  Ruote::Engine.new(
25
28
  Ruote::Worker.new(
26
29
  Ruote::FsStorage.new(
27
- 'work0',
30
+ @dir0,
28
31
  'engine_id' => 'engine0',
29
32
  's_logger' => [ 'ruote/log/test_logger', 'Ruote::TestLogger' ])))
30
33
  @engine1 =
31
34
  Ruote::Engine.new(
32
35
  Ruote::Worker.new(
33
36
  Ruote::FsStorage.new(
34
- 'work1',
37
+ @dir1,
35
38
  'engine_id' => 'engine1',
36
39
  's_logger' => [ 'ruote/log/test_logger', 'Ruote::TestLogger' ])))
37
40
 
@@ -46,13 +49,13 @@ class FtEngineParticipantTest < Test::Unit::TestCase
46
49
  Ruote::EngineParticipant,
47
50
  'storage_class' => Ruote::FsStorage,
48
51
  'storage_path' => 'ruote/storage/fs_storage',
49
- 'storage_args' => 'work1')
52
+ 'storage_args' => @dir1)
50
53
  @engine1.register_participant(
51
54
  'engine0',
52
55
  Ruote::EngineParticipant,
53
56
  'storage_class' => Ruote::FsStorage,
54
57
  'storage_path' => 'ruote/storage/fs_storage',
55
- 'storage_args' => 'work0')
58
+ 'storage_args' => @dir0)
56
59
  end
57
60
 
58
61
  def teardown
@@ -60,8 +63,8 @@ class FtEngineParticipantTest < Test::Unit::TestCase
60
63
  @engine0.shutdown
61
64
  @engine1.shutdown
62
65
 
63
- FileUtils.rm_rf('work0')
64
- FileUtils.rm_rf('work1')
66
+ FileUtils.rm_rf(@dir0)
67
+ FileUtils.rm_rf(@dir1)
65
68
  end
66
69
 
67
70
  def noisy
@@ -164,12 +167,13 @@ class FtEngineParticipantTest < Test::Unit::TestCase
164
167
  @engine0.cancel_process(wfid)
165
168
  @engine0.wait_for(wfid)
166
169
 
167
- sleep 0.350 # since dispatch_cancel is asyncrhonous now
170
+ #@engine0.wait_for(1) # since dispatch_cancel is asynchronous now
171
+ sleep 0.777 # but well sometimes the dispatch is too fast
168
172
 
169
173
  assert_equal 0, alpha.size
170
174
 
171
- assert_equal "a", @tracer0.to_s
172
- assert_equal "", @tracer1.to_s
175
+ assert_equal 'a', @tracer0.to_s
176
+ assert_equal '', @tracer1.to_s
173
177
  end
174
178
 
175
179
  def test_with_variables
@@ -282,7 +286,7 @@ class FtEngineParticipantTest < Test::Unit::TestCase
282
286
  Ruote::EngineParticipant,
283
287
  'storage_class' => Ruote::FsStorage,
284
288
  'storage_path' => 'ruote/storage/fs_storage',
285
- 'storage_args' => 'work0')
289
+ 'storage_args' => @dir0)
286
290
 
287
291
  # replay
288
292