ayl-beanstalk 0.1.8 → 0.2.0
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/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/VERSION +1 -1
- data/ayl-beanstalk.gemspec +5 -5
- data/lib/ayl-beanstalk/engine.rb +1 -0
- data/lib/ayl-beanstalk/worker.rb +46 -13
- data/spec/ayl_worker_control_spec.rb +2 -2
- data/spec/engine_spec.rb +2 -1
- data/spec/worker_spec.rb +97 -0
- metadata +5 -5
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -30,7 +30,7 @@ GEM
|
|
30
30
|
activesupport (3.1.2)
|
31
31
|
multi_json (~> 1.0)
|
32
32
|
arel (2.2.1)
|
33
|
-
ayl (0.1
|
33
|
+
ayl (0.2.1)
|
34
34
|
beanstalk-client (1.1.1)
|
35
35
|
builder (3.0.0)
|
36
36
|
coderay (0.9.8)
|
@@ -114,7 +114,7 @@ PLATFORMS
|
|
114
114
|
ruby
|
115
115
|
|
116
116
|
DEPENDENCIES
|
117
|
-
ayl (>= 0.1
|
117
|
+
ayl (>= 0.2.1)
|
118
118
|
beanstalk-client (>= 1.1.0)
|
119
119
|
bundler (>= 1.0.0)
|
120
120
|
daemons (>= 1.1.0)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/ayl-beanstalk.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ayl-beanstalk"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["j0hnds@gmail.com"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-07-22"
|
13
13
|
s.description = "Ayl extension to provide beanstalk support."
|
14
14
|
s.email = "j0hnds@gmail.com"
|
15
15
|
s.executables = ["ayl_beanstalk", "ayl_worker", "ayl_worker_control"]
|
@@ -54,7 +54,7 @@ Gem::Specification.new do |s|
|
|
54
54
|
s.specification_version = 3
|
55
55
|
|
56
56
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
57
|
-
s.add_runtime_dependency(%q<ayl>, [">= 0.1
|
57
|
+
s.add_runtime_dependency(%q<ayl>, [">= 0.2.1"])
|
58
58
|
s.add_runtime_dependency(%q<beanstalk-client>, [">= 1.1.0"])
|
59
59
|
s.add_runtime_dependency(%q<daemons>, [">= 1.1.0"])
|
60
60
|
s.add_development_dependency(%q<rspec>, [">= 2.3.0"])
|
@@ -63,7 +63,7 @@ Gem::Specification.new do |s|
|
|
63
63
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
64
64
|
s.add_development_dependency(%q<pry>, [">= 0"])
|
65
65
|
else
|
66
|
-
s.add_dependency(%q<ayl>, [">= 0.1
|
66
|
+
s.add_dependency(%q<ayl>, [">= 0.2.1"])
|
67
67
|
s.add_dependency(%q<beanstalk-client>, [">= 1.1.0"])
|
68
68
|
s.add_dependency(%q<daemons>, [">= 1.1.0"])
|
69
69
|
s.add_dependency(%q<rspec>, [">= 2.3.0"])
|
@@ -73,7 +73,7 @@ Gem::Specification.new do |s|
|
|
73
73
|
s.add_dependency(%q<pry>, [">= 0"])
|
74
74
|
end
|
75
75
|
else
|
76
|
-
s.add_dependency(%q<ayl>, [">= 0.1
|
76
|
+
s.add_dependency(%q<ayl>, [">= 0.2.1"])
|
77
77
|
s.add_dependency(%q<beanstalk-client>, [">= 1.1.0"])
|
78
78
|
s.add_dependency(%q<daemons>, [">= 1.1.0"])
|
79
79
|
s.add_dependency(%q<rspec>, [">= 2.3.0"])
|
data/lib/ayl-beanstalk/engine.rb
CHANGED
@@ -36,6 +36,7 @@ module Ayl
|
|
36
36
|
pool.yput(message.to_hash, message.options.priority, message.options.delay, message.options.time_to_run)
|
37
37
|
rescue Exception => ex
|
38
38
|
logger.error "Error submitting message to beanstalk: #{ex}"
|
39
|
+
Ayl::Mailer.instance.deliver_message("Error submitting message to beanstalk", ex)
|
39
40
|
end
|
40
41
|
end
|
41
42
|
end
|
data/lib/ayl-beanstalk/worker.rb
CHANGED
@@ -14,40 +14,73 @@ module Ayl
|
|
14
14
|
|
15
15
|
def process_messages
|
16
16
|
logger.debug "#{self.class.name} entering process_messages loop watching: #{Ayl::MessageOptions.default_queue_name}"
|
17
|
-
# trap('TERM') { puts "## Got the term signal"; @stop = true }
|
18
|
-
# trap('INT') { puts "## Got the int signal"; @stop = true }
|
19
17
|
# Set the queue that we will be watching
|
20
18
|
pool.watch(Ayl::MessageOptions.default_queue_name)
|
21
19
|
while true
|
22
20
|
break if @stop
|
23
|
-
job =
|
21
|
+
job = nil
|
22
|
+
begin
|
23
|
+
job = pool.reserve
|
24
|
+
rescue Exception => ex
|
25
|
+
logger.error "#{self.class.name} Exception in process_messages: #{ex}\n#{ex.backtrace.join("\n")}"
|
26
|
+
Ayl::Mailer.instance.deliver_message("#{self.class.name} Exception in process_messages.", ex)
|
27
|
+
delete_job(job) unless job.nil?
|
28
|
+
next
|
29
|
+
end
|
24
30
|
break if job.nil?
|
31
|
+
msg = nil
|
25
32
|
begin
|
26
|
-
|
27
|
-
|
33
|
+
msg = Ayl::Message.from_hash(job.ybody)
|
34
|
+
process_message(msg)
|
35
|
+
delete_job(job)
|
28
36
|
rescue Ayl::UnrecoverableMessageException => ex
|
29
37
|
logger.error "#{self.class.name} Unrecoverable exception in process_messages: #{ex}"
|
30
|
-
|
38
|
+
Ayl::Mailer.instance.deliver_message("#{self.class.name} Unrecoverable exception in process_messages", ex)
|
39
|
+
delete_job(job)
|
31
40
|
rescue SystemExit
|
32
41
|
# This exception is raised when 'Kernel.exit' is called. In this case
|
33
42
|
# we want to make sure the job is deleted, then we simply re-raise
|
34
43
|
# the exception and we go bye-bye.
|
35
|
-
job
|
44
|
+
delete_job(job)
|
36
45
|
raise
|
37
46
|
rescue Exception => ex
|
38
47
|
logger.error "#{self.class.name} Exception in process_messages: #{ex}\n#{ex.backtrace.join("\n")}"
|
39
|
-
|
40
|
-
|
41
|
-
logger.debug "Deleting job"
|
42
|
-
job.delete
|
48
|
+
if msg.options.decay_failed_job
|
49
|
+
handle_job_decay(job, ex)
|
43
50
|
else
|
44
|
-
|
45
|
-
|
51
|
+
delete_job(job)
|
52
|
+
Ayl::Mailer.instance.deliver_message("#{self.class.name} Exception in process_messages.", ex)
|
46
53
|
end
|
47
54
|
end
|
48
55
|
end
|
49
56
|
end
|
50
57
|
|
58
|
+
def handle_job_decay(job, ex)
|
59
|
+
logger.debug "Age of job: #{job.age}"
|
60
|
+
if job.age > 60
|
61
|
+
Ayl::Mailer.instance.deliver_message("#{self.class.name} Deleting decayed job; it just took too long.", ex)
|
62
|
+
logger.debug "Deleting job"
|
63
|
+
delete_job(job)
|
64
|
+
else
|
65
|
+
logger.debug "Decaying job"
|
66
|
+
decay_job(job)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete_job(job)
|
71
|
+
job.delete
|
72
|
+
rescue RuntimeError => ex
|
73
|
+
logger.error "#{self.class.name} Error deleting job: #{ex}\n#{ex.backtrace.join("\n")}"
|
74
|
+
Ayl::Mailer.instance.deliver_message("#{self.class.name} Error deleting job", ex)
|
75
|
+
end
|
76
|
+
|
77
|
+
def decay_job(job)
|
78
|
+
job.decay
|
79
|
+
rescue RuntimeError => ex
|
80
|
+
logger.error "#{self.class.name} Error decaying job: #{ex}\n#{ex.backtrace.join("\n")}"
|
81
|
+
Ayl::Mailer.instance.deliver_message("#{self.class.name} Error decaying job", ex)
|
82
|
+
end
|
83
|
+
|
51
84
|
end
|
52
85
|
|
53
86
|
end
|
@@ -13,14 +13,14 @@ describe 'ayl_worker_control script' do
|
|
13
13
|
|
14
14
|
it "should honor the use of the -a option to name the daemon" do
|
15
15
|
ARGV.concat [ '--', '--pid-path', '/tmp', '--name', 'the_name' ]
|
16
|
-
Daemons.should_receive(:run).with(anything, { :log_dir => '/tmp', :log_output => true, :dir_mode => :normal, :dir => '/tmp', :app_name => 'the_name' })
|
16
|
+
Daemons.should_receive(:run).with(anything, { :log_dir => '/tmp', :log_output => true, :dir_mode => :normal, :dir => '/tmp', :multiple => true, :app_name => 'the_name' })
|
17
17
|
|
18
18
|
load(@ayl_control_script, true)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should assume the use of the script for the daemon name if no name argument is specified" do
|
22
22
|
ARGV.concat [ '--', '--pid-path', '/tmp' ]
|
23
|
-
Daemons.should_receive(:run).with(anything, { :log_dir => '/tmp', :log_output => true, :dir_mode => :normal, :dir => '/tmp' })
|
23
|
+
Daemons.should_receive(:run).with(anything, { :log_dir => '/tmp', :log_output => true, :dir_mode => :normal, :dir => '/tmp', :multiple => true })
|
24
24
|
|
25
25
|
load(@ayl_control_script, true)
|
26
26
|
end
|
data/spec/engine_spec.rb
CHANGED
@@ -11,6 +11,7 @@ describe Ayl::Beanstalk::Engine do
|
|
11
11
|
Kernel.stub(:puts)
|
12
12
|
@engine = Ayl::Beanstalk::Engine.new
|
13
13
|
@engine.stub_chain(:logger, :info)
|
14
|
+
@engine.stub_chain(:logger, :debug)
|
14
15
|
@engine.stub_chain(:logger, :error)
|
15
16
|
end
|
16
17
|
|
@@ -46,7 +47,7 @@ describe Ayl::Beanstalk::Engine do
|
|
46
47
|
it "should submit the specified message to beanstalk" do
|
47
48
|
mock_pool = mock("Beanstalk::Pool")
|
48
49
|
mock_pool.should_receive(:use).with("default")
|
49
|
-
mock_pool.should_receive(:yput).with( { :type => :ayl, :code => "23.to_s(2)" }, 512, 0, 120)
|
50
|
+
mock_pool.should_receive(:yput).with( { :type => :ayl, :decay_failed_job => false, :code => "23.to_s(2)" }, 512, 0, 120)
|
50
51
|
|
51
52
|
::Beanstalk::Pool.should_receive(:new).with([ "localhost:11300" ]).and_return(mock_pool)
|
52
53
|
|
data/spec/worker_spec.rb
CHANGED
@@ -12,6 +12,7 @@ describe Ayl::Beanstalk::Worker do
|
|
12
12
|
@worker = Ayl::Beanstalk::Worker.new
|
13
13
|
@worker.stub_chain(:logger, :info)
|
14
14
|
@worker.stub_chain(:logger, :error)
|
15
|
+
@worker.stub_chain(:logger, :debug)
|
15
16
|
Ayl::MessageOptions.default_queue_name = 'default'
|
16
17
|
end
|
17
18
|
|
@@ -90,6 +91,32 @@ describe Ayl::Beanstalk::Worker do
|
|
90
91
|
@worker.process_messages
|
91
92
|
end
|
92
93
|
|
94
|
+
it "should not decay a job that receives an active-record exception when the default message options are used" do
|
95
|
+
mock_job = mock("Beanstalk::Job")
|
96
|
+
mock_job.should_not_receive(:decay)
|
97
|
+
mock_job.should_receive(:ybody).and_return({ :type => :ayl, :code => "Dog" })
|
98
|
+
mock_job.should_not_receive(:age)
|
99
|
+
mock_job.should_receive(:delete)
|
100
|
+
|
101
|
+
mock_pool = mock("Beanstalk::Pool")
|
102
|
+
mock_pool.should_receive(:watch).with("default")
|
103
|
+
mock_pool.should_receive(:reserve).and_return(mock_job, nil)
|
104
|
+
|
105
|
+
mock_message = mock("Ayl::Message")
|
106
|
+
mock_message.should_receive(:evaluate).and_raise(ActiveRecord::RecordNotFound)
|
107
|
+
mock_message.should_receive(:options).and_return do
|
108
|
+
mock("Options").tap do | mock_opts |
|
109
|
+
mock_opts.should_receive(:decay_failed_job).and_return(false)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
Ayl::Message.stub(:from_hash).with({ :type => :ayl, :code => "Dog" }).and_return(mock_message)
|
113
|
+
|
114
|
+
::Beanstalk::Pool.should_receive(:new).with([ "localhost:11300" ]).and_return(mock_pool)
|
115
|
+
|
116
|
+
@worker.process_messages
|
117
|
+
|
118
|
+
end
|
119
|
+
|
93
120
|
it "should decay a job that receives an active-record exception on receipt of message that is less than 60 seconds old" do
|
94
121
|
mock_job = mock("Beanstalk::Job")
|
95
122
|
mock_job.should_receive(:decay)
|
@@ -102,6 +129,11 @@ describe Ayl::Beanstalk::Worker do
|
|
102
129
|
|
103
130
|
mock_message = mock("Ayl::Message")
|
104
131
|
mock_message.should_receive(:evaluate).and_raise(ActiveRecord::RecordNotFound)
|
132
|
+
mock_message.should_receive(:options).and_return do
|
133
|
+
mock("Options").tap do | mock_opts |
|
134
|
+
mock_opts.should_receive(:decay_failed_job).and_return(true)
|
135
|
+
end
|
136
|
+
end
|
105
137
|
Ayl::Message.stub(:from_hash).with({ :type => :ayl, :code => "Dog" }).and_return(mock_message)
|
106
138
|
|
107
139
|
::Beanstalk::Pool.should_receive(:new).with([ "localhost:11300" ]).and_return(mock_pool)
|
@@ -121,12 +153,77 @@ describe Ayl::Beanstalk::Worker do
|
|
121
153
|
|
122
154
|
mock_message = mock("Ayl::Message")
|
123
155
|
mock_message.should_receive(:evaluate).and_raise(ActiveRecord::RecordNotFound)
|
156
|
+
mock_message.should_receive(:options).and_return do
|
157
|
+
mock("Options").tap do | mock_opts |
|
158
|
+
mock_opts.should_receive(:decay_failed_job).and_return(true)
|
159
|
+
end
|
160
|
+
end
|
124
161
|
Ayl::Message.stub(:from_hash).with({ :type => :ayl, :code => "Dog" }).and_return(mock_message)
|
125
162
|
|
126
163
|
::Beanstalk::Pool.should_receive(:new).with([ "localhost:11300" ]).and_return(mock_pool)
|
127
164
|
|
128
165
|
@worker.process_messages
|
129
166
|
end
|
167
|
+
|
168
|
+
it "should not attempt to decay the job if there is a problem deleting a job after the message is successfully processed" do
|
169
|
+
|
170
|
+
mock_job = mock("Beanstalk::Job")
|
171
|
+
mock_job.should_receive(:delete).and_raise("Delete failed for some reason")
|
172
|
+
mock_job.should_receive(:ybody).and_return({ :type => :ayl, :code => "23.to_s(2)" })
|
173
|
+
mock_job.should_not_receive(:age)
|
174
|
+
|
175
|
+
mock_pool = mock("Beanstalk::Pool")
|
176
|
+
mock_pool.should_receive(:watch).with("default")
|
177
|
+
mock_pool.should_receive(:reserve).and_return(mock_job, nil)
|
178
|
+
|
179
|
+
mock_message = mock("Ayl::Message")
|
180
|
+
mock_message.should_receive(:evaluate)
|
181
|
+
Ayl::Message.stub(:from_hash).with({ :type => :ayl, :code => "23.to_s(2)" }).and_return(mock_message)
|
182
|
+
|
183
|
+
::Beanstalk::Pool.should_receive(:new).with([ "localhost:11300" ]).and_return(mock_pool)
|
184
|
+
|
185
|
+
expect { @worker.process_messages }.not_to raise_error
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
context '#delete_job' do
|
190
|
+
|
191
|
+
before(:each) do
|
192
|
+
Kernel.stub(:puts)
|
193
|
+
@worker = Ayl::Beanstalk::Worker.new
|
194
|
+
@worker.stub_chain(:logger, :info)
|
195
|
+
@worker.stub_chain(:logger, :error)
|
196
|
+
@worker.stub_chain(:logger, :debug)
|
197
|
+
Ayl::MessageOptions.default_queue_name = 'default'
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should not raise an exception if the job.delete fail" do
|
201
|
+
mock_job = mock("Job")
|
202
|
+
mock_job.should_receive(:delete).and_raise("Delete failed for some reason")
|
203
|
+
|
204
|
+
expect { @worker.delete_job(mock_job) }.not_to raise_error
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
context '#decay_job' do
|
210
|
+
|
211
|
+
before(:each) do
|
212
|
+
Kernel.stub(:puts)
|
213
|
+
@worker = Ayl::Beanstalk::Worker.new
|
214
|
+
@worker.stub_chain(:logger, :info)
|
215
|
+
@worker.stub_chain(:logger, :error)
|
216
|
+
@worker.stub_chain(:logger, :debug)
|
217
|
+
Ayl::MessageOptions.default_queue_name = 'default'
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should not raise an exception if the job.delete fail" do
|
221
|
+
mock_job = mock("Job")
|
222
|
+
mock_job.should_receive(:decay).and_raise("Decay failed for some reason")
|
223
|
+
|
224
|
+
expect { @worker.decay_job(mock_job) }.not_to raise_error
|
225
|
+
end
|
226
|
+
|
130
227
|
end
|
131
228
|
|
132
229
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ayl-beanstalk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
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: 2013-
|
12
|
+
date: 2013-07-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ayl
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.1
|
21
|
+
version: 0.2.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.1
|
29
|
+
version: 0.2.1
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: beanstalk-client
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -190,7 +190,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
190
190
|
version: '0'
|
191
191
|
segments:
|
192
192
|
- 0
|
193
|
-
hash:
|
193
|
+
hash: 2726199589731342968
|
194
194
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
195
|
none: false
|
196
196
|
requirements:
|