ruote 2.1.9 → 2.1.10

Sign up to get free protection for your applications and to get access to all the features.
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