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.
- data/CHANGELOG.txt +32 -0
- data/CREDITS.txt +3 -0
- data/Rakefile +4 -4
- data/TODO.txt +55 -11
- data/examples/barley.rb +2 -1
- data/examples/flickr_report.rb +5 -6
- data/examples/web_first_page.rb +11 -0
- data/lib/ruote/context.rb +36 -13
- data/lib/ruote/engine.rb +88 -56
- data/lib/ruote/engine/process_error.rb +13 -0
- data/lib/ruote/engine/process_status.rb +33 -1
- data/lib/ruote/error_handler.rb +122 -0
- data/lib/ruote/evt/tracker.rb +27 -10
- data/lib/ruote/exp/fe_apply.rb +69 -0
- data/lib/ruote/exp/fe_participant.rb +33 -5
- data/lib/ruote/exp/flowexpression.rb +37 -5
- data/lib/ruote/exp/ro_persist.rb +8 -4
- data/lib/ruote/exp/ro_variables.rb +2 -2
- data/lib/ruote/fei.rb +59 -7
- data/lib/ruote/log/storage_history.rb +2 -0
- data/lib/ruote/log/test_logger.rb +28 -19
- data/lib/ruote/log/wait_logger.rb +4 -2
- data/lib/ruote/parser.rb +2 -1
- data/lib/ruote/part/dispatch_pool.rb +10 -10
- data/lib/ruote/part/engine_participant.rb +2 -2
- data/lib/ruote/part/local_participant.rb +99 -7
- data/lib/ruote/part/participant_list.rb +18 -7
- data/lib/ruote/part/storage_participant.rb +9 -6
- data/lib/ruote/receiver/base.rb +109 -10
- data/lib/ruote/storage/base.rb +118 -41
- data/lib/ruote/storage/fs_storage.rb +1 -0
- data/lib/ruote/storage/hash_storage.rb +2 -1
- data/lib/ruote/util/lookup.rb +22 -2
- data/lib/ruote/util/misc.rb +5 -5
- data/lib/ruote/version.rb +1 -1
- data/lib/ruote/worker.rb +50 -63
- data/lib/ruote/workitem.rb +64 -0
- data/ruote.gemspec +17 -12
- data/test/functional/base.rb +3 -1
- data/test/functional/concurrent_base.rb +35 -29
- data/test/functional/crunner.sh +19 -0
- data/test/functional/ct_0_concurrence.rb +17 -30
- data/test/functional/ct_1_iterator.rb +20 -17
- data/test/functional/ct_2_cancel.rb +32 -25
- data/test/functional/eft_12_listen.rb +2 -1
- data/test/functional/eft_23_apply.rb +23 -0
- data/test/functional/eft_3_participant.rb +27 -0
- data/test/functional/ft_11_recursion.rb +1 -1
- data/test/functional/ft_13_variables.rb +22 -0
- data/test/functional/ft_14_re_apply.rb +3 -0
- data/test/functional/ft_15_timeout.rb +1 -0
- data/test/functional/ft_20_storage_participant.rb +20 -2
- data/test/functional/ft_21_forget.rb +30 -0
- data/test/functional/ft_22_process_definitions.rb +2 -1
- data/test/functional/ft_24_block_participants.rb +1 -1
- data/test/functional/ft_25_receiver.rb +83 -1
- data/test/functional/ft_26_participant_timeout.rb +1 -1
- data/test/functional/ft_2_errors.rb +2 -5
- data/test/functional/ft_30_smtp_participant.rb +47 -45
- data/test/functional/ft_36_storage_history.rb +4 -4
- data/test/functional/ft_37_engine_participant.rb +14 -10
- data/test/functional/ft_38_participant_more.rb +178 -0
- data/test/functional/ft_39_wait_for.rb +100 -0
- data/test/functional/ft_40_participant_on_reply.rb +87 -0
- data/test/functional/ft_41_participants.rb +65 -0
- data/test/functional/ft_42_storage_copy.rb +67 -0
- data/test/functional/ft_5_on_error.rb +103 -0
- data/test/functional/ft_9_subprocesses.rb +2 -1
- data/test/functional/storage_helper.rb +5 -1
- data/test/functional/test.rb +4 -1
- data/test/functional/vertical.rb +46 -0
- data/test/unit/storage.rb +17 -1
- data/test/unit/storages.rb +27 -7
- data/test/unit/ut_11_lookup.rb +36 -0
- data/test/unit/ut_16_parser.rb +43 -0
- data/test/unit/ut_1_fei.rb +28 -1
- data/test/unit/ut_7_workitem.rb +23 -0
- metadata +67 -105
- data/lib/ruote/log/fs_history.rb +0 -182
- data/test/functional/ft_32_fs_history.rb +0 -188
- data/test/mpc_test.rb +0 -29
@@ -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(:
|
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
|
@@ -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
|
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
|
|
@@ -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
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
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' =>
|
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' =>
|
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(
|
64
|
-
FileUtils.rm_rf(
|
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
|
-
|
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
|
172
|
-
assert_equal
|
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' =>
|
289
|
+
'storage_args' => @dir0)
|
286
290
|
|
287
291
|
# replay
|
288
292
|
|