resque-integration 3.4.1 → 3.8.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: d09663fd4ebbbdeab2821981399c99d590c4d1f4
4
- data.tar.gz: ae7c8f47a7b88af93bf6e5e46577f4e95ae8bcac
3
+ metadata.gz: d37c0511fee9c3f766f352cb18ef36c4980cc869
4
+ data.tar.gz: d8dd5259944ac4ed274530171bda477551bb9f09
5
5
  SHA512:
6
- metadata.gz: f3029f15b7082a53034862bdb3d0b9aae77784ac95f9dc73c05966abd881d722a7e5285ea8e83f28697a77f8d2dc6266d8c89e82e25b5d65a4c7564d3e105fcf
7
- data.tar.gz: 2aebb5a7298e3bb1713f0490e4062445d74f600b657d47e77d27b06d64dfbd34a0e90ca3aa481c4eefb2169fb62f86dd4567835249f2737de02fcbcb328d526b
6
+ metadata.gz: '09ee9d7d3640eb5138138bc941064adcb19cb0ef817d90048613c2cb9c1bb01546ea428b6f10f5ab13b0a874b6289a7ae1ecaead8b36a8fd443c4cba16decf77'
7
+ data.tar.gz: 5bdbe905a197ac686192ca05b192a3e64808a0c676498366b3c18ca7cd8ec4a638d0576aab0f7c77ab7eeb0f72a54698d83d46bf2c68e3324fa23410235d5600
data/.drone.yml CHANGED
@@ -1,28 +1,74 @@
1
- build:
2
- test:
3
- image: abakpress/dind-testing
4
- pull: true
5
- privileged: true
6
- volumes:
7
- - /home/data/drone/images:/images
8
- - /home/data/drone/gems:/bundle
1
+ name: build
2
+
3
+ kind: pipeline
4
+ type: docker
5
+
6
+ volumes:
7
+ - name: images
8
+ host:
9
+ path: /home/data/drone/images
10
+ - name: bundle
11
+ host:
12
+ path: /home/data/drone/gems
13
+ - name: rubygems
14
+ host:
15
+ path: /home/data/drone/rubygems
16
+
17
+ spec_step_common: &spec_step_common
18
+ image: abakpress/dind-testing:1.0.3
19
+ pull: if-not-exists
20
+ privileged: true
21
+ volumes:
22
+ - name: images
23
+ path: /images
24
+ - name: bundle
25
+ path: /bundle
26
+ commands:
27
+ - prepare-build
28
+
29
+ - fetch-images
30
+ --image abakpress/ruby-app:$RUBY_IMAGE_TAG
31
+ --image redis:$REDIS_IMAGE_TAG
32
+ - dip provision
33
+ - dip rspec
34
+
35
+ steps:
36
+ - name: Tests Ruby 2.2
9
37
  environment:
10
- - COMPOSE_FILE_EXT=drone
11
- - RUBY_IMAGE_TAG=2.2-latest
12
- commands:
13
- - wrapdocker docker -v
38
+ COMPOSE_FILE_EXT: drone
39
+ DOCKER_RUBY_VERSION: 2.2
40
+ RUBY_IMAGE_TAG: 2.2-latest
41
+ REDIS_IMAGE_TAG: 4-alpine
42
+ RAILS_ENV: test
43
+ <<: *spec_step_common
14
44
 
15
- - fetch-images --image abakpress/ruby-app:$RUBY_IMAGE_TAG
16
- - dip provision
17
- - dip rspec
45
+ - name: Tests Ruby 2.3
46
+ environment:
47
+ COMPOSE_FILE_EXT: drone
48
+ DOCKER_RUBY_VERSION: 2.3
49
+ RUBY_IMAGE_TAG: 2.3-latest
50
+ REDIS_IMAGE_TAG: 4-alpine
51
+ RAILS_ENV: test
52
+ <<: *spec_step_common
53
+
54
+ - name: Tests Ruby 2.4
55
+ environment:
56
+ COMPOSE_FILE_EXT: drone
57
+ DOCKER_RUBY_VERSION: 2.4
58
+ RUBY_IMAGE_TAG: 2.4-latest
59
+ REDIS_IMAGE_TAG: 4-alpine
60
+ RAILS_ENV: test
61
+ <<: *spec_step_common
18
62
 
