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 CHANGED
@@ -2,7 +2,7 @@ source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
- gem 'ayl', ">= 0.1.0"
5
+ gem 'ayl', ">= 0.2.1"
6
6
  gem 'beanstalk-client', ">= 1.1.0"
7
7
  gem 'daemons', ">= 1.1.0"
8
8
 
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.0)
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.0)
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.8
1
+ 0.2.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "ayl-beanstalk"
8
- s.version = "0.1.8"
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-02-25"
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.0"])
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.0"])
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.0"])
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"])
@@ -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
@@ -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 = pool.reserve
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
- process_message(Ayl::Message.from_hash(job.ybody))
27
- job.delete
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
- job.delete
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.delete
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
- logger.debug "Age of job: #{job.age}"
40
- if job.age > 60
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
- logger.debug "Decaying job"
45
- job.decay
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.1.8
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-02-25 00:00:00.000000000 Z
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.0
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.0
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: -880016066289096428
193
+ hash: 2726199589731342968
194
194
  required_rubygems_version: !ruby/object:Gem::Requirement
195
195
  none: false
196
196
  requirements: