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