19
- release:
20
- image: abakpress/gem-publication
21
- pull: true
63
+ - name: release
64
+ image: abakpress/gem-publication:latest
65
+ pull: if-not-exists
22
66
  when:
23
67
  event: push
24
68
  branch: master
69
+ status: success
25
70
  volumes:
26
- - /home/data/drone/rubygems:/root/.gem
71
+ - name: rubygems
72
+ path: /root/.gem
27
73
  commands:
28
74
  - release-gem --public
data/Appraisals CHANGED
@@ -1,13 +1,7 @@
1
- appraise 'rails3.2' do
2
- gem 'rails', '~> 3.2.0'
3
- end
4
-
5
- appraise 'rails4.0' do
6
- gem 'rails', '~> 4.0.13'
7
- end
8
-
9
- appraise 'rails4.1' do
10
- gem 'rails', '~> 4.1.16'
1
+ if RUBY_VERSION < '2.4'
2
+ appraise 'rails4.0' do
3
+ gem 'rails', '~> 4.0.13'
4
+ end
11
5
  end
12
6
 
13
7
  appraise 'rails4.2' do
@@ -23,5 +17,6 @@ appraise 'rails5.1' do
23
17
  end
24
18
 
25
19
  appraise 'rails5.2' do
26
- gem 'rails', '~> 5.2.0'
20
+ gem 'rails', '~> 5.2.0', '< 5.2.4.1'
21
+ gem 'mimemagic', '<= 0.3.9' if RUBY_VERSION < '2.3'
27
22
  end
data/CHANGELOG.md CHANGED
@@ -1,7 +1,38 @@
1
- # v3.4.1
2
-
1
+ # v3.8.0
2
+
3
+ * 2021-08-19 [27ad006](../../commit/27ad006) - __(Andrew N. Shalaev)__ Release v3.8.0
4
+ * 2021-08-19 [03eab18](../../commit/03eab18) - __(Andrew N. Shalaev)__ fix: use Redis#exists? for get boolean value
5
+ * 2021-07-22 [0caf11c](../../commit/0caf11c) - __(TamarinEA)__ chore: fetch redis image and add rubygems volume
6
+ * 2021-07-21 [7b94d0e](../../commit/7b94d0e) - __(TamarinEA)__ chore: release public gem
7
+ * 2021-07-20 [c51d9ab](../../commit/c51d9ab) - __(TamarinEA)__ chore: lock mimemagic for ruby 2.2
8
+ * 2021-07-20 [843c787](../../commit/843c787) - __(TamarinEA)__ Release 3.7.1
9
+ * 2021-07-20 [933115d](../../commit/933115d) - __(TamarinEA)__ chore: use redis image istead of mock
10
+ * 2021-07-20 [21aa6ba](../../commit/21aa6ba) - __(TamarinEA)__ chore: add ruby 2.4 support
11
+ * 2020-10-05 [05e046b](../../commit/05e046b) - __(TamarinEA)__ Relesae 3.7.0
12
+ * 2020-10-05 [6f12054](../../commit/6f12054) - __(Andrew N. Shalaev)__ Release v3.6.0
13
+ * 2020-09-04 [ee6104e](../../commit/ee6104e) - __(Zhidkov Denis)__ fix: change resque restart command to avoid unwatched workers appearance
14
+ https://jira.railsc.ru/browse/BPC-17334
15
+
16
+ * 2020-08-30 [7676652](../../commit/7676652) - __(TamarinEA)__ feature: add ordered queue check
17
+ https://jira.railsc.ru/browse/GOODS-2471
18
+
19
+ * 2020-04-20 [d36e4b2](../../commit/d36e4b2) - __(TamarinEA)__ chore: use drone 1.6
20
+ * 2020-04-19 [e33faa6](../../commit/e33faa6) - __(TamarinEA)__ Release 3.5.2
21
+ * 2020-04-16 [35eafa2](../../commit/35eafa2) - __(TamarinEA)__ fix: reload ordered meta before save
22
+ https://jira.railsc.ru/browse/GOODS-2326
23
+
24
+ * 2020-04-16 [0c53eef](../../commit/0c53eef) - __(TamarinEA)__ chore: lock gems for support ruby 2.2
25
+ * 2018-12-21 [c2b890d](../../commit/c2b890d) - __(Andrew N. Shalaev)__ Release v3.5.1
26
+ * 2018-12-21 [d7478c2](../../commit/d7478c2) - __(Andrew N. Shalaev)__ fix: add support for redis >= v4
27
+ * 2018-09-06 [49717a5](../../commit/49717a5) - __(Mikhail Nelaev)__ Release 3.5.0
3
28
  * 2018-08-21 [b56dcc8](../../commit/b56dcc8) - __(Artem Napolskih)__ chore: Add automatic publication
