queueing_rabbit 0.3.5 → 0.3.6
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.
@@ -89,6 +89,8 @@ module QueueingRabbit
|
|
89
89
|
|
90
90
|
def close
|
91
91
|
@connection.close
|
92
|
+
yield if block_given?
|
93
|
+
@continue_worker_loop = false
|
92
94
|
end
|
93
95
|
|
94
96
|
def open?
|
@@ -97,7 +99,9 @@ module QueueingRabbit
|
|
97
99
|
|
98
100
|
def begin_worker_loop
|
99
101
|
yield
|
100
|
-
@
|
102
|
+
@continue_worker_loop = true
|
103
|
+
# We may need to add signal handling here
|
104
|
+
sleep 2 while @continue_worker_loop
|
101
105
|
end
|
102
106
|
|
103
107
|
private
|
@@ -8,10 +8,6 @@ namespace :queueing_rabbit do
|
|
8
8
|
task :work => :setup do
|
9
9
|
require 'queueing_rabbit'
|
10
10
|
|
11
|
-
if ENV['PIDFILE'] && File.exists?(ENV['PIDFILE'])
|
12
|
-
abort "PID file already exists. Is the worker running?"
|
13
|
-
end
|
14
|
-
|
15
11
|
jobs = (ENV['JOBS'] || ENV['JOB']).to_s.split(',')
|
16
12
|
|
17
13
|
begin
|
@@ -28,10 +24,11 @@ namespace :queueing_rabbit do
|
|
28
24
|
Process.daemon(true)
|
29
25
|
end
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
begin
|
28
|
+
worker.use_pidfile(ENV['PIDFILE']) if ENV['PIDFILE']
|
29
|
+
worker.work!
|
30
|
+
rescue QueueingRabbit::Worker::WorkerError => e
|
31
|
+
abort e.message
|
32
|
+
end
|
36
33
|
end
|
37
34
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module QueueingRabbit
|
2
2
|
class Worker
|
3
|
+
|
4
|
+
class WorkerError < RuntimeError; end
|
5
|
+
|
3
6
|
include QueueingRabbit::Logging
|
4
7
|
|
5
8
|
attr_accessor :jobs
|
@@ -13,28 +16,37 @@ module QueueingRabbit
|
|
13
16
|
end
|
14
17
|
|
15
18
|
def work
|
16
|
-
|
17
|
-
trap_signals(conn)
|
19
|
+
trap_signals
|
18
20
|
|
19
21
|
QueueingRabbit.trigger_event(:worker_ready)
|
20
22
|
|
21
|
-
jobs.each { |job| run_job(
|
23
|
+
jobs.each { |job| run_job(QueueingRabbit.connection, job) }
|
22
24
|
|
23
25
|
QueueingRabbit.trigger_event(:consuming_started)
|
24
26
|
end
|
25
27
|
|
26
28
|
def work!
|
27
|
-
|
28
|
-
|
29
|
-
|
29
|
+
info "starting a new queueing_rabbit worker #{self}"
|
30
|
+
|
31
|
+
QueueingRabbit.begin_worker_loop { work }
|
30
32
|
end
|
31
33
|
|
32
34
|
def use_pidfile(filename)
|
33
|
-
|
35
|
+
@pidfile = filename
|
36
|
+
cleanup_pidfile
|
37
|
+
File.open(@pidfile, 'w') { |f| f << pid }
|
34
38
|
end
|
35
39
|
|
36
40
|
def remove_pidfile
|
37
|
-
File.delete(@pidfile) if
|
41
|
+
File.delete(@pidfile) if pidfile_exists?
|
42
|
+
end
|
43
|
+
|
44
|
+
def read_pidfile
|
45
|
+
File.read(@pidfile).to_i if pidfile_exists?
|
46
|
+
end
|
47
|
+
|
48
|
+
def pidfile_exists?
|
49
|
+
@pidfile && File.exists?(@pidfile)
|
38
50
|
end
|
39
51
|
|
40
52
|
def pid
|
@@ -45,6 +57,16 @@ module QueueingRabbit
|
|
45
57
|
"PID=#{pid}, JOBS=#{jobs.join(',')}"
|
46
58
|
end
|
47
59
|
|
60
|
+
def stop
|
61
|
+
return unless QueueingRabbit.connection
|
62
|
+
|
63
|
+
QueueingRabbit.connection.close {
|
64
|
+
info "gracefully shutting down the worker #{self}"
|
65
|
+
remove_pidfile
|
66
|
+
QueueingRabbit.trigger_event(:consuming_done)
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
48
70
|
private
|
49
71
|
|
50
72
|
def validate_jobs
|
@@ -80,7 +102,7 @@ module QueueingRabbit
|
|
80
102
|
elsif job <= QueueingRabbit::AbstractJob
|
81
103
|
job.new(payload, metadata).perform
|
82
104
|
else
|
83
|
-
error "
|
105
|
+
error "don't know how to perform job #{job}"
|
84
106
|
end
|
85
107
|
end
|
86
108
|
|
@@ -89,16 +111,20 @@ module QueueingRabbit
|
|
89
111
|
$stderr.sync = true
|
90
112
|
end
|
91
113
|
|
92
|
-
def trap_signals
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
remove_pidfile
|
97
|
-
}
|
98
|
-
end
|
114
|
+
def trap_signals
|
115
|
+
Signal.trap("TERM") { stop }
|
116
|
+
Signal.trap("INT") { stop }
|
117
|
+
end
|
99
118
|
|
100
|
-
|
101
|
-
|
119
|
+
def cleanup_pidfile
|
120
|
+
return unless pid_in_file = read_pidfile
|
121
|
+
Process.getpgid(pid_in_file)
|
122
|
+
fatal "failed to use the pidfile #{@pidfile}. It is already " \
|
123
|
+
"in use by a process with pid=#{pid_in_file}."
|
124
|
+
raise WorkerError.new('The pidfile is already in use.')
|
125
|
+
rescue Errno::ESRCH
|
126
|
+
info "found abandoned pidfile: #{@pidfile}. Can be safely overwritten."
|
102
127
|
end
|
128
|
+
|
103
129
|
end
|
104
130
|
end
|
@@ -126,5 +126,23 @@ describe QueueingRabbit::Client::Bunny do
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
+
describe '#close' do
|
130
|
+
|
131
|
+
before do
|
132
|
+
connection.should_receive(:close)
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'closes the connection and yields a block if given' do
|
136
|
+
expect { |b| client.close(&b) }.to yield_control
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'discontinues the worker loop' do
|
140
|
+
expect { |b| client.close(&b) }.
|
141
|
+
to change{client.instance_variable_get(:@continue_worker_loop)}.
|
142
|
+
to(false)
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
129
147
|
end
|
130
148
|
end
|
@@ -69,7 +69,7 @@ describe QueueingRabbit::Worker do
|
|
69
69
|
|
70
70
|
describe '#work' do
|
71
71
|
before do
|
72
|
-
QueueingRabbit.
|
72
|
+
QueueingRabbit.stub(:connection).and_return(connection)
|
73
73
|
[class_based_job, instance_based_job].each do |job|
|
74
74
|
QueueingRabbit.should_receive(:follow_job_requirements).
|
75
75
|
with(job).
|
@@ -106,13 +106,45 @@ describe QueueingRabbit::Worker do
|
|
106
106
|
let(:file_name) { mock }
|
107
107
|
let(:file) { mock }
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
context 'given pidfile is already in use' do
|
110
|
+
|
111
|
+
it 'raises a worker error' do
|
112
|
+
File.stub(:exists?).with(file_name).and_return(true)
|
113
|
+
File.should_receive(:read).with(file_name).and_return('123')
|
114
|
+
Process.should_receive(:getpgid).with(123).and_return(123)
|
115
|
+
expect { subject.use_pidfile(file_name) }.
|
116
|
+
to raise_error(QueueingRabbit::Worker::WorkerError)
|
117
|
+
end
|
118
|
+
|
112
119
|
end
|
113
120
|
|
114
|
-
|
115
|
-
|
121
|
+
context 'given pidfile is not in use' do
|
122
|
+
|
123
|
+
before do
|
124
|
+
File.should_receive(:open).with(file_name, 'w').and_yield(file)
|
125
|
+
file.should_receive(:<<).with(Process.pid)
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'there is an abandoned pidfile' do
|
129
|
+
|
130
|
+
it 'removes the abandoned pidfile and writes pid to a file' do
|
131
|
+
File.stub(:exists?).with(file_name).and_return(true)
|
132
|
+
File.should_receive(:read).with(file_name).and_return('123')
|
133
|
+
Process.should_receive(:getpgid).with(123).and_raise(Errno::ESRCH)
|
134
|
+
subject.use_pidfile(file_name)
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'new pidfile' do
|
140
|
+
|
141
|
+
it 'creates a pidfile' do
|
142
|
+
File.stub(:exists?).with(file_name).and_return(false)
|
143
|
+
subject.use_pidfile(file_name)
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
116
148
|
end
|
117
149
|
end
|
118
150
|
|
@@ -133,5 +165,25 @@ describe QueueingRabbit::Worker do
|
|
133
165
|
describe "#pid" do
|
134
166
|
its(:pid) { should == Process.pid }
|
135
167
|
end
|
168
|
+
|
169
|
+
describe '#stop' do
|
170
|
+
|
171
|
+
let(:file_name) { mock }
|
172
|
+
|
173
|
+
before do
|
174
|
+
subject.instance_variable_set(:@pidfile, file_name)
|
175
|
+
QueueingRabbit.stub(:connection).and_return(connection)
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'closes the connection, removes the pidfile and reports the event' do
|
179
|
+
connection.should_receive(:close).and_yield
|
180
|
+
File.stub(:exists?).with(file_name).and_return(true)
|
181
|
+
File.should_receive(:delete).with(file_name)
|
182
|
+
QueueingRabbit.should_receive(:trigger_event).with(:consuming_done)
|
183
|
+
subject.stop
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
136
188
|
end
|
137
189
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: queueing_rabbit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-01-
|
12
|
+
date: 2014-01-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: amqp
|
@@ -172,7 +172,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
172
172
|
version: '0'
|
173
173
|
segments:
|
174
174
|
- 0
|
175
|
-
hash: -
|
175
|
+
hash: -1747676710658043461
|
176
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
177
|
none: false
|
178
178
|
requirements:
|
@@ -181,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
181
181
|
version: '0'
|
182
182
|
segments:
|
183
183
|
- 0
|
184
|
-
hash: -
|
184
|
+
hash: -1747676710658043461
|
185
185
|
requirements: []
|
186
186
|
rubyforge_project:
|
187
187
|
rubygems_version: 1.8.23
|