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
@@ -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
|
+
|