4
29
  * 2018-08-15 [5e90b55](../../commit/5e90b55) - __(Artem Napolskih)__ feat: rails 5-x support added
30
+ * 2018-08-09 [3fa8ce0](../../commit/3fa8ce0) - __(terentev)__ feat: move temporary_exceptions to yml config
31
+ https://jira.railsc.ru/browse/GOODS-1418
32
+
33
+ * 2018-08-02 [528feab](../../commit/528feab) - __(terentev)__ feat: adds ability for retry jobs after temporary errors
34
+ https://jira.railsc.ru/browse/GOODS-1418
35
+
5
36
  * 2018-06-05 [3fc2608](../../commit/3fc2608) - __(Pavel Galkin)__ Release 3.4.0
6
37
  * 2018-06-05 [6ec7a38](../../commit/6ec7a38) - __(Pavel Galkin)__ feat: resque:expire task
7
38
  https://jira.railsc.ru/browse/PC4-21225
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in resque-integration.gemspec
4
4
  gemspec
5
+
6
+ gem 'pry', '< 0.13.0', require: false
data/dip.yml CHANGED
@@ -1,8 +1,9 @@
1
1
  version: '1'
2
2
 
3
3
  environment:
4
- DOCKER_RUBY_VERSION: '2.2'
5
- RUBY_IMAGE_TAG: 2.2-latest
4
+ DOCKER_RUBY_VERSION: 2.3
5
+ RUBY_IMAGE_TAG: 2.3-latest
6
+ REDIS_IMAGE_TAG: 4-alpine
6
7
  COMPOSE_FILE_EXT: development
7
8
  RAILS_ENV: test
8
9
  APRESS_GEMS_CREDENTIALS: ""
data/docker-compose.yml CHANGED
@@ -5,6 +5,13 @@ services:
5
5
  image: abakpress/ruby-app:$RUBY_IMAGE_TAG
6
6
  environment:
7
7
  - BUNDLE_PATH=/bundle/$DOCKER_RUBY_VERSION
8
+ - TEST_REDIS_HOST=redis
8
9
  command: bash
9
10
  volumes:
10
11
  - .:/app
12
+ depends_on:
13
+ - redis
14
+
15
+ redis:
16
+ image: redis:$REDIS_IMAGE_TAG
17
+ command: 'redis-server --bind 0.0.0.0'
@@ -100,33 +100,34 @@ module Resque
100
100
 
101
101
  # Extend resque-retry.
102
102
  #
103
- # options - Hash
103
+ # options - Hash of retry options (default: {}):
104
+ # :limit - Integer max number of retry attempts (default: 2)
105
+ # :delay - Integer seconds between retry attempts (default: 60)
106
+ # :exceptions - Array or Hash of specific exceptions to retry (optional)
107
+ # :temporary - boolean retry on temporary exceptions list (default: false)
108
+ # :expire_retry_key_after - Integer expire of retry key in redis (default: 3200)
104
109
  #
