perfectqueue 0.8.44.1 → 0.8.45
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.
- 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
|
|