freekiqs 4.1.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0a7ee677e8d100c7405dc91f9d4c341d7f7a8986
4
- data.tar.gz: 0281092a960af50ca75ed3b03370bd7a86b1ae17
3
+ metadata.gz: 44594d919a76aa86c249eb5fe88a9af8f95ba253
4
+ data.tar.gz: b788548a59466399a3e58ed192cd4344b6d37df4
5
5
  SHA512:
6
- metadata.gz: 35984aad9ab4d0fec1d33f07469ba0f82ff83a5b3cdeaecb39f1bbdb42f56ec9566df45c8735970034f99294919790481983047141a89750118845d46d7a3ad9
7
- data.tar.gz: d932c98cefbdcc672d00c2e85ae16a86b6b4b70cb719403a462b8981dacd22fca4f0cbaa7cf90735879cbd8cbc8efe3a5f221eaa9d8cd033962e0efd841dbaf4
6
+ metadata.gz: fbeab3d19cea8a86adf9e8a47e9cfab8e3739da4d53157fe82418bd838550736c77a414e81b505ccb7dba7663292058bc63b133fabebc2f4048dda0f8ed79f41
7
+ data.tar.gz: f0e33f9fc4851bfbfb1f4ff1b6f09cdc14dd4ba282e413b8c8e3c69366a4006f63af5edc63eda77b970660d9baa91d17da57468b06f9c5820a625bdb68ebdff0
data/.gitignore CHANGED
@@ -3,3 +3,6 @@ gemfiles/*.lock
3
3
  Gemfile.lock
4
4
  .ruby-version
5
5
  pkg
6
+ /.bundle
7
+ /.vagrant
8
+ /ubuntu-*-console.log
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/Gemfile CHANGED
@@ -5,5 +5,5 @@ gemspec
5
5
  gem 'rake'
6
6
 
7
7
  group :test do
8
- gem 'rspec', '~> 3.1'
8
+ gem 'rspec', '~> 3.6'
9
9
  end
data/README.md CHANGED
@@ -3,13 +3,13 @@
3
3
  Sidekiq middleware that allows capturing exceptions thrown
4
4
  by failed jobs and wrapping them with a `FreekiqException` exception class
5
5
  that can be filtered by monitoring tools such as New Relic and
6
- Honeybadger.
6
+ Rollbar.
7
7
 
8
8
  Configuration example (in config/initializers/sidekiq.rb):
9
9
  ``` ruby
10
10
  Sidekiq.configure_server do |config|
11
11
  config.server_middleware do |chain|
12
- chain.insert_after Sidekiq::Middleware::Server::RetryJobs, Sidekiq::Middleware::Server::Freekiqs
12
+ chain.add Sidekiq::Middleware::Server::Freekiqs
13
13
  end
14
14
  end
15
15
  ```
@@ -19,7 +19,7 @@ Worker example:
19
19
  class MyWorker
20
20
  include Sidekiq::Worker
21
21
  sidekiq_options freekiqs: 3
22
- #
22
+
23
23
  def perform(param)
24
24
  ...
25
25
  end
@@ -35,7 +35,7 @@ Example:
35
35
  ``` ruby
36
36
  Sidekiq.configure_server do |config|
37
37
  config.server_middleware do |chain|
38
- chain.insert_after Sidekiq::Middleware::Server::RetryJobs, Sidekiq::Middleware::Server::Freekiqs, freekiqs: 3
38
+ chain.add Sidekiq::Middleware::Server::Freekiqs, freekiqs: 3
39
39
  end
40
40
  end
41
41
  ```
@@ -44,6 +44,17 @@ A callback can be fired when a freekiq happens.
44
44
  This can be useful for tracking or logging freekiqs separately from the sidekiq logs.
45
45
 
46
46
  Example:
47
+ ``` ruby
48
+ Sidekiq.configure_server do |config|
49
+ config.server_middleware do |chain|
50
+ chain.add Sidekiq::Middleware::Server::Freekiqs, callback: ->(worker, msg, queue) do
51
+ Librato::Metrics.submit freekiqs: { value: 1, source: worker.class.name }
52
+ end
53
+ end
54
+ end
55
+ ```
56
+
57
+ Or callback can be set outside middleware configuration:
47
58
  ``` ruby
48
59
  Sidekiq::Middleware::Server::Freekiqs::callback = ->(worker, msg, queue) do
49
60
  Librato::Metrics.submit freekiqs: { value: 1, source: worker.class.name }
@@ -57,7 +68,7 @@ Example:
57
68
  class MyWorker
58
69
  include Sidekiq::Worker
59
70
  sidekiq_options freekiqs: 1, freekiq_for: ['MyError']
60
- #
71
+
61
72
  def perform(param)
62
73
  ...
63
74
  end
@@ -67,8 +78,8 @@ In this case, if MyWorker fails with a MyError it will get 1 freekiq.
67
78
  All other errors thrown by this worker will get no freekiqs.
68
79
 
69
80
 
70
- If a `freekiq_for` contains a class name as a constant, any exception is that class
71
- *or a subclass* of that class will get freekiq'd.
81
+ If a `freekiq_for` contains a class name as a constant, any exception of that class
82
+ type *or a subclass* of that class will get freekiq'd.
72
83
 
73
84
  Example:
74
85
  ``` ruby
@@ -77,7 +88,7 @@ Example:
77
88
  class MyWorker
78
89
  include Sidekiq::Worker
79
90
  sidekiq_options freekiqs: 1, freekiq_for: [MyError]
80
- #
91
+
81
92
  def perform(param)
82
93
  ...
83
94
  end
@@ -85,6 +96,10 @@ Example:
85
96
  ```
86
97
  If MyWorker throws a SubMyError or MyError, it will get freekiq'd.
87
98
 
99
+ ## Sidekiq Versions
100
+
101
+ Version 5 of this gem only works with Sidekiq 5 and higher. If you are using
102
+ an older version of Sidekiq, you'll need to use version [4.1.0](https://github.com/BookBub/freekiqs/tree/v4.1.0).
88
103
 
89
104
  ## Overview
90
105
 
@@ -95,7 +110,8 @@ tools. If job fails more times than configured "freekiqs", thrown
95
110
  exception will not be wrapped. That should result in normal operation
96
111
  and the exception showing up in monitoring tools.
97
112
 
98
- Implementation Details:
113
+ #### Implementation Details
114
+
99
115
  This relies on Sidekiq's built-in retry handling. Specifically, its
100
116
  `retry_count` value. When a job first fails, its `retry_count` value
101
117
  is nil (because it hasn't actually been retried yet). That exception,
data/Vagrantfile ADDED
@@ -0,0 +1,31 @@
1
+ Vagrant.configure(2) do |config|
2
+ config.vm.box = 'ubuntu/xenial64'
3
+
4
+ config.vm.network :private_network, ip: '192.168.33.69'
5
+ config.vm.network :forwarded_port, host: 2202, guest: 22, id: 'ssh', auto_correct: true
6
+
7
+ config.vm.synced_folder '.', '/vagrant', type: 'nfs'
8
+
9
+ config.vm.provider :virtualbox do |vb|
10
+ vb.name = 'freekiqs'
11
+ vb.memory = 2048
12
+ vb.cpus = 2
13
+ end
14
+
15
+ config.vm.provision :shell, inline: <<-SCRIPT
16
+ apt-get update
17
+ apt-get upgrade
18
+ apt-get install -y git gnupg2 redis-server
19
+ SCRIPT
20
+
21
+ config.vm.provision :shell, privileged: false, inline: <<-SCRIPT
22
+ gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
23
+ curl -sSL https://get.rvm.io | bash -s stable --quiet-curl --with-gems=bundler
24
+ source "$HOME/.rvm/scripts/rvm"
25
+ rvm --quiet-curl install 2.3.4
26
+ rvm use 2.3.4 --default
27
+ cd /vagrant
28
+ bundle install --full-index -j4
29
+ echo 'cd /vagrant' >> ~/.bash_profile
30
+ SCRIPT
31
+ end
data/circle.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  machine:
2
2
  ruby:
3
- version: 2.3.0
3
+ version: 2.3.4
4
4
  services:
5
5
  - redis
data/freekiqs.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = 'freekiqs'
5
- gem.version = '4.1.0'
5
+ gem.version = '5.0.0'
6
6
  gem.authors = ['Rob Lewis']
7
7
  gem.email = ['rob@bookbub.com']
8
8
  gem.summary = 'Sidekiq middleware extending RetryJobs to allow silient errors.'
@@ -14,8 +14,8 @@ Gem::Specification.new do |gem|
14
14
  gem.files = `git ls-files`.split("\n")
15
15
  gem.test_files = `git ls-files -- spec/*`.split("\n")
16
16
  gem.require_paths = ['lib']
17
- gem.required_ruby_version = '>= 1.9.3'
17
+ gem.required_ruby_version = '>= 2.2.2'
18
18
 
19
- gem.add_dependency 'sidekiq', '>= 4.0.0', '< 5.0.0'
20
- gem.add_development_dependency 'rspec', '>= 2.14.1'
19
+ gem.add_dependency 'sidekiq', '>= 5.0.0'
20
+ gem.add_development_dependency 'rspec', '>= 3.6.0'
21
21
  end
@@ -13,12 +13,13 @@ module Sidekiq
13
13
  def initialize(opts={})
14
14
  @default_freekiqs = opts[:freekiqs]
15
15
  @default_freekiq_for = opts[:freekiq_for]
16
+ @@callback = opts[:callback]
16
17
  end
17
18
 
18
19
  def call(worker, msg, queue)
19
20
  yield
20
21
  rescue => ex
21
- freekiqs = get_freekiqs_if_enabled(worker, msg, ex)
22
+ freekiqs = get_freekiqs_if_enabled(worker, ex)
22
23
  if freekiqs
23
24
  if msg['retry_count'].nil? || msg['retry_count'] < freekiqs-1
24
25
  begin
@@ -29,15 +30,15 @@ module Sidekiq
29
30
  raise FreekiqException, ex.message
30
31
  end
31
32
  else
32
- Sidekiq.logger.info { "Out of free kiqs for #{msg['class']} job #{msg['jid']}" }
33
+ Sidekiq.logger.info { "Out of freekiqs for #{msg['class']} job #{msg['jid']}" }
33
34
  end
34
35
  end
35
36
  raise ex
36
37
  end
37
38
 
38
- def get_freekiqs_if_enabled(worker, msg, ex)
39
+ def get_freekiqs_if_enabled(worker, ex)
39
40
  freekiqs = nil
40
- if msg['retry']
41
+ if worker.class.get_sidekiq_options['retry']
41
42
  if worker.class.get_sidekiq_options['freekiqs'] != false
42
43
  errors = get_freekiq_errors(worker)
43
44
  if worker.class.get_sidekiq_options['freekiqs']
@@ -1,329 +1,248 @@
1
- require 'spec_helper'
2
- require 'sidekiq/cli'
3
- require 'sidekiq/middleware/server/retry_jobs'
1
+ require 'sidekiq/processor'
4
2
 
5
- shared_examples_for 'it should have 2 freekiqs for an ArgumentError' do
6
- it 'throws Freekiq exception for specified number of free kiqs' do
7
- expect {
8
- handler.invoke(worker, job, 'default') do
9
- raise ArgumentError, 'overlooked'
10
- end
11
- }.to raise_error(Sidekiq::FreekiqException, 'overlooked')
12
- expect(job['retry_count']).to eq(0)
13
- expect(job['error_class']).to eq('Sidekiq::FreekiqException')
14
- expect(job['error_message']).to eq('overlooked')
15
- expect {
16
- handler.invoke(worker, job, 'default') do
17
- raise ArgumentError, 'overlooked'
18
- end
19
- }.to raise_error(Sidekiq::FreekiqException, 'overlooked')
20
- expect(job['retry_count']).to eq(1)
21
- expect(job['error_class']).to eq('Sidekiq::FreekiqException')
22
- expect(job['error_message']).to eq('overlooked')
23
- expect {
24
- handler.invoke(worker, job, 'default') do
25
- raise ArgumentError, 'not overlooked'
26
- end
27
- }.to raise_error(ArgumentError, 'not overlooked')
28
- expect(job['retry_count']).to eq(2)
29
- expect(job['error_class']).to eq('ArgumentError')
30
- expect(job['error_message']).to eq('not overlooked')
31
- expect(Sidekiq::RetrySet.new.size).to eq(3)
32
- expect(Sidekiq::DeadSet.new.size).to eq(0)
33
- end
34
- end
3
+ RSpec.describe Sidekiq::Middleware::Server::Freekiqs do
4
+ class NonArgumentError < StandardError; end
35
5
 
36
- shared_examples_for 'it should have 0 freekiqs for an ArgumentError' do
37
- it 'raises the original error' do
38
- expect {
39
- handler.invoke(worker, job, 'default') do
40
- raise ArgumentError, 'not overlooked'
41
- end
42
- }.to raise_error(ArgumentError, 'not overlooked')
43
- expect(job['retry_count']).to eq(0)
44
- expect(job['error_class']).to eq('ArgumentError')
45
- expect(job['error_message']).to eq('not overlooked')
46
- expect(Sidekiq::RetrySet.new.size).to eq(1)
47
- expect(Sidekiq::DeadSet.new.size).to eq(0)
6
+ def build_job_hash(worker_class, args=[])
7
+ {'class' => worker_class, 'args' => args}
48
8
  end
49
- end
50
9
 
51
- describe Sidekiq::Middleware::Server::Freekiqs do
52
- class DummyWorkerPlain
53
- include Sidekiq::Worker
10
+ def fetch_retry_job
11
+ retry_set = Sidekiq::RetrySet.new
12
+ retry_job = retry_set.first
13
+ retry_set.clear
14
+ retry_job
54
15
  end
55
- class DummyWorkerWithFreekiqsEnabled
56
- include Sidekiq::Worker
57
- sidekiq_options freekiqs: 2
16
+
17
+ def process_job(job_hash)
18
+ mgr = instance_double('Manager', options: {:queues => ['default']})
19
+ processor = ::Sidekiq::Processor.new(mgr)
20
+ job_msg = Sidekiq.dump_json(job_hash)
21
+ processor.process(Sidekiq::BasicFetch::UnitOfWork.new('queue:default', job_msg))
58
22
  end
59
23
 
60
- def build_handler_chain(freekiq_options={}, retry_options={})
61
- Sidekiq::Middleware::Chain.new do |chain|
62
- chain.add Sidekiq::Middleware::Server::RetryJobs, retry_options
63
- chain.add Sidekiq::Middleware::Server::Freekiqs, freekiq_options
24
+ def initialize_middleware(middleware_opts={})
25
+ Sidekiq.server_middleware do |chain|
26
+ chain.add Sidekiq::Middleware::Server::Freekiqs, middleware_opts
64
27
  end
65
28
  end
66
29
 
67
- def build_job(options={})
68
- {'class' => 'FreekiqDummyWorker', 'args' => [], 'retry' => true}.merge(options)
30
+ def initialize_worker_class(sidekiq_opts=nil)
31
+ worker_class_name = :TestDummyWorker
32
+ Object.send(:remove_const, worker_class_name) if Object.const_defined?(worker_class_name)
33
+ klass = Class.new do
34
+ include Sidekiq::Worker
35
+ sidekiq_options sidekiq_opts if sidekiq_opts
36
+ def perform
37
+ raise ArgumentError, 'Oops'
38
+ end
39
+ end
40
+ Object.const_set(worker_class_name, klass)
69
41
  end
70
42
 
71
43
  def cleanup_redis
72
- Sidekiq::RetrySet.new.select{|job| job.klass == 'FreekiqDummyWorker'}.each(&:delete)
73
- Sidekiq::DeadSet.new.clear
44
+ Sidekiq.redis {|c| c.flushdb }
45
+ end
46
+
47
+ shared_examples_for 'it should have 2 freekiqs for an ArgumentError' do
48
+ it 'throws Freekiq exception for specified number of freekiqs' do
49
+ args ||= []
50
+ expect {
51
+ process_job(build_job_hash(worker_class, args))
52
+ }.to raise_error(Sidekiq::FreekiqException, 'Oops')
53
+ expect(Sidekiq::RetrySet.new.size).to eq(1)
54
+ retry_job = fetch_retry_job
55
+ expect(retry_job['retry_count']).to eq(0)
56
+ expect(retry_job['error_class']).to eq('Sidekiq::FreekiqException')
57
+ expect(retry_job['error_message']).to eq('Oops')
58
+
59
+ expect {
60
+ process_job(retry_job.item)
61
+ }.to raise_error(Sidekiq::FreekiqException, 'Oops')
62
+ expect(Sidekiq::RetrySet.new.size).to eq(1)
63
+ retry_job = fetch_retry_job
64
+ expect(retry_job['retry_count']).to eq(1)
65
+ expect(retry_job['error_class']).to eq('Sidekiq::FreekiqException')
66
+ expect(retry_job['error_message']).to eq('Oops')
67
+
68
+ expect {
69
+ process_job(retry_job.item)
70
+ }.to raise_error(ArgumentError, 'Oops')
71
+ expect(Sidekiq::RetrySet.new.size).to eq(1)
72
+ retry_job = fetch_retry_job
73
+ expect(retry_job['retry_count']).to eq(2)
74
+ expect(retry_job['error_class']).to eq('ArgumentError')
75
+ expect(retry_job['error_message']).to eq('Oops')
76
+ end
77
+ end
78
+
79
+ shared_examples_for 'it should have 0 freekiqs for an ArgumentError' do
80
+ it 'raises the original error' do
81
+ args ||= []
82
+ expect {
83
+ process_job(build_job_hash(worker_class, args))
84
+ }.to raise_error(ArgumentError, 'Oops')
85
+ expect(Sidekiq::RetrySet.new.size).to eq(1)
86
+ retry_job = fetch_retry_job
87
+ expect(retry_job['retry_count']).to eq(0)
88
+ expect(retry_job['error_class']).to eq('ArgumentError')
89
+ expect(retry_job['error_message']).to eq('Oops')
90
+ end
91
+ end
92
+
93
+ shared_examples_for 'it should only raise exception for an ArgumentError' do
94
+ it 'raises the original error' do
95
+ args ||= []
96
+ expect {
97
+ process_job(build_job_hash(worker_class, args))
98
+ }.to raise_error(ArgumentError, 'Oops')
99
+ expect(Sidekiq::RetrySet.new.size).to eq(0)
100
+ # Note: Sidekiq doesn't send job to morgue when retries are diabled
101
+ expect(Sidekiq::DeadSet.new.size).to eq(0)
102
+ end
74
103
  end
75
104
 
76
105
  before(:each) do
77
106
  cleanup_redis
78
107
  end
79
108
 
80
- let(:worker_plain) { DummyWorkerPlain.new }
81
- let(:worker_with_freekiqs_enabled) { DummyWorkerWithFreekiqsEnabled.new }
109
+ context 'with default middleware config' do
110
+ before(:each) do
111
+ initialize_middleware
112
+ end
82
113
 
83
- it 'requires RetryJobs to update retry_count' do
84
- handler = Sidekiq::Middleware::Server::RetryJobs.new
85
- worker = worker_plain
86
- job = build_job
87
- expect {
88
- handler.call(worker, job, 'default') do
89
- raise 'Oops'
114
+ describe 'with nothing explicitly enabled' do
115
+ it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
116
+ let!(:worker_class) { initialize_worker_class }
90
117
  end
91
- }.to raise_error(RuntimeError)
92
- expect(job['retry_count']).to eq(0)
93
- expect {
94
- handler.call(worker, job, 'default') do
95
- raise 'Oops'
96
- end
97
- }.to raise_error(RuntimeError)
98
- expect(job['retry_count']).to eq(1)
99
- end
100
-
101
- it 'should execute a defined callback' do
102
- Sidekiq::Middleware::Server::Freekiqs::callback = ->(worker, msg, queue) do
103
- return true
104
118
  end
105
119
 
106
- handler = build_handler_chain
107
- worker = worker_with_freekiqs_enabled
108
- job = build_job
109
-
110
- expect(Sidekiq::Middleware::Server::Freekiqs::callback).to receive(:call)
111
- expect {
112
- handler.invoke(worker, job, 'default') do
113
- raise ArgumentError, 'overlooked'
120
+ describe 'with freekiqs explicitly disabled' do
121
+ it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
122
+ let!(:worker_class) { initialize_worker_class(freekiqs: false) }
114
123
  end
115
- }.to raise_error(Sidekiq::FreekiqException, 'overlooked')
116
- end
117
-
118
- it 'should still raise FreekiqException if the callback fails' do
119
- Sidekiq::Middleware::Server::Freekiqs::callback = ->(worker, msg, queue) do
120
- raise 'callback error'
121
124
  end
122
125
 
123
- handler = build_handler_chain
124
- worker = worker_with_freekiqs_enabled
125
- job = build_job
126
-
127
- expect {
128
- handler.invoke(worker, job, 'default') do
129
- raise ArgumentError, 'overlooked'
126
+ describe 'with 2 freekiqs in the worker' do
127
+ it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
128
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2) }
130
129
  end
131
- }.to raise_error(Sidekiq::FreekiqException, 'overlooked')
132
- end
130
+ end
133
131
 
134
- describe 'with nothing explicitly enabled' do
135
- it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
136
- let (:handler) { build_handler_chain }
137
- let (:job) { build_job }
138
- let (:worker) do
139
- Class.new do
140
- include Sidekiq::Worker
141
- end.new
132
+ describe 'with freekiq_for ArgumentError and 2 freekiqs in worker' do
133
+ it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
134
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2, freekiq_for: [ArgumentError]) }
142
135
  end
143
136
  end
144
- end
145
137
 
146
- describe 'with freekiqs explicitly disabled' do
147
- it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
148
- let (:handler) { build_handler_chain(freekiqs: 3) }
149
- let (:job) { build_job }
150
- let (:worker) do
151
- Class.new do
152
- include Sidekiq::Worker
153
- sidekiq_options freekiqs: false
154
- end.new
138
+ describe 'with freekiq_for ArgumentError in worker and no freekiqs' do
139
+ it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
140
+ let!(:worker_class) { initialize_worker_class(freekiqs: false, freekiq_for: [ArgumentError]) }
155
141
  end
156
142
  end
157
- end
158
143
 
159
- describe 'with 2 freekiqs in the initializer' do
160
- it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
161
- let (:handler) { build_handler_chain(freekiqs: 2) }
162
- let (:job) { build_job }
163
- let (:worker) do
164
- Class.new do
165
- include Sidekiq::Worker
166
- end.new
144
+ describe 'with freekiq_for NonArgumentError in worker and 2 freekiqs in worker' do
145
+ it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
146
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2, freekiq_for: [NonArgumentError]) }
167
147
  end
168
148
  end
169
- end
170
149
 
171
- describe 'with 2 freekiqs in the worker' do
172
- it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
173
- let (:handler) { build_handler_chain }
174
- let (:job) { build_job }
175
- let (:worker) do
176
- Class.new do
177
- include Sidekiq::Worker
178
- sidekiq_options freekiqs: 2
179
- end.new
150
+ describe 'with freekiq_for ArgumentError as a string' do
151
+ it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
152
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2, freekiq_for: ['ArgumentError']) }
180
153
  end
181
154
  end
182
- end
183
155
 
184
- describe 'with freekiq_for ArgumentError and 2 freekiqs in worker' do
185
- it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
186
- let (:handler) { build_handler_chain }
187
- let (:job) { build_job }
188
- let (:worker) do
189
- Class.new do
190
- include Sidekiq::Worker
191
- sidekiq_options freekiqs: 2, freekiq_for: [ArgumentError]
192
- end.new
156
+ describe 'with freekiq_for the super class of ArgumentError' do
157
+ it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
158
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2, freekiq_for: [ArgumentError.superclass]) }
193
159
  end
194
160
  end
195
- end
196
161
 
197
- describe 'with freekiq_for ArgumentError in worker and no freekiqs' do
198
- it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
199
- let (:handler) { build_handler_chain }
200
- let (:job) { build_job }
201
- let (:worker) do
202
- Class.new do
203
- include Sidekiq::Worker
204
- class NonArgumentError < StandardError; end
205
- sidekiq_options freekiqs: 2, freekiq_for: [NonArgumentError]
206
- end.new
162
+ describe 'with 2 freekiqs in the worker and retries disabled' do
163
+ it_behaves_like 'it should only raise exception for an ArgumentError' do
164
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2, retry: false) }
207
165
  end
208
166
  end
209
167
  end
210
168
 
211
- describe 'with freekiq_for ArgumentError in worker and 2 freekiqs in initializer' do
212
- it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
213
- let (:handler) { build_handler_chain(freekiqs: 2) }
214
- let (:job) { build_job }
215
- let (:worker) do
216
- Class.new do
217
- include Sidekiq::Worker
218
- sidekiq_options freekiq_for: [ArgumentError]
219
- end.new
220
- end
169
+ context 'with middleware configured with 2 freekiqs' do
170
+ before(:each) do
171
+ initialize_middleware(freekiqs: 2)
221
172
  end
222
- end
223
173
 
224
- describe 'with freekiq_for ArgumentError in initializer and 2 freekiqs in initializer' do
225
174
  it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
226
- let (:handler) { build_handler_chain(freekiqs: 2, freekiq_for: [ArgumentError]) }
227
- let (:job) { build_job }
228
- let (:worker) do
229
- Class.new do
230
- include Sidekiq::Worker
231
- end.new
232
- end
175
+ let!(:worker_class) { initialize_worker_class }
233
176
  end
234
- end
235
177
 
236
- describe 'with freekiq_for ArgumentError in initializer and 2 freekiqs in worker' do
237
- it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
238
- let (:handler) { build_handler_chain(freekiq_for: [ArgumentError]) }
239
- let (:job) { build_job }
240
- let (:worker) do
241
- Class.new do
242
- include Sidekiq::Worker
243
- sidekiq_options freekiqs: 2
244
- end.new
178
+ describe 'with freekiq_for ArgumentError in worker' do
179
+ it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
180
+ let!(:worker_class) { initialize_worker_class(freekiq_for: [ArgumentError]) }
245
181
  end
246
182
  end
247
183
  end
248
184
 
249
- describe 'with freekiq_for NonArgumentError in worker and 2 freekiqs in worker' do
250
- it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
251
- let (:handler) { build_handler_chain }
252
- let (:job) { build_job }
253
- let (:worker) do
254
- Class.new do
255
- include Sidekiq::Worker
256
- class NonArgumentError < StandardError; end
257
- sidekiq_options freekiqs: 2, freekiq_for: [NonArgumentError]
258
- end.new
259
- end
185
+ context 'with middleware configured with freekiq_for ArgumentError' do
186
+ before(:each) do
187
+ initialize_middleware(freekiq_for: [ArgumentError])
260
188
  end
261
- end
262
189
 
263
- describe 'with freekiq_for NonArgumentError in initializer and 2 freekiqs in worker' do
264
- it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
265
- let (:handler) { build_handler_chain(freekiq_for: [NonArgumentError]) }
266
- let (:job) { build_job }
267
- let (:worker) do
268
- Class.new do
269
- include Sidekiq::Worker
270
- class NonArgumentError < StandardError; end
271
- sidekiq_options freekiqs: 2
272
- end.new
190
+ describe 'with 2 freekiqs in worker' do
191
+ it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
192
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2) }
273
193
  end
274
194
  end
275
- end
276
195
 
277
- describe 'with freekiq_for NonArgumentError in initializer and freekiq for ArgumentError in worker' do
278
- it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
279
- let (:handler) { build_handler_chain(freekiq_for: [NonArgumentError]) }
280
- let (:job) { build_job }
281
- let (:worker) do
282
- Class.new do
283
- include Sidekiq::Worker
284
- sidekiq_options freekiqs: 2, freekiq_for: [ArgumentError]
285
- end.new
196
+ describe 'with freekiq_for NonArgumentError in worker' do
197
+ it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
198
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2, freekiq_for: [NonArgumentError]) }
286
199
  end
287
200
  end
288
201
  end
289
202
 
290
- describe 'with freekiq_for ArgumentError in initializer and freekiq for NonArgumentError in worker' do
291
- it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
292
- let (:handler) { build_handler_chain(freekiq_for: [ArgumentError]) }
293
- let (:job) { build_job }
294
- let (:worker) do
295
- Class.new do
296
- include Sidekiq::Worker
297
- class NonArgumentError < StandardError; end
298
- sidekiq_options freekiqs: 2, freekiq_for: [NonArgumentError]
299
- end.new
203
+ context 'with middleware configured with freekiq_for NonArgumentError' do
204
+ before(:each) do
205
+ initialize_middleware(freekiq_for: [NonArgumentError])
206
+ end
207
+
208
+ describe 'with 2 freekiqs in worker' do
209
+ it_behaves_like 'it should have 0 freekiqs for an ArgumentError' do
210
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2) }
300
211
  end
301
212
  end
302
- end
303
213
 
304
- describe 'with freekiq_for ArgumentError as a string' do
305
- it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
306
- let (:handler) { build_handler_chain }
307
- let (:job) { build_job }
308
- let (:worker) do
309
- Class.new do
310
- include Sidekiq::Worker
311
- sidekiq_options freekiqs: 2, freekiq_for: ['ArgumentError']
312
- end.new
214
+ describe 'with freekiq_for ArgumentError in worker' do
215
+ it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
216
+ let!(:worker_class) { initialize_worker_class(freekiqs: 2, freekiq_for: [ArgumentError]) }
313
217
  end
314
218
  end
315
219
  end
316
220
 
317
- describe 'with freekiq_for the super class of ArgumentError' do
221
+ context 'with middleware configured with 2 freekiqs and freekiq_for ArgumentError' do
222
+ before(:each) do
223
+ initialize_middleware(freekiqs: 2, freekiq_for: [ArgumentError])
224
+ end
225
+
318
226
  it_behaves_like 'it should have 2 freekiqs for an ArgumentError' do
319
- let (:handler) { build_handler_chain }
320
- let (:job) { build_job }
321
- let (:worker) do
322
- Class.new do
323
- include Sidekiq::Worker
324
- sidekiq_options freekiqs: 2, freekiq_for: [ArgumentError.superclass]
325
- end.new
326
- end
227
+ let!(:worker_class) { initialize_worker_class }
327
228
  end
328
229
  end
230
+
231
+ it 'should execute a defined callback' do
232
+ called = false
233
+ initialize_middleware(callback: ->(worker, msg, queue){called = true})
234
+
235
+ expect {
236
+ process_job(build_job_hash(initialize_worker_class(freekiqs: 2)))
237
+ }.to raise_error(Sidekiq::FreekiqException, 'Oops')
238
+ expect(called).to eq(true)
239
+ end
240
+
241
+ it 'should still raise FreekiqException if the callback fails' do
242
+ initialize_middleware(callback: ->(worker, msg, queue){raise 'callback error'})
243
+
244
+ expect {
245
+ process_job(build_job_hash(initialize_worker_class(freekiqs: 2)))
246
+ }.to raise_error(Sidekiq::FreekiqException, 'Oops')
247
+ end
329
248
  end
data/spec/spec_helper.rb CHANGED
@@ -1,11 +1,102 @@
1
1
  require 'freekiqs'
2
2
 
3
+ $TESTING = true
4
+
5
+ Sidekiq::Logging.logger = nil
6
+
7
+ # This file was generated by the `rspec --init` command. Conventionally, all
8
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
9
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
10
+ # this file to always be loaded, without a need to explicitly require it in any
11
+ # files.
12
+ #
13
+ # Given that it is always loaded, you are encouraged to keep this file as
14
+ # light-weight as possible. Requiring heavyweight dependencies from this file
15
+ # will add to the boot time of your test suite on EVERY test run, even for an
16
+ # individual file that may not need all of that loaded. Instead, consider making
17
+ # a separate helper file that requires the additional dependencies and performs
18
+ # the additional setup, and require it from the spec files that actually need
19
+ # it.
20
+ #
21
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
3
22
  RSpec.configure do |config|
23
+ # rspec-expectations config goes here. You can use an alternate
24
+ # assertion/expectation library such as wrong or the stdlib/minitest
25
+ # assertions if you prefer.
4
26
  config.expect_with :rspec do |expectations|
27
+ # This option will default to `true` in RSpec 4. It makes the `description`
28
+ # and `failure_message` of custom matchers include text for helper methods
29
+ # defined using `chain`, e.g.:
30
+ # be_bigger_than(2).and_smaller_than(4).description
31
+ # # => "be bigger than 2 and smaller than 4"
32
+ # ...rather than:
33
+ # # => "be bigger than 2"
5
34
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
6
35
  end
7
36
 
37
+ # rspec-mocks config goes here. You can use an alternate test double
38
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
8
39
  config.mock_with :rspec do |mocks|
40
+ # Prevents you from mocking or stubbing a method that does not exist on
41
+ # a real object. This is generally recommended, and will default to
42
+ # `true` in RSpec 4.
9
43
  mocks.verify_partial_doubles = true
10
44
  end
45
+
46
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
47
+ # have no way to turn it off -- the option exists only for backwards
48
+ # compatibility in RSpec 3). It causes shared context metadata to be
49
+ # inherited by the metadata hash of host groups and examples, rather than
50
+ # triggering implicit auto-inclusion in groups with matching metadata.
51
+ config.shared_context_metadata_behavior = :apply_to_host_groups
52
+
53
+ # This allows you to limit a spec run to individual examples or groups
54
+ # you care about by tagging them with `:focus` metadata. When nothing
55
+ # is tagged with `:focus`, all examples get run. RSpec also provides
56
+ # aliases for `it`, `describe`, and `context` that include `:focus`
57
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
58
+ config.filter_run_when_matching :focus
59
+
60
+ # Allows RSpec to persist some state between runs in order to support
61
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
62
+ # you configure your source control system to ignore this file.
63
+ # config.example_status_persistence_file_path = "spec/examples.txt"
64
+
65
+ # Limits the available syntax to the non-monkey patched syntax that is
66
+ # recommended. For more details, see:
67
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
68
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
69
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
70
+ config.disable_monkey_patching!
71
+
72
+ # This setting enables warnings. It's recommended, but in some cases may
73
+ # be too noisy due to issues in dependencies.
74
+ config.warnings = true
75
+
76
+ # Many RSpec users commonly either run the entire suite or an individual
77
+ # file, and it's useful to allow more verbose output when running an
78
+ # individual spec file.
79
+ if config.files_to_run.one?
80
+ # Use the documentation formatter for detailed output,
81
+ # unless a formatter has already been configured
82
+ # (e.g. via a command-line flag).
83
+ config.default_formatter = "doc"
84
+ end
85
+
86
+ # Print the 10 slowest examples and example groups at the
87
+ # end of the spec run, to help surface which specs are running
88
+ # particularly slow.
89
+ config.profile_examples = 10
90
+
91
+ # Run specs in random order to surface order dependencies. If you find an
92
+ # order dependency and want to debug it, you can fix the order by providing
93
+ # the seed, which is printed after each run.
94
+ # --seed 1234
95
+ config.order = :random
96
+
97
+ # Seed global randomization in this process using the `--seed` CLI option.
98
+ # Setting this allows you to use `--seed` to deterministically reproduce
99
+ # test failures related to randomization by passing the same `--seed` value
100
+ # as the one that triggered the failure.
101
+ Kernel.srand config.seed
11
102
  end
metadata CHANGED
@@ -1,23 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freekiqs
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Lewis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-24 00:00:00.000000000 Z
11
+ date: 2017-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sidekiq
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 4.0.0
20
- - - "<"
21
18
  - !ruby/object:Gem::Version
22
19
  version: 5.0.0
23
20
  type: :runtime
@@ -25,9 +22,6 @@ dependencies:
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - ">="
28
- - !ruby/object:Gem::Version
29
- version: 4.0.0
30
- - - "<"
31
25
  - !ruby/object:Gem::Version
32
26
  version: 5.0.0
33
27
  - !ruby/object:Gem::Dependency
@@ -36,14 +30,14 @@ dependencies:
36
30
  requirements:
37
31
  - - ">="
38
32
  - !ruby/object:Gem::Version
39
- version: 2.14.1
33
+ version: 3.6.0
40
34
  type: :development
41
35
  prerelease: false
42
36
  version_requirements: !ruby/object:Gem::Requirement
43
37
  requirements:
44
38
  - - ">="
45
39
  - !ruby/object:Gem::Version
46
- version: 2.14.1
40
+ version: 3.6.0
47
41
  description: Sidekiq middleware extending RetryJobs to allow configuring how many
48
42
  exceptions a job can throw and be wrapped by a silenceable exception.
49
43
  email:
@@ -53,10 +47,12 @@ extensions: []
53
47
  extra_rdoc_files: []
54
48
  files:
55
49
  - ".gitignore"
50
+ - ".rspec"
56
51
  - Gemfile
57
52
  - MIT-LICENSE
58
53
  - README.md
59
54
  - Rakefile
55
+ - Vagrantfile
60
56
  - circle.yml
61
57
  - freekiqs.gemspec
62
58
  - lib/freekiqs.rb
@@ -75,7 +71,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
75
71
  requirements:
76
72
  - - ">="
77
73
  - !ruby/object:Gem::Version
78
- version: 1.9.3
74
+ version: 2.2.2
79
75
  required_rubygems_version: !ruby/object:Gem::Requirement
80
76
  requirements:
81
77
  - - ">="
@@ -83,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
79
  version: '0'
84
80
  requirements: []
85
81
  rubyforge_project:
86
- rubygems_version: 2.5.1
82
+ rubygems_version: 2.6.11
87
83
  signing_key:
88
84
  specification_version: 4
89
85
  summary: Sidekiq middleware extending RetryJobs to allow silient errors.