105
- # :limit - Integer (default: 2)
106
- # :delay - Integer (default: 60)
107
- # :expire_retry_key_after - Integer (default: 3200), истечение ключа в секундах. Если
108
- #
109
- # t - среднее время выполнения одного джоба
110
- # n - текущее кол-во джобов в очереди
111
- # k - кол-во воркеров
112
- #
113
- # то expire_retry_key_after >= t * n / k
114
- #
115
- # Иначе ключ истечет, прежде чем джоб отработает.
116
- #
117
- #
118
- # Returns nothing
110
+ # Returns nothing.
119
111
  def retrys(options = {})
120
- if unique?
121
- raise '`retrys` should be declared higher in code than `unique`'
122
- end
112
+ raise '`retries` should be declared higher in code than `unique`' if unique?
123
113
 
124
114
  extend Resque::Plugins::Retry
125
115
 
126
116
  @retry_limit = options.fetch(:limit, 2)
127
117
  @retry_delay = options.fetch(:delay, 60)
118
+
119
+ @retry_exceptions = options[:exceptions] if options.key? :exceptions
120
+
121
+ if options[:temporary]
122
+ @retry_exceptions = @retry_exceptions && @retry_exceptions.dup || {}
123
+ @retry_exceptions = @retry_exceptions.product([@retry_delay]).to_h if @retry_exceptions.is_a? Array
124
+
125
+ @retry_exceptions.reverse_merge!(Resque.config.temporary_exceptions)
126
+ end
127
+
128
128
  @expire_retry_key_after = options.fetch(:expire_retry_key_after, 1.hour.seconds)
129
129
  end
130
+ alias retries retrys
130
131
 
131
132
  # Mark Job as ordered
132
133
  def ordered(options = {})
@@ -209,6 +209,24 @@ module Resque
209
209
  self['resque.god_log_level'] || 'info'
210
210
  end
211
211
 
212
+ # Public: Temporary exceptions.
213
+ #
214
+ # Examples
215
+ #
216
+ # temporary_exceptions
217
+ # # => {PG::TRDeadlockDetected => 20, Net::OpenTimeout => 123}
218
+ #
219
+ # Returns Hash.
220
+ def temporary_exceptions
221
+ return @temporary_exceptions if defined?(@temporary_exceptions)
222
+
223
+ return {} unless self['resque.temporary_exceptions']
224
+
225
+ @temporary_exceptions = self['resque.temporary_exceptions'].each_with_object({}) do |(key, value), result|
226
+ result[key.constantize] = value
227
+ end
228
+ end
229
+
212
230
  private
213
231
  def load(path)
214
232
  if File.exists?(path)
@@ -35,7 +35,7 @@ module Resque::Integration
35
35
  initializer 'resque-integration.redis' do
36
36
  redis = Resque.config.redis
37
37
 
38
- if redis.any?
38
+ if redis.present?
39
39
  Resque.redis = Redis.new(redis)
40
40
  Resque.redis.namespace = redis[:namespace] if redis[:namespace]
41
41
  end
@@ -112,12 +112,14 @@ module Resque
112
112
  begin
113
113
  execute(ordered_meta, *job_args)
114
114
  rescue Exception
115
+ ordered_meta.reload!
115
116
  ordered_meta.fail!
116
117
  raise
117
118
  ensure
118
119
  uniqueness.remove(meta_id, job_args) if uniqueness
119
120
  end
120
121
 
122
+ ordered_meta.reload!
121
123
  ordered_meta.finish!
122
124
 
123
125
  i += 1
@@ -137,6 +139,31 @@ module Resque
137
139
  def ordered_meta_id(args)
138
140
  Digest::SHA1.hexdigest([Time.now.to_f, rand, self, args].join)
139
141
  end
142
+
143
+ def in_ordered_queue?(*args)
144
+ meta = enqueued?(*args)
145
+ return false unless meta
146
+
147
+ decoded_args = Resque.decode(Resque.encode(args))
148
+
149
+ args_key = ordered_queue_key(meta.meta_id)
150
+
151
+ args_meta_id = nil
152
+
153
+ ::Resque.redis.lrange(args_key, 0, -1).each do |job_args|
154
+ job_args = ::Resque.decode(job_args)
155
+ meta_id = job_args.shift
156
+
157
+ if job_args == decoded_args
158
+ args_meta_id = meta_id
159
+ break
160
+ end
161
+ end
162
+
163
+ return false unless args_meta_id
164
+
165
+ get_meta(args_meta_id)
166
+ end
140
167
  end
