perfectqueue 0.8.44.1 → 0.8.45
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +5 -2
- data/lib/perfectqueue/application/decider.rb +2 -2
- data/lib/perfectqueue/application/router.rb +1 -1
- data/lib/perfectqueue/backend/rdb_compat.rb +40 -58
- data/lib/perfectqueue/engine.rb +2 -5
- data/lib/perfectqueue/multiprocess/thread_processor.rb +1 -1
- data/lib/perfectqueue/task.rb +2 -1
- data/lib/perfectqueue/task_metadata.rb +2 -4
- data/lib/perfectqueue/version.rb +1 -1
- data/perfectqueue.gemspec +1 -2
- data/spec/application/base_spec.rb +81 -0
- data/spec/application/decider_spec.rb +56 -0
- data/spec/application/dispatch_spec.rb +22 -0
- data/spec/application/router_spec.rb +48 -0
- data/spec/backend_spec.rb +9 -0
- data/spec/blocking_flag_spec.rb +103 -0
- data/spec/client_spec.rb +28 -0
- data/spec/daemons_logger_spec.rb +35 -0
- data/spec/engine_spec.rb +159 -0
- data/spec/multiprocess/child_process_monitor_spec.rb +300 -0
- data/spec/multiprocess/child_process_spec.rb +160 -0
- data/spec/multiprocess/fork_processor_spec.rb +170 -0
- data/spec/multiprocess/thread_processor_spec.rb +52 -0
- data/spec/queue_spec.rb +73 -68
- data/spec/rdb_compat_backend_spec.rb +481 -19
- data/spec/runner_spec.rb +32 -0
- data/spec/signal_thread_spec.rb +43 -0
- data/spec/stress.rb +1 -1
- data/spec/supervisor_spec.rb +188 -33
- data/spec/task_metadata_spec.rb +69 -0
- data/spec/task_monitor_spec.rb +42 -0
- data/spec/task_spec.rb +70 -0
- metadata +40 -19
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PerfectQueue::Multiprocess::ChildProcess do
|
4
|
+
let (:runner_insntace){ double('runner') }
|
5
|
+
let (:runner) do
|
6
|
+
runner = double('Runner')
|
7
|
+
allow(runner).to receive(:new).and_return(runner_insntace)
|
8
|
+
runner
|
9
|
+
end
|
10
|
+
let (:processor_id){ double('processor_id') }
|
11
|
+
let (:logger){ double('logger').as_null_object }
|
12
|
+
let (:config){ {logger: logger} }
|
13
|
+
let (:wpipe){ double('wpipe', sync: true, :'sync=' => true) }
|
14
|
+
let (:pr){ Multiprocess::ChildProcess.new(runner, processor_id, config, wpipe) }
|
15
|
+
describe '.run' do
|
16
|
+
let (:pr){ double('child_process') }
|
17
|
+
before do
|
18
|
+
expect(Multiprocess::ChildProcess).to receive(:new).exactly(:once) \
|
19
|
+
.with(runner, processor_id, config, wpipe).and_return(pr)
|
20
|
+
expect(pr).to receive(:run).exactly(:once)
|
21
|
+
end
|
22
|
+
it 'runs an instance' do
|
23
|
+
Multiprocess::ChildProcess.run(runner, processor_id, config, wpipe)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.new' do
|
28
|
+
it 'returns a Multiprocess::ChildProcess' do
|
29
|
+
pr = Multiprocess::ChildProcess.new(runner, processor_id, config, wpipe)
|
30
|
+
expect(pr).to be_an_instance_of(Multiprocess::ChildProcess)
|
31
|
+
expect(pr.instance_variable_get(:@wpipe)).to eq(wpipe)
|
32
|
+
expect(pr.instance_variable_get(:@sig)).to be_a(SignalThread)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#stop' do
|
37
|
+
it 'call super' do
|
38
|
+
pr.stop(true)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#keepalive' do
|
43
|
+
it { pr.keepalive }
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#logrotated' do
|
47
|
+
it do
|
48
|
+
expect(logger).to receive(:reopen!).with(no_args).exactly(:once)
|
49
|
+
pr.logrotated
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#child_heartbeat' do
|
54
|
+
let (:packet){ Multiprocess::ChildProcess::HEARTBEAT_PACKET }
|
55
|
+
it 'write HEARTBEAT_PACKET' do
|
56
|
+
expect(wpipe).to receive(:write).with(packet).exactly(:once)
|
57
|
+
pr.child_heartbeat
|
58
|
+
end
|
59
|
+
it 'rescue an error' do
|
60
|
+
expect(wpipe).to receive(:write).with(packet).exactly(:once) \
|
61
|
+
.and_raise(RuntimeError)
|
62
|
+
expect(pr).to receive(:force_stop).exactly(:once)
|
63
|
+
pr.child_heartbeat
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#force_stop' do
|
68
|
+
it 'calls exit! 137' do
|
69
|
+
expect(Process).to receive(:kill).with(:KILL, Process.pid)
|
70
|
+
expect(pr).to receive(:exit!).with(137).exactly(:once)
|
71
|
+
pr.force_stop
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#process' do
|
76
|
+
let (:task){ double('task', key: double) }
|
77
|
+
before do
|
78
|
+
expect(runner_insntace).to receive(:run)
|
79
|
+
end
|
80
|
+
context 'max_request_per_child is nil' do
|
81
|
+
it 'runs' do
|
82
|
+
pr.process(task)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
context 'max_request_per_child is set' do
|
86
|
+
before do
|
87
|
+
pr.instance_variable_set(:@max_request_per_child, 2)
|
88
|
+
end
|
89
|
+
it 'counts children if request_per_child is still small' do
|
90
|
+
expect(pr).not_to receive(:stop)
|
91
|
+
pr.instance_variable_set(:@request_per_child, 1)
|
92
|
+
pr.process(task)
|
93
|
+
expect(pr.instance_variable_get(:@request_per_child)).to eq(2)
|
94
|
+
end
|
95
|
+
it 'stops children if request_per_child exceeds the limit' do
|
96
|
+
expect(pr).to receive(:stop).with(false).exactly(:once)
|
97
|
+
pr.instance_variable_set(:@request_per_child, 2)
|
98
|
+
pr.process(task)
|
99
|
+
expect(pr.instance_variable_get(:@request_per_child)).to eq(3)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'signal handling' do
|
105
|
+
before do
|
106
|
+
allow(PerfectQueue).to receive(:open) do
|
107
|
+
flag = pr.instance_variable_get(:@finish_flag)
|
108
|
+
Thread.pass until flag.set?
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'calls stop(false) SIGTERM' do
|
113
|
+
expect(pr).to receive(:stop).with(false).and_call_original
|
114
|
+
Process.kill(:TERM, Process.pid)
|
115
|
+
pr.run
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'calls stop(false) SIGINT' do
|
119
|
+
expect(pr).to receive(:stop).with(false).and_call_original
|
120
|
+
Process.kill(:INT, Process.pid)
|
121
|
+
pr.run
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'calls stop(true) SIGQUIT' do
|
125
|
+
expect(pr).to receive(:stop).with(true).and_call_original
|
126
|
+
Process.kill(:QUIT, Process.pid)
|
127
|
+
pr.run
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'calls stop(false) SIGUSR1' do
|
131
|
+
expect(pr).to receive(:stop).with(false).and_call_original
|
132
|
+
Process.kill(:USR1, Process.pid)
|
133
|
+
pr.run
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'calls stop(true) SIGHUP' do
|
137
|
+
expect(pr).to receive(:stop).with(true).and_call_original
|
138
|
+
Process.kill(:HUP, Process.pid)
|
139
|
+
pr.run
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'calls stop(false) on SIGCONT' do
|
143
|
+
expect(pr).to receive(:stop).with(false).and_call_original
|
144
|
+
Process.kill(:CONT, Process.pid)
|
145
|
+
pr.run
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'calls stop(true) on SIGWINCH' do
|
149
|
+
expect(pr).to receive(:stop).with(true).and_call_original
|
150
|
+
Process.kill(:WINCH, Process.pid)
|
151
|
+
pr.run
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'calls logrotated on SIGUSR2' do
|
155
|
+
expect(pr).to receive(:logrotated){ pr.stop(true) }
|
156
|
+
Process.kill(:USR2, Process.pid)
|
157
|
+
pr.run
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PerfectQueue::Multiprocess::ForkProcessor do
|
4
|
+
describe '.new' do
|
5
|
+
it 'returns a PerfectQueue::Multiprocess::ForkProcessor' do
|
6
|
+
runner = double('runner')
|
7
|
+
processor_id = double('processor_id')
|
8
|
+
config = {}
|
9
|
+
processor = Multiprocess::ForkProcessor.new(runner, processor_id, config)
|
10
|
+
expect(processor).to be_an_instance_of(Multiprocess::ForkProcessor)
|
11
|
+
expect(processor.instance_variable_get(:@processor_id)).to eq(processor_id)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#restart' do
|
16
|
+
let (:config_keys){[
|
17
|
+
:child_heartbeat_limit,
|
18
|
+
:child_kill_interval,
|
19
|
+
:child_graceful_kill_limit,
|
20
|
+
:child_fork_frequency_limit,
|
21
|
+
:child_heartbeat_kill_delay,
|
22
|
+
]}
|
23
|
+
let (:config){ {logger: double('logger').as_null_object} }
|
24
|
+
let (:processor) {
|
25
|
+
runner = double('runner')
|
26
|
+
processor_id = double('processor_id')
|
27
|
+
Multiprocess::ForkProcessor.new(runner, processor_id, config)
|
28
|
+
}
|
29
|
+
it 'sets config' do
|
30
|
+
config_keys.each do |key|
|
31
|
+
config[key] = double(key)
|
32
|
+
end
|
33
|
+
processor.restart(true, config)
|
34
|
+
config_keys.each do |key|
|
35
|
+
expect(processor.instance_variable_get("@#{key}".to_sym)).to eq(config[key])
|
36
|
+
end
|
37
|
+
expect(processor.instance_variable_get(:@config)).to eq(config)
|
38
|
+
end
|
39
|
+
it 'calls ChildProcessMonitor#start_killing if it has ChildProcessMonitor' do
|
40
|
+
immediate = double('immediate')
|
41
|
+
cpm = double('ChildProcessMonitor')
|
42
|
+
expect(cpm).to receive(:start_killing).with(immediate).exactly(:once)
|
43
|
+
processor.instance_variable_set(:@cpm, cpm)
|
44
|
+
processor.restart(immediate, config)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#stop' do
|
49
|
+
let (:processor) {
|
50
|
+
runner = double('runner')
|
51
|
+
processor_id = double('processor_id')
|
52
|
+
config = {logger: double('logger').as_null_object}
|
53
|
+
Multiprocess::ForkProcessor.new(runner, processor_id, config)
|
54
|
+
}
|
55
|
+
it 'calls ChildProcessMonitor#start_killing if it has ChildProcessMonitor' do
|
56
|
+
immediate = double('immediate')
|
57
|
+
cpm = double('ChildProcessMonitor')
|
58
|
+
expect(cpm).to receive(:start_killing).with(immediate).exactly(:once)
|
59
|
+
processor.instance_variable_set(:@cpm, cpm)
|
60
|
+
processor.stop(immediate)
|
61
|
+
expect(processor.instance_variable_get(:@stop)).to be true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#keepalive' do
|
66
|
+
let (:processor) do
|
67
|
+
config = {logger: double('logger').as_null_object}
|
68
|
+
Multiprocess::ForkProcessor.new(double('runner'), double('processor_id'), config)
|
69
|
+
end
|
70
|
+
it 'tries join on stopping without cpm' do
|
71
|
+
processor.stop(true)
|
72
|
+
processor.keepalive
|
73
|
+
end
|
74
|
+
it 'tries join on stopping with cpm' do
|
75
|
+
processor.stop(true)
|
76
|
+
cpm = double('ChildProcessMonitor', try_join: false)
|
77
|
+
processor.instance_variable_set(:@cpm, cpm)
|
78
|
+
processor.keepalive
|
79
|
+
end
|
80
|
+
it 'calls fork_child if it doesn\'t have ChildProcessMonitor' do
|
81
|
+
expect(processor.keepalive).to be_nil
|
82
|
+
expect(processor.instance_variable_get(:@cpm)).to be_an_instance_of(Multiprocess::ChildProcessMonitor)
|
83
|
+
end
|
84
|
+
it 'rascues fork_child\'s error if it doesn\'t have ChildProcessMonitor' do
|
85
|
+
allow(processor).to receive(:fork_child).and_raise(RuntimeError)
|
86
|
+
expect(processor.keepalive).to be_nil
|
87
|
+
end
|
88
|
+
it 'tries join if it has killed ChildProcessMonitor' do
|
89
|
+
cpm = double('ChildProcessMonitor', killing_status: true, try_join: true, cleanup: nil)
|
90
|
+
processor.instance_variable_set(:@cpm, cpm)
|
91
|
+
expect(processor.keepalive).to be_nil
|
92
|
+
expect(processor.instance_variable_get(:@cpm)).to be_an_instance_of(Multiprocess::ChildProcessMonitor)
|
93
|
+
end
|
94
|
+
it 'recues EOFError of ChildProcessMonitor#check_heartbeat' do
|
95
|
+
cpm = double('ChildProcessMonitor', killing_status: false, try_join: true, cleanup: nil, pid: 42)
|
96
|
+
allow(cpm).to receive(:check_heartbeat).and_raise(EOFError)
|
97
|
+
immediate = double('immediate')
|
98
|
+
expect(cpm).to receive(:start_killing).with(true, processor.instance_variable_get(:@child_heartbeat_kill_delay)).exactly(:once)
|
99
|
+
processor.instance_variable_set(:@cpm, cpm)
|
100
|
+
expect(processor.keepalive).to be_nil
|
101
|
+
expect(processor.instance_variable_get(:@cpm)).to be_an_instance_of(Multiprocess::ChildProcessMonitor)
|
102
|
+
end
|
103
|
+
it 'recues an error of ChildProcessMonitor#check_heartbeat' do
|
104
|
+
cpm = double('ChildProcessMonitor', killing_status: false, try_join: true, cleanup: nil, pid: 42)
|
105
|
+
allow(cpm).to receive(:check_heartbeat).and_raise(RuntimeError)
|
106
|
+
immediate = double('immediate')
|
107
|
+
expect(cpm).to receive(:start_killing).with(true, processor.instance_variable_get(:@child_heartbeat_kill_delay)).exactly(:once)
|
108
|
+
processor.instance_variable_set(:@cpm, cpm)
|
109
|
+
expect(processor.keepalive).to be_nil
|
110
|
+
expect(processor.instance_variable_get(:@cpm)).to be_an_instance_of(Multiprocess::ChildProcessMonitor)
|
111
|
+
end
|
112
|
+
it 'calls ChildProcessMonitor#start_killing if it is dead' do
|
113
|
+
cpm = double('ChildProcessMonitor', killing_status: false, check_heartbeat: false, try_join: true, cleanup: nil, pid: 42)
|
114
|
+
immediate = double('immediate')
|
115
|
+
expect(cpm).to receive(:start_killing).with(true).exactly(:once)
|
116
|
+
processor.instance_variable_set(:@cpm, cpm)
|
117
|
+
expect(processor.keepalive).to be_nil
|
118
|
+
expect(processor.instance_variable_get(:@cpm)).to be_an_instance_of(Multiprocess::ChildProcessMonitor)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#join' do
|
123
|
+
let (:processor) {
|
124
|
+
config = {logger: double('logger').as_null_object, child_kill_interval: 0.1}
|
125
|
+
Multiprocess::ForkProcessor.new(double('runner'), double('processor_id'), config)
|
126
|
+
}
|
127
|
+
it 'calls ChildProcessMonitor#start_killing if it has ChildProcessMonitor' do
|
128
|
+
immediate = double('immediate')
|
129
|
+
cpm = double('ChildProcessMonitor', cleanup: nil)
|
130
|
+
allow(cpm).to receive(:try_join).and_return(false, true)
|
131
|
+
processor.instance_variable_set(:@cpm, cpm)
|
132
|
+
processor.join
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '#logrotated' do
|
137
|
+
let (:processor) {
|
138
|
+
config = {logger: double('logger').as_null_object}
|
139
|
+
Multiprocess::ForkProcessor.new(double('runner'), double('processor_id'), config)
|
140
|
+
}
|
141
|
+
it 'calls ChildProcessMonitor#start_killing if it has ChildProcessMonitor' do
|
142
|
+
immediate = double('immediate')
|
143
|
+
cpm = double('ChildProcessMonitor')
|
144
|
+
allow(cpm).to receive(:send_signal).with(:CONT).exactly(:once)
|
145
|
+
processor.instance_variable_set(:@cpm, cpm)
|
146
|
+
processor.logrotated
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe '#fork_child' do
|
151
|
+
it 'calls ChildProcessMonitor#start_killing if it has ChildProcessMonitor' do
|
152
|
+
config = {logger: double('logger').as_null_object}
|
153
|
+
processor = Multiprocess::ForkProcessor.new(double('runner'), double('processor_id'), config)
|
154
|
+
processor.instance_variable_set(:@last_fork_time, Float::MAX)
|
155
|
+
expect(processor.__send__(:fork_child)).to be_nil
|
156
|
+
end
|
157
|
+
it 'runs child process' do
|
158
|
+
runner = double('runner')
|
159
|
+
processor_id = double('processor_id')
|
160
|
+
expect(runner).to receive(:after_fork).exactly(:once)
|
161
|
+
expect(runner).to receive(:after_child_end).exactly(:once)
|
162
|
+
config = {logger: double('logger').as_null_object}
|
163
|
+
processor = Multiprocess::ForkProcessor.new(runner, processor_id, config)
|
164
|
+
expect(processor).to receive(:fork).and_yield
|
165
|
+
e = Exception.new
|
166
|
+
allow(processor).to receive(:exit!).and_raise(e)
|
167
|
+
expect{processor.__send__(:fork_child)}.to raise_error(e)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe PerfectQueue::Multiprocess::ThreadProcessor do
|
4
|
+
describe '.new' do
|
5
|
+
it 'returns a Multiprocess::ThreadProcessor' do
|
6
|
+
runner = double('runner')
|
7
|
+
processor_id = double('processor_id')
|
8
|
+
config = {}
|
9
|
+
processor = Multiprocess::ThreadProcessor.new(runner, processor_id, config)
|
10
|
+
expect(processor).to be_an_instance_of(Multiprocess::ThreadProcessor)
|
11
|
+
expect(processor.instance_variable_get(:@processor_id)).to eq(processor_id)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#force_stop' do
|
16
|
+
let (:processor) do
|
17
|
+
config = {logger: double('logger').as_null_object}
|
18
|
+
Multiprocess::ThreadProcessor.new(double('runner'), double('processor_id'), config)
|
19
|
+
end
|
20
|
+
it 'force_stop' do
|
21
|
+
processor.force_stop
|
22
|
+
expect(processor.instance_variable_get(:@finish_flag).set?).to be true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#run_loop' do
|
27
|
+
let (:processor) do
|
28
|
+
config = {logger: double('logger').as_null_object}
|
29
|
+
Multiprocess::ThreadProcessor.new(double('runner'), double('processor_id'), config)
|
30
|
+
end
|
31
|
+
it 'rescues error' do
|
32
|
+
pq = object_double('PerfectQueue').as_stubbed_const
|
33
|
+
allow(pq).to receive(:open).and_raise(RuntimeError)
|
34
|
+
processor.__send__(:run_loop)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#process' do
|
39
|
+
let (:runner) do
|
40
|
+
r = double('runner')
|
41
|
+
allow(r).to receive(:new).and_raise(RuntimeError)
|
42
|
+
r
|
43
|
+
end
|
44
|
+
let (:processor) do
|
45
|
+
config = {logger: double('logger').as_null_object}
|
46
|
+
Multiprocess::ThreadProcessor.new(runner, double('processor_id'), config)
|
47
|
+
end
|
48
|
+
it 'rescues error' do
|
49
|
+
expect{processor.__send__(:process, double('task', key: 1))}.to raise_error(RuntimeError)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/queue_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe Queue do
|
|
4
4
|
include QueueTest
|
5
5
|
|
6
6
|
it 'is a Queue' do
|
7
|
-
queue.class.
|
7
|
+
expect(queue.class).to eq(PerfectQueue::Queue)
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'succeess submit' do
|
@@ -15,15 +15,17 @@ describe Queue do
|
|
15
15
|
now = Time.now.to_i
|
16
16
|
queue.submit('task01', 'type1', {}, :now=>now)
|
17
17
|
|
18
|
-
|
18
|
+
expect {
|
19
|
+
allow(STDERR).to receive(:puts)
|
19
20
|
queue.submit('task01', 'type1', {}, :now=>now+1)
|
20
|
-
}.
|
21
|
+
}.to raise_error AlreadyExistsError
|
21
22
|
|
22
23
|
queue['task01'].cancel_request!(:now=>now+2)
|
23
24
|
|
24
|
-
|
25
|
+
expect {
|
26
|
+
allow(STDERR).to receive(:puts)
|
25
27
|
queue.submit('task01', 'type1', {}, :now=>now+10)
|
26
|
-
}.
|
28
|
+
}.to raise_error AlreadyExistsError
|
27
29
|
end
|
28
30
|
|
29
31
|
it 'list' do
|
@@ -36,24 +38,24 @@ describe Queue do
|
|
36
38
|
a.sort_by! {|t| t.key }
|
37
39
|
|
38
40
|
task01 = a.shift
|
39
|
-
task01.finished
|
41
|
+
expect(task01.finished?).to eq(false)
|
40
42
|
task01.type == 'type1'
|
41
|
-
task01.key.
|
42
|
-
task01.data["a"].
|
43
|
+
expect(task01.key).to eq('task01')
|
44
|
+
expect(task01.data["a"]).to eq(1)
|
43
45
|
|
44
46
|
task02 = a.shift
|
45
|
-
task02.finished
|
47
|
+
expect(task02.finished?).to eq(false)
|
46
48
|
task02.type == 'type1'
|
47
|
-
task02.key.
|
48
|
-
task02.data["a"].
|
49
|
+
expect(task02.key).to eq('task02')
|
50
|
+
expect(task02.data["a"]).to eq(2)
|
49
51
|
|
50
52
|
task03 = a.shift
|
51
|
-
task03.finished
|
53
|
+
expect(task03.finished?).to eq(false)
|
52
54
|
task03.type == 'type1'
|
53
|
-
task03.key.
|
54
|
-
task03.data["a"].
|
55
|
+
expect(task03.key).to eq('task03')
|
56
|
+
expect(task03.data["a"]).to eq(3)
|
55
57
|
|
56
|
-
a.empty
|
58
|
+
expect(a.empty?).to eq(true)
|
57
59
|
end
|
58
60
|
|
59
61
|
it 'poll' do
|
@@ -63,16 +65,16 @@ describe Queue do
|
|
63
65
|
queue.submit('task03', 'type1', {"a"=>3}, :now=>now+2)
|
64
66
|
|
65
67
|
task01 = queue.poll(:now=>now+10)
|
66
|
-
task01.key.
|
68
|
+
expect(task01.key).to eq('task01')
|
67
69
|
|
68
70
|
task02 = queue.poll(:now=>now+10)
|
69
|
-
task02.key.
|
71
|
+
expect(task02.key).to eq('task02')
|
70
72
|
|
71
73
|
task03 = queue.poll(:now=>now+10)
|
72
|
-
task03.key.
|
74
|
+
expect(task03.key).to eq('task03')
|
73
75
|
|
74
76
|
t4 = queue.poll(:now=>now+10)
|
75
|
-
t4.
|
77
|
+
expect(t4).to eq(nil)
|
76
78
|
end
|
77
79
|
|
78
80
|
it 'release' do
|
@@ -80,15 +82,15 @@ describe Queue do
|
|
80
82
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now+0)
|
81
83
|
|
82
84
|
task01 = queue.poll(:now=>now+10)
|
83
|
-
task01.key.
|
85
|
+
expect(task01.key).to eq('task01')
|
84
86
|
|
85
87
|
task02 = queue.poll(:now=>now+10)
|
86
|
-
task02.
|
88
|
+
expect(task02).to eq(nil)
|
87
89
|
|
88
90
|
task01.release!(:now=>now+10)
|
89
91
|
|
90
92
|
task03 = queue.poll(:now=>now+11)
|
91
|
-
task03.key.
|
93
|
+
expect(task03.key).to eq('task01')
|
92
94
|
end
|
93
95
|
|
94
96
|
it 'timeout' do
|
@@ -96,13 +98,13 @@ describe Queue do
|
|
96
98
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now+0)
|
97
99
|
|
98
100
|
task01 = queue.poll(:now=>now+10, :alive_time=>10)
|
99
|
-
task01.key.
|
101
|
+
expect(task01.key).to eq('task01')
|
100
102
|
|
101
103
|
task02 = queue.poll(:now=>now+15)
|
102
|
-
task02.
|
104
|
+
expect(task02).to eq(nil)
|
103
105
|
|
104
106
|
task03 = queue.poll(:now=>now+20)
|
105
|
-
task03.key.
|
107
|
+
expect(task03.key).to eq('task01')
|
106
108
|
end
|
107
109
|
|
108
110
|
it 'heartbeat' do
|
@@ -110,15 +112,15 @@ describe Queue do
|
|
110
112
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now+0)
|
111
113
|
|
112
114
|
task01 = queue.poll(:now=>now+10, :alive_time=>10)
|
113
|
-
task01.key.
|
115
|
+
expect(task01.key).to eq('task01')
|
114
116
|
|
115
117
|
task01.heartbeat!(:alive_time=>15, :now=>now+10)
|
116
118
|
|
117
119
|
task02 = queue.poll(:now=>now+20)
|
118
|
-
task02.
|
120
|
+
expect(task02).to eq(nil)
|
119
121
|
|
120
122
|
task03 = queue.poll(:now=>now+30)
|
121
|
-
task03.key.
|
123
|
+
expect(task03.key).to eq('task01')
|
122
124
|
end
|
123
125
|
|
124
126
|
it 'retry' do
|
@@ -126,15 +128,15 @@ describe Queue do
|
|
126
128
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now+0)
|
127
129
|
|
128
130
|
task01 = queue.poll(:now=>now+10, :alive_time=>10)
|
129
|
-
task01.key.
|
131
|
+
expect(task01.key).to eq('task01')
|
130
132
|
|
131
133
|
task01.retry!(:retry_wait=>15, :now=>now+10)
|
132
134
|
|
133
135
|
task02 = queue.poll(:now=>now+20)
|
134
|
-
task02.
|
136
|
+
expect(task02).to eq(nil)
|
135
137
|
|
136
138
|
task03 = queue.poll(:now=>now+30)
|
137
|
-
task03.key.
|
139
|
+
expect(task03.key).to eq('task01')
|
138
140
|
end
|
139
141
|
|
140
142
|
it 'froce_finish' do
|
@@ -142,13 +144,13 @@ describe Queue do
|
|
142
144
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now+0)
|
143
145
|
|
144
146
|
task01 = queue.poll(:now=>now+10)
|
145
|
-
task01.key.
|
147
|
+
expect(task01.key).to eq('task01')
|
146
148
|
|
147
|
-
queue['task01'].metadata.running
|
149
|
+
expect(queue['task01'].metadata.running?).to eq(true)
|
148
150
|
|
149
151
|
queue['task01'].force_finish!(:now=>now+11)
|
150
152
|
|
151
|
-
queue['task01'].metadata.finished
|
153
|
+
expect(queue['task01'].metadata.finished?).to eq(true)
|
152
154
|
end
|
153
155
|
|
154
156
|
it 'status' do
|
@@ -162,27 +164,27 @@ describe Queue do
|
|
162
164
|
#queue['task01'].metadata.cancel_requested?.should == false
|
163
165
|
|
164
166
|
task01 = queue.poll(:now=>now+10, :alive_time=>10)
|
165
|
-
task01.key.
|
167
|
+
expect(task01.key).to eq('task01')
|
166
168
|
|
167
|
-
queue['task01'].metadata.finished
|
168
|
-
queue['task01'].metadata.running
|
169
|
-
queue['task01'].metadata.waiting
|
170
|
-
queue['task01'].metadata.cancel_requested
|
169
|
+
expect(queue['task01'].metadata.finished?).to eq(false)
|
170
|
+
expect(queue['task01'].metadata.running?).to eq(true)
|
171
|
+
expect(queue['task01'].metadata.waiting?).to eq(false)
|
172
|
+
expect(queue['task01'].metadata.cancel_requested?).to eq(false)
|
171
173
|
|
172
174
|
task01.cancel_request!
|
173
175
|
|
174
176
|
# status of cancel_requested running tasks is cancel_requested
|
175
|
-
queue['task01'].metadata.finished
|
176
|
-
queue['task01'].metadata.running
|
177
|
-
queue['task01'].metadata.waiting
|
178
|
-
queue['task01'].metadata.cancel_requested
|
177
|
+
expect(queue['task01'].metadata.finished?).to eq(false)
|
178
|
+
expect(queue['task01'].metadata.running?).to eq(false)
|
179
|
+
expect(queue['task01'].metadata.waiting?).to eq(false)
|
180
|
+
expect(queue['task01'].metadata.cancel_requested?).to eq(true)
|
179
181
|
|
180
182
|
task01.finish!
|
181
183
|
|
182
|
-
queue['task01'].metadata.finished
|
183
|
-
queue['task01'].metadata.running
|
184
|
-
queue['task01'].metadata.waiting
|
185
|
-
queue['task01'].metadata.cancel_requested
|
184
|
+
expect(queue['task01'].metadata.finished?).to eq(true)
|
185
|
+
expect(queue['task01'].metadata.running?).to eq(false)
|
186
|
+
expect(queue['task01'].metadata.waiting?).to eq(false)
|
187
|
+
expect(queue['task01'].metadata.cancel_requested?).to eq(false)
|
186
188
|
end
|
187
189
|
|
188
190
|
it 'fail canceling finished task' do
|
@@ -190,39 +192,42 @@ describe Queue do
|
|
190
192
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now+0)
|
191
193
|
|
192
194
|
task01 = queue.poll(:now=>now+10, :alive_time=>10)
|
193
|
-
task01.key.
|
195
|
+
expect(task01.key).to eq('task01')
|
194
196
|
|
195
197
|
task01.finish!
|
196
198
|
|
197
|
-
|
199
|
+
expect {
|
200
|
+
allow(STDERR).to receive(:puts)
|
198
201
|
queue['task01'].cancel_request!
|
199
|
-
}.
|
202
|
+
}.to raise_error AlreadyFinishedError
|
200
203
|
end
|
201
204
|
|
202
205
|
it 'retention_time' do
|
203
206
|
now = Time.now.to_i
|
204
207
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now+0)
|
205
208
|
|
206
|
-
queue['task01'].metadata.finished
|
209
|
+
expect(queue['task01'].metadata.finished?).to eq(false)
|
207
210
|
|
208
211
|
task01 = queue.poll(:now=>now+10, :alive_time=>10)
|
209
|
-
task01.key.
|
212
|
+
expect(task01.key).to eq('task01')
|
210
213
|
|
211
214
|
task01.finish!(:now=>now+11, :retention_time=>10)
|
212
215
|
|
213
216
|
queue.poll(:now=>now+12)
|
214
217
|
|
215
|
-
queue['task01'].exists
|
218
|
+
expect(queue['task01'].exists?).to eq(true)
|
216
219
|
|
217
220
|
queue.poll(:now=>now+22)
|
218
221
|
|
219
|
-
|
222
|
+
allow(STDERR).to receive(:puts)
|
223
|
+
expect(queue['task01'].exists?).to eq(false)
|
220
224
|
end
|
221
225
|
|
222
226
|
it 'get_task_metadata failed with NotFoundError' do
|
223
|
-
|
227
|
+
expect {
|
228
|
+
allow(STDERR).to receive(:puts)
|
224
229
|
queue['task99'].metadata
|
225
|
-
}.
|
230
|
+
}.to raise_error NotFoundError
|
226
231
|
end
|
227
232
|
|
228
233
|
it 'prefetch' do
|
@@ -232,16 +237,16 @@ describe Queue do
|
|
232
237
|
queue.submit('task03', 'type3', {"a"=>3}, :now=>now+2)
|
233
238
|
|
234
239
|
tasks = queue.poll_multi(:now=>now+10, :alive_time=>10, :max_acquire=>2)
|
235
|
-
tasks.size.
|
236
|
-
tasks[0].key.
|
237
|
-
tasks[1].key.
|
240
|
+
expect(tasks.size).to eq(2)
|
241
|
+
expect(tasks[0].key).to eq('task01')
|
242
|
+
expect(tasks[1].key).to eq('task02')
|
238
243
|
|
239
244
|
tasks = queue.poll_multi(:now=>now+10, :alive_time=>10, :max_acquire=>2)
|
240
|
-
tasks.size.
|
241
|
-
tasks[0].key.
|
245
|
+
expect(tasks.size).to eq(1)
|
246
|
+
expect(tasks[0].key).to eq('task03')
|
242
247
|
|
243
248
|
tasks = queue.poll_multi(:now=>now+10, :alive_time=>10, :max_acquire=>2)
|
244
|
-
tasks.
|
249
|
+
expect(tasks).to eq(nil)
|
245
250
|
end
|
246
251
|
|
247
252
|
it 'data' do
|
@@ -249,20 +254,20 @@ describe Queue do
|
|
249
254
|
queue.submit('task01', 'type1', {"a"=>1}, :now=>now)
|
250
255
|
|
251
256
|
task01 = queue.poll(:now=>now+10)
|
252
|
-
task01.key.
|
253
|
-
task01.data.
|
257
|
+
expect(task01.key).to eq('task01')
|
258
|
+
expect(task01.data).to eq({"a"=>1})
|
254
259
|
|
255
260
|
task01.update_data!({"b"=>2})
|
256
|
-
task01.data.
|
261
|
+
expect(task01.data).to eq({"a"=>1, "b"=>2})
|
257
262
|
|
258
263
|
task01.update_data!({"a"=>3,"c"=>4})
|
259
|
-
task01.data.
|
264
|
+
expect(task01.data).to eq({"a"=>3, "b"=>2, "c"=>4})
|
260
265
|
|
261
266
|
task01.release!
|
262
267
|
|
263
268
|
task01 = queue.poll(:now=>now+10)
|
264
|
-
task01.key.
|
265
|
-
task01.data.
|
269
|
+
expect(task01.key).to eq('task01')
|
270
|
+
expect(task01.data).to eq({"a"=>3, "b"=>2, "c"=>4})
|
266
271
|
end
|
267
272
|
end
|
268
273
|
|