ruote 2.1.9 → 2.1.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,178 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing ruote
|
4
|
+
#
|
5
|
+
# Mon Apr 19 14:38:54 JST 2010
|
6
|
+
#
|
7
|
+
# Qcon Tokyo, special day
|
8
|
+
#
|
9
|
+
|
10
|
+
require File.join(File.dirname(__FILE__), 'base')
|
11
|
+
|
12
|
+
require 'ruote/part/local_participant'
|
13
|
+
|
14
|
+
|
15
|
+
class FtParticipantMoreTest < Test::Unit::TestCase
|
16
|
+
include FunctionalBase
|
17
|
+
|
18
|
+
class DifficultParticipant
|
19
|
+
include Ruote::LocalParticipant
|
20
|
+
def initialize (opts)
|
21
|
+
end
|
22
|
+
def consume (workitem)
|
23
|
+
context.tracer << "diff\n"
|
24
|
+
if workitem.fields['rejected'].nil?
|
25
|
+
workitem.fields['rejected'] = true
|
26
|
+
reject(workitem)
|
27
|
+
else
|
28
|
+
reply_to_engine(workitem)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_participant_reject
|
34
|
+
|
35
|
+
pdef = Ruote.process_definition do
|
36
|
+
alpha
|
37
|
+
end
|
38
|
+
|
39
|
+
@engine.register_participant :alpha, DifficultParticipant
|
40
|
+
|
41
|
+
#noisy
|
42
|
+
|
43
|
+
assert_trace(%w[ diff diff ], pdef)
|
44
|
+
end
|
45
|
+
|
46
|
+
class FightingParticipant
|
47
|
+
include Ruote::LocalParticipant
|
48
|
+
def initialize (opts)
|
49
|
+
end
|
50
|
+
def consume (workitem)
|
51
|
+
try = workitem.fields['try'] || 0
|
52
|
+
context.tracer << "try#{try}\n"
|
53
|
+
workitem.fields['try'] = try + 1
|
54
|
+
if (try == 0)
|
55
|
+
re_dispatch(workitem)
|
56
|
+
else
|
57
|
+
reply(workitem)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_participant_re_dispatch
|
63
|
+
|
64
|
+
pdef = Ruote.process_definition do
|
65
|
+
alpha
|
66
|
+
end
|
67
|
+
|
68
|
+
@engine.register_participant :alpha, FightingParticipant
|
69
|
+
|
70
|
+
#noisy
|
71
|
+
|
72
|
+
assert_trace(%w[ try0 try1 ], pdef)
|
73
|
+
end
|
74
|
+
|
75
|
+
class RetryParticipant
|
76
|
+
include Ruote::LocalParticipant
|
77
|
+
def initialize (opts)
|
78
|
+
@opts = opts
|
79
|
+
end
|
80
|
+
def consume (workitem)
|
81
|
+
try = workitem.fields['try'] || 0
|
82
|
+
context.tracer << "#{Time.now.to_f}\n"
|
83
|
+
workitem.fields['try'] = try + 1
|
84
|
+
if (try == 0)
|
85
|
+
re_dispatch(workitem, :in => @opts['delay'] || '1s')
|
86
|
+
else
|
87
|
+
reply(workitem)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
def cancel (fei, flavour)
|
91
|
+
unschedule_re_dispatch(fei)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_participant_re_dispatch_later
|
96
|
+
|
97
|
+
pdef = Ruote.process_definition do
|
98
|
+
alpha
|
99
|
+
end
|
100
|
+
|
101
|
+
@engine.register_participant :alpha, RetryParticipant
|
102
|
+
|
103
|
+
#noisy
|
104
|
+
|
105
|
+
wfid = @engine.launch(pdef)
|
106
|
+
wait_for(wfid)
|
107
|
+
|
108
|
+
times = @tracer.to_s.split("\n").collect { |t| Float(t) }
|
109
|
+
t = times.last - times.first
|
110
|
+
|
111
|
+
assert t >= 1.0, "took less that 1 second"
|
112
|
+
assert t < 2.0, "took more than 1.99 second"
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_participant_re_dispatch_later_cancel
|
116
|
+
|
117
|
+
pdef = Ruote.process_definition do
|
118
|
+
alpha
|
119
|
+
end
|
120
|
+
|
121
|
+
@engine.register_participant :alpha, RetryParticipant, 'delay' => '1m'
|
122
|
+
|
123
|
+
#noisy
|
124
|
+
|
125
|
+
wfid = @engine.launch(pdef)
|
126
|
+
sleep 0.7
|
127
|
+
|
128
|
+
@engine.cancel_process(wfid)
|
129
|
+
wait_for(wfid)
|
130
|
+
|
131
|
+
assert_equal 0, @engine.storage.get_many('schedules').size
|
132
|
+
end
|
133
|
+
|
134
|
+
BLACKBOARD = {}
|
135
|
+
|
136
|
+
class StashingParticipant
|
137
|
+
include Ruote::LocalParticipant
|
138
|
+
def initialize (opts)
|
139
|
+
end
|
140
|
+
def consume (workitem)
|
141
|
+
put(workitem.fei, 'token' => workitem.params['token'])
|
142
|
+
end
|
143
|
+
def cancel (fei, flavour)
|
144
|
+
BLACKBOARD['token'] = get(fei, 'token')
|
145
|
+
BLACKBOARD['all'] = get(fei)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_stash
|
150
|
+
|
151
|
+
BLACKBOARD.clear
|
152
|
+
|
153
|
+
pdef = Ruote.process_definition do
|
154
|
+
alpha :token => 'of esteem'
|
155
|
+
end
|
156
|
+
|
157
|
+
@engine.register_participant :alpha, StashingParticipant
|
158
|
+
|
159
|
+
#noisy
|
160
|
+
|
161
|
+
wfid = @engine.launch(pdef)
|
162
|
+
wait_for(:alpha)
|
163
|
+
|
164
|
+
sleep 0.350 # since wait_for(:alpha) releases too early sometimes
|
165
|
+
|
166
|
+
ps = @engine.process(wfid)
|
167
|
+
fexp = ps.expressions.find { |e| e.fei.expid == '0_0' }
|
168
|
+
|
169
|
+
assert_equal({ 'token' => 'of esteem' }, fexp.h.stash)
|
170
|
+
|
171
|
+
@engine.cancel_process(wfid)
|
172
|
+
wait_for(wfid)
|
173
|
+
|
174
|
+
assert_equal('of esteem', BLACKBOARD['token'])
|
175
|
+
assert_equal({ 'token' => 'of esteem' }, BLACKBOARD['all'])
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
@@ -0,0 +1,100 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing ruote
|
4
|
+
#
|
5
|
+
# Tue Apr 20 12:32:44 JST 2010
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'base')
|
9
|
+
|
10
|
+
require 'ruote/part/storage_participant'
|
11
|
+
|
12
|
+
|
13
|
+
class FtEngineTest < Test::Unit::TestCase
|
14
|
+
include FunctionalBase
|
15
|
+
|
16
|
+
def test_workitem
|
17
|
+
|
18
|
+
pdef = Ruote.process_definition :name => 'my process' do
|
19
|
+
alpha
|
20
|
+
end
|
21
|
+
|
22
|
+
sp = @engine.register_participant :alpha, Ruote::StorageParticipant
|
23
|
+
|
24
|
+
#noisy
|
25
|
+
|
26
|
+
wfid = @engine.launch(pdef)
|
27
|
+
|
28
|
+
wait_for(:alpha)
|
29
|
+
|
30
|
+
assert_equal Ruote::Workitem, @engine.workitem("0_0!!#{wfid}").class
|
31
|
+
end
|
32
|
+
|
33
|
+
class MyParticipant
|
34
|
+
include Ruote::LocalParticipant
|
35
|
+
def initialize (opts)
|
36
|
+
end
|
37
|
+
def consume (workitem)
|
38
|
+
sleep rand * 2
|
39
|
+
reply_to_engine(workitem)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_wait_for_empty
|
44
|
+
|
45
|
+
pdef = Ruote.process_definition :name => 'my process' do
|
46
|
+
alpha
|
47
|
+
end
|
48
|
+
|
49
|
+
@engine.register_participant :alpha, MyParticipant
|
50
|
+
|
51
|
+
4.times do
|
52
|
+
@engine.launch(pdef)
|
53
|
+
end
|
54
|
+
|
55
|
+
#noisy
|
56
|
+
|
57
|
+
@engine.wait_for(:empty)
|
58
|
+
|
59
|
+
assert_equal [], @engine.processes
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_wait_for_multiple
|
63
|
+
|
64
|
+
pdef0 = Ruote.process_definition { alpha }
|
65
|
+
pdef1 = Ruote.process_definition { bravo }
|
66
|
+
|
67
|
+
@engine.register_participant :alpha, MyParticipant
|
68
|
+
|
69
|
+
#noisy
|
70
|
+
|
71
|
+
wfids = []
|
72
|
+
|
73
|
+
2.times { wfids << @engine.launch(pdef0) }
|
74
|
+
2.times { wfids << @engine.launch(pdef1) }
|
75
|
+
|
76
|
+
@engine.wait_for(*wfids)
|
77
|
+
|
78
|
+
assert_equal 2, @engine.processes.size
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_wait_for_inactive
|
82
|
+
|
83
|
+
pdef0 = Ruote.process_definition { alpha }
|
84
|
+
pdef1 = Ruote.process_definition { bravo }
|
85
|
+
|
86
|
+
@engine.register_participant :alpha, MyParticipant
|
87
|
+
|
88
|
+
#noisy
|
89
|
+
|
90
|
+
wfids = []
|
91
|
+
|
92
|
+
2.times { @engine.launch(pdef0) }
|
93
|
+
2.times { wfids << @engine.launch(pdef1) }
|
94
|
+
|
95
|
+
@engine.wait_for(:inactive)
|
96
|
+
|
97
|
+
assert_equal wfids.sort, @engine.processes.collect { |ps| ps.wfid }.sort
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing ruote
|
4
|
+
#
|
5
|
+
# Thu Apr 22 14:41:38 JST 2010
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'base')
|
9
|
+
|
10
|
+
require 'ruote/part/local_participant'
|
11
|
+
|
12
|
+
|
13
|
+
class FtParticipantOnReplyTest < Test::Unit::TestCase
|
14
|
+
include FunctionalBase
|
15
|
+
|
16
|
+
class MyParticipant
|
17
|
+
include Ruote::LocalParticipant
|
18
|
+
def initialize (opts)
|
19
|
+
end
|
20
|
+
def consume (workitem)
|
21
|
+
reply(workitem)
|
22
|
+
end
|
23
|
+
def on_reply (workitem)
|
24
|
+
workitem.fields['message'] = 'hello'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_participant_on_reply
|
29
|
+
|
30
|
+
pdef = Ruote.process_definition do
|
31
|
+
sequence do
|
32
|
+
alpha
|
33
|
+
echo '${f:message}'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
@engine.register_participant :alpha, MyParticipant
|
38
|
+
|
39
|
+
#noisy
|
40
|
+
|
41
|
+
assert_trace('hello', pdef)
|
42
|
+
end
|
43
|
+
|
44
|
+
class AwkwardParticipant
|
45
|
+
include Ruote::LocalParticipant
|
46
|
+
def initialize (opts)
|
47
|
+
end
|
48
|
+
def consume (workitem)
|
49
|
+
reply(workitem)
|
50
|
+
end
|
51
|
+
def on_reply (workitem)
|
52
|
+
return if workitem.fields['pass']
|
53
|
+
raise "something went wrong"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_participant_on_reply_error
|
58
|
+
|
59
|
+
pdef = Ruote.process_definition do
|
60
|
+
sequence do
|
61
|
+
alpha
|
62
|
+
echo 'over.'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
@engine.register_participant :alpha, AwkwardParticipant
|
67
|
+
|
68
|
+
#noisy
|
69
|
+
|
70
|
+
wfid = @engine.launch(pdef)
|
71
|
+
|
72
|
+
wait_for(wfid)
|
73
|
+
|
74
|
+
ps = @engine.process(wfid)
|
75
|
+
|
76
|
+
assert_equal 1, ps.errors.size
|
77
|
+
|
78
|
+
err = ps.errors.first
|
79
|
+
err.fields['pass'] = true
|
80
|
+
@engine.replay_at_error(err)
|
81
|
+
|
82
|
+
wait_for(wfid)
|
83
|
+
|
84
|
+
assert_equal 'over.', @tracer.to_s
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing ruote
|
4
|
+
#
|
5
|
+
# Mon Jun 14 12:02:53 JST 2010
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'base')
|
9
|
+
|
10
|
+
require 'ruote/part/local_participant'
|
11
|
+
|
12
|
+
|
13
|
+
class FtMiscParticipantTest < Test::Unit::TestCase
|
14
|
+
include FunctionalBase
|
15
|
+
|
16
|
+
class MyParticipant
|
17
|
+
include Ruote::LocalParticipant
|
18
|
+
def consume (workitem)
|
19
|
+
workitem.fields['seen'] = true
|
20
|
+
reply_to_engine(workitem)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class MyMessageParticipant
|
25
|
+
include Ruote::LocalParticipant
|
26
|
+
def initialize (opts)
|
27
|
+
@opts = opts
|
28
|
+
end
|
29
|
+
def consume (workitem)
|
30
|
+
workitem.fields['message'] = @opts['message']
|
31
|
+
reply_to_engine(workitem)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_participant_without_initialize
|
36
|
+
|
37
|
+
@engine.register_participant :alpha, MyParticipant
|
38
|
+
|
39
|
+
#noisy
|
40
|
+
|
41
|
+
wfid = @engine.launch(Ruote.process_definition do
|
42
|
+
alpha
|
43
|
+
end)
|
44
|
+
|
45
|
+
r = wait_for(wfid)
|
46
|
+
|
47
|
+
assert_equal true, r['workitem']['fields']['seen']
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_participant_with_initialize
|
51
|
+
|
52
|
+
@engine.register_participant :bravo, MyMessageParticipant, 'message' => 'hi'
|
53
|
+
|
54
|
+
#noisy
|
55
|
+
|
56
|
+
wfid = @engine.launch(Ruote.process_definition do
|
57
|
+
bravo
|
58
|
+
end)
|
59
|
+
|
60
|
+
r = wait_for(wfid)
|
61
|
+
|
62
|
+
assert_equal 'hi', r['workitem']['fields']['message']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
|
2
|
+
#
|
3
|
+
# testing ruote
|
4
|
+
#
|
5
|
+
# Tue Jun 15 09:07:58 JST 2010
|
6
|
+
#
|
7
|
+
|
8
|
+
require File.join(File.dirname(__FILE__), 'base')
|
9
|
+
|
10
|
+
require 'ruote/part/storage_participant'
|
11
|
+
|
12
|
+
|
13
|
+
class FtStorageCopyTest < Test::Unit::TestCase
|
14
|
+
include FunctionalBase
|
15
|
+
|
16
|
+
def test_copy_to_hash_storage
|
17
|
+
|
18
|
+
@engine.register_participant '.+', Ruote::StorageParticipant
|
19
|
+
|
20
|
+
#noisy
|
21
|
+
|
22
|
+
wfid = @engine.launch(Ruote.process_definition do
|
23
|
+
sequence do
|
24
|
+
alpha :timeout => '2d'
|
25
|
+
end
|
26
|
+
end)
|
27
|
+
|
28
|
+
wait_for(:alpha)
|
29
|
+
|
30
|
+
target = Ruote::HashStorage.new
|
31
|
+
source = @engine.context.storage
|
32
|
+
|
33
|
+
#count = source.copy_to(target, :verbose => true)
|
34
|
+
count = source.copy_to(target)
|
35
|
+
|
36
|
+
assert_equal 8, count
|
37
|
+
assert_equal source.ids('expressions'), target.ids('expressions')
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_copy_from_hash_storage
|
41
|
+
|
42
|
+
engine = Ruote::Engine.new(Ruote::Worker.new(Ruote::HashStorage.new()))
|
43
|
+
|
44
|
+
engine.register_participant '.+', Ruote::StorageParticipant
|
45
|
+
|
46
|
+
#engine.context.logger.noisy = true
|
47
|
+
|
48
|
+
wfid = engine.launch(Ruote.process_definition do
|
49
|
+
sequence do
|
50
|
+
alpha :timeout => '2d'
|
51
|
+
end
|
52
|
+
end)
|
53
|
+
|
54
|
+
engine.wait_for(:alpha)
|
55
|
+
|
56
|
+
source = engine.context.storage
|
57
|
+
target = @engine.context.storage
|
58
|
+
|
59
|
+
#count = source.copy_to(target, :verbose => true)
|
60
|
+
count = source.copy_to(target)
|
61
|
+
|
62
|
+
assert_equal 8, count
|
63
|
+
assert_equal source.ids('expressions'), target.ids('expressions')
|
64
|
+
assert_not_nil @engine.process(wfid)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|