141
168
  end
142
169
  end
@@ -26,7 +26,12 @@ namespace :resque do
26
26
  end
27
27
 
28
28
  Resque.before_fork do
29
- Resque.redis.client.disconnect
29
+ client = if Gem::Version.new(::Redis::VERSION) < Gem::Version.new('4')
30
+ Resque.redis.client
31
+ else
32
+ Resque.redis._client
33
+ end
34
+ client.disconnect
30
35
 
31
36
  ActiveRecord::Base.connection_handler.clear_all_connections!
32
37
  end
@@ -36,7 +41,12 @@ namespace :resque do
36
41
 
37
42
  ActiveRecord::Base.establish_connection
38
43
 
39
- Resque.redis.client.connect
44
+ client = if Gem::Version.new(::Redis::VERSION) < Gem::Version.new('4')
45
+ Resque.redis.client
46
+ else
47
+ Resque.redis._client
48
+ end
49
+ client.connect
40
50
  end
41
51
 
42
52
  # Support for resque-multi-job-forks
@@ -20,7 +20,7 @@ namespace :resque do
20
20
  if god_stopped?
21
21
  Rake::Task['resque:start'].invoke
22
22
  else
23
- puts `#{god} load #{Resque.config.config_file} stop && #{god} restart resque`
23
+ puts `#{god} stop resque && #{god} load #{Resque.config.config_file} stop && #{god} start resque`
24
24
  end
25
25
  end
26
26
 
@@ -165,8 +165,12 @@ module Resque
165
165
  end
166
166
 
167
167
  # Returns true if resque job is in locked state
168
+ #
169
+ # Returns Boolean
168
170
  def locked?(*args)
169
- ::Resque.redis.exists(lock_id(*args))
171
+ redis = ::Resque.redis
172
+
173
+ redis.respond_to?(:exists?) ? redis.exists?(lock_id(*args)) : redis.exists(lock_id(*args))
170
174
  end
171
175
 
172
176
  # Dequeue unique job
@@ -1,5 +1,5 @@
1
1
  module Resque
2
2
  module Integration
3
- VERSION = '3.4.1'.freeze
3
+ VERSION = '3.8.0'.freeze
4
4
  end
5
5
  end
@@ -28,13 +28,14 @@ Gem::Specification.new do |gem|
28
28
  gem.add_runtime_dependency 'multi_json'
29
29
  gem.add_runtime_dependency 'rake'
30
30
 
31
+ gem.add_runtime_dependency 'redis'
32
+
31
33
  gem.add_development_dependency 'bundler'
32
34
  gem.add_development_dependency 'rspec', '~> 2.14'
33
35
  gem.add_development_dependency 'rspec-its'
34
36
  gem.add_development_dependency 'simplecov'
35
37
  gem.add_development_dependency 'appraisal', '>= 1.0.2'
36
38
  gem.add_development_dependency 'combustion', '>= 0.5.5'
37
- gem.add_development_dependency 'mock_redis'
38
39
  gem.add_development_dependency 'timecop'
39
40
  gem.add_development_dependency 'pry-byebug'
40
41
  end
@@ -0,0 +1,10 @@
1
+ class RetriesArgumentErrorJob
2
+ include Resque::Integration
3
+
4
+ retries temporary: true, exceptions: [ArgumentError]
5
+ queue :test_retries
6
+
7
+ def self.execute
8
+ DummyForRetriesService.call
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class RetriesJob
2
+ include Resque::Integration
3
+
4
+ retries
5
+ queue :test_retries
6
+
7
+ def self.execute
8
+ DummyForRetriesService.call
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class RetriesStandardErrorJob
2
+ include Resque::Integration
3
+
4
+ retries temporary: true, exceptions: [StandardError]
5
+ queue :test_retries
6
+
7
+ def self.execute
8
+ DummyForRetriesService.call
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class DummyForRetriesService
2
+ def self.call
3
+ raise StandardError.new('test')
4
+ end
5
+ end
@@ -54,6 +54,18 @@ describe Resque::Integration::Configuration do
54
54
  it { expect(config.run_at_exit_hooks?).to be_falsey }
55
55
  end
56
56
  end
57
+
58
+ describe '#temporary_exceptions' do
59
+ context 'when default' do
60
+ it { expect(config.temporary_exceptions).to eq({}) }
61
+ end
62
+
63
+ context 'when defined' do
64
+ let(:config_yaml) { {'resque' => {'temporary_exceptions' => {'StandardError' => 12}}} }
65
+
66
+ it { expect(config.temporary_exceptions).to eq(StandardError => 12) }
67
+ end
68
+ end
57
69
  end
58
70
 
59
71
  describe Resque::Integration::Configuration::Notifier do
@@ -6,6 +6,15 @@ describe Resque::Integration::Ordered do
6
6
 
7
7
  unique { |company_id, param1| [company_id] }
8
8
  ordered max_iterations: 2
9
+
10
+ def self.execute(ordered_meta, arg1, arg2)
11
+ old_meta = @meta_id
12
+ @meta_id = ordered_meta.meta_id
13
+
14
+ at(arg1, arg2, 'some message')
15
+
16
+ @meta_id = old_meta
17
+ end
9
18
  end
10
19
 
11
20
  class UniqueTestJob
@@ -62,6 +71,16 @@ describe Resque::Integration::Ordered do
62
71
  expect(TestJob.ordered_queue_size(meta_id)).to eq 2
63
72
  end
64
73
 
74
+ it 'save ordered meta' do
75
+ ordered_meta_id = TestJob.enqueue(1, 10).meta_id
76
+ meta_id = TestJob.meta_id(1, 10)
77
+ TestJob.perform(meta_id)
78
+ ordered_meta = TestJob.get_meta(ordered_meta_id)
79
+
80
+ expect(ordered_meta).to be_finished
81
+ expect(ordered_meta.progress).to eq(num: 1, total: 10, percent: 10, message: 'some message')
82
+ end
83
+
65
84
  context 'uniqueness' do
66
85
  it 'perform with unique args only once' do
67
86
  UniqueTestJob.enqueue(1, 10)
@@ -84,4 +103,42 @@ describe Resque::Integration::Ordered do
84
103
  expect(meta.meta_id).to_not eq UniqueTestJob.enqueue(1, 20).meta_id
85
104
  end
86
105
  end
106
+
107
+ describe '#in_ordered_queue?' do
108
+ before do
109
+ allow(TestJob).to receive(:rand).and_return(123)
110
+
111
+ Timecop.freeze
112
+ end
113
+
114
+ it do
115
+ TestJob.enqueue(1, 10)
116
+ TestJob.enqueue(1, 20)
117
+
118
+ expect(TestJob.in_ordered_queue?(1, 10)).to be_instance_of(Resque::Plugins::Meta::Metadata)
119
+ expect(TestJob.in_ordered_queue?(1, 10).meta_id).to eq TestJob.ordered_meta_id([1, 10])
120
+ expect(TestJob.in_ordered_queue?(1, 20)).to be_instance_of(Resque::Plugins::Meta::Metadata)
121
+ expect(TestJob.in_ordered_queue?(1, 20).meta_id).to eq TestJob.ordered_meta_id([1, 20])
122
+ expect(TestJob.in_ordered_queue?(1, 30)).to be_falsey
123
+ end
124
+
125
+ context 'when some complex arg' do
126
+ let(:complex_arg) { [Integer, {a: 1, 'b' => '2'}, 10] }
127
+
128
+ it do
129
+ expect(TestJob.in_ordered_queue?(1, complex_arg)).to be_falsey
130
+
131
+ TestJob.enqueue(1, complex_arg)
132
+
133
+ expect(TestJob.in_ordered_queue?(1, complex_arg)).to be_instance_of(Resque::Plugins::Meta::Metadata)
134
+ expect(TestJob.in_ordered_queue?(1, complex_arg).meta_id).to eq TestJob.ordered_meta_id([1, complex_arg])
135
+
136
+ TestJob.perform(TestJob.meta_id(1, complex_arg))
137
+
138
+ expect(TestJob.in_ordered_queue?(1, complex_arg)).to be_falsey
139
+ end
140
+ end
141
+
142
+ after { Timecop.return }
143
+ end
87
144
  end
@@ -1,4 +1,3 @@
1
- # coding: utf-8
2
1
  require 'spec_helper'
3
2
 
4
3
  RSpec.describe Resque::Integration do
@@ -38,34 +37,49 @@ RSpec.describe Resque::Integration do
38
37
  end
39
38
  end
40
39
 
41
- it 'enqueues only one job' do
42
- UniqueJob.enqueue(1, param: 'one')
40
+ let(:redis) { Resque.redis }
41
+ let(:travel_redis) do
42
+ ->(time) do
43
+ redis.keys.each do |key|
44
+ ttl = redis.ttl(key)
45
+ next if ttl <= 0
43
46
 
44
- Timecop.travel(10.hours.since) do
45
- UniqueJob.enqueue(1, param: 'one')
46
-
47
- expect(Resque.peek(:test, 0, 100).size).to eq(1)
47
+ redis.expire(key, ttl - time.to_i)
48
+ end
48
49
  end
49
50
  end
50
51
 
51
- it 'enqueues two jobs with differ args' do
52
- UniqueJob.enqueue(1, param: 'one')
52
+ context 'when enqueues only one job' do
53
+ before do
54
+ UniqueJob.enqueue(1, param: 'one')
53
55
 
54
- Timecop.travel(10.hours.since) do
55
- UniqueJob.enqueue(1, param: 'two')
56
+ travel_redis.call(10.hours)
56
57
 
57
- expect(Resque.peek(:test, 0, 100).size).to eq(2)
58
+ UniqueJob.enqueue(1, param: 'one')
58
59
  end
60
+
61
+ it { expect(Resque.peek(:test, 0, 100).size).to eq(1) }
59
62
  end
60
63
 
61
- it 'enqueues two jobs after expire lock timeout' do
62
- UniqueJob.enqueue(1, param: 'one')
64
+ context 'when enqueues two jobs with differ args' do
65
+ before do
66
+ UniqueJob.enqueue(1, param: 'one')
67
+ UniqueJob.enqueue(1, param: 'two')
68
+ end
69
+
70
+ it { expect(Resque.peek(:test, 0, 100).size).to eq(2) }
71
+ end
63
72
 
64
- Timecop.travel(4.days.since) do
73
+ context 'when enqueues two jobs after expire lock timeout' do
74
+ before do
65
75
  UniqueJob.enqueue(1, param: 'one')
66
76
 
67
- expect(Resque.peek(:test, 0, 100).size).to eq(2)
77
+ travel_redis.call(4.days)
78
+
79
+ UniqueJob.enqueue(1, param: 'one')
68
80
  end
81
+
82
+ it { expect(Resque.peek(:test, 0, 100).size).to eq(2) }
69
83
  end
70
84
 
71
85
  describe 'unlock' do
@@ -102,4 +116,35 @@ RSpec.describe Resque::Integration do
102
116
  end
103
117
  end
104
118
  end
119
+
120
+ describe 'retries' do
121
+ context 'with default params' do
122
+ let(:job) { Resque::Job.new(:test_retries, 'class' => 'RetriesJob', 'args' => ['meta']) }
123
+
124
+ it do
125
+ expect { job.perform }.to raise_error StandardError
126
+ expect(Resque.delayed_queue_schedule_size).to eq 1
127
+ end
128
+ end
129
+
130
+ context 'with custom params' do
131
+ context 'with StandardError in exceptions' do
132
+ let(:job) { Resque::Job.new(:test_retries, 'class' => 'RetriesStandardErrorJob', 'args' => ['meta']) }
133
+
134
+ it do
135
+ expect { job.perform }.to raise_error StandardError
136
+ expect(Resque.delayed_queue_schedule_size).to eq 1
137
+ end
138
+ end
139
+
140
+ context 'with ArgumentError in exceptions' do
141
+ let(:job) { Resque::Job.new(:test_retries, 'class' => 'RetriesArgumentErrorJob', 'args' => ['meta']) }
142
+
143
+ it do
144
+ expect { job.perform }.to raise_error StandardError
145
+ expect(Resque.delayed_queue_schedule_size).to eq 0
146
+ end
147
+ end
148
+ end
149
+ end
105
150
  end
data/spec/spec_helper.rb CHANGED
@@ -4,12 +4,13 @@ require 'rspec'
4
4
  require 'rspec/its'
5
5
  require 'resque'
6
6
  require 'simplecov'
7
- require 'mock_redis'
8
7
  require 'timecop'
9
8
  require 'pry-byebug'
10
9
  require 'combustion'
11
10
 
12
- Resque.redis = MockRedis.new
11
+ redis = Redis.new(host: ENV['TEST_REDIS_HOST'])
12
+ Redis.current = redis
13
+ Resque.redis = redis
13
14
 
14
15
  SimpleCov.start
15
16
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-integration
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.1
4
+ version: 3.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexei Mikhailov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-08-22 00:00:00.000000000 Z
12
+ date: 2021-08-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: resque
@@ -165,6 +165,20 @@ dependencies:
165
165
  - - ">="
166
166
  - !ruby/object:Gem::Version
167
167
  version: '0'
168
+ - !ruby/object:Gem::Dependency
169
+ name: redis
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ type: :runtime
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
168
182
  - !ruby/object:Gem::Dependency
169
183
  name: bundler
170
184
  requirement: !ruby/object:Gem::Requirement
@@ -249,20 +263,6 @@ dependencies:
249
263
  - - ">="
250
264
  - !ruby/object:Gem::Version
251
265
  version: 0.5.5
252
- - !ruby/object:Gem::Dependency
253
- name: mock_redis
254
- requirement: !ruby/object:Gem::Requirement
255
- requirements:
256
- - - ">="
257
- - !ruby/object:Gem::Version
258
- version: '0'
259
- type: :development
260
- prerelease: false
261
- version_requirements: !ruby/object:Gem::Requirement
262
- requirements:
263
- - - ">="
264
- - !ruby/object:Gem::Version
265
- version: '0'
266
266
  - !ruby/object:Gem::Dependency
267
267
  name: timecop
268
268
  requirement: !ruby/object:Gem::Requirement
@@ -349,6 +349,10 @@ files:
349
349
  - lib/resque/integration/version.rb
350
350
  - resque-integration.gemspec
351
351
  - spec/fixtures/resque_queues.yml
352
+ - spec/internal/app/jobs/retries_argument_error_job.rb
353
+ - spec/internal/app/jobs/retries_job.rb
354
+ - spec/internal/app/jobs/retries_standard_error_job.rb
355
+ - spec/internal/app/services/dummy_for_retries_service.rb
352
356
  - spec/resque/controllers/jobs_controller_spec.rb
353
357
  - spec/resque/integration/configuration_spec.rb
354
358
  - spec/resque/integration/continuous_spec.rb
@@ -389,6 +393,10 @@ specification_version: 4
389
393
  summary: Seamless integration of resque with resque-progress and resque-lock
390
394
  test_files:
391
395
  - spec/fixtures/resque_queues.yml
396
+ - spec/internal/app/jobs/retries_argument_error_job.rb
397
+ - spec/internal/app/jobs/retries_job.rb
398
+ - spec/internal/app/jobs/retries_standard_error_job.rb
399
+ - spec/internal/app/services/dummy_for_retries_service.rb
392
400
  - spec/resque/controllers/jobs_controller_spec.rb
393
401
  - spec/resque/integration/configuration_spec.rb
394
402
  - spec/resque/integration/continuous_spec.rb