gitlab-sidekiq-fetcher 0.5.4 → 0.5.5

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
  SHA256:
3
- metadata.gz: 477650a08755f00beb453c4867a270fa8469a83a372b5b09ba1c030885899699
4
- data.tar.gz: da3fcf3f0b67dd3f71c73ea80d09666e82fa9360cdf5cbf6c8b8e5668b85bfb5
3
+ metadata.gz: eb384451139d1638854cd94a673b12e0f7fd5a42c663535da0145fd153ba4c51
4
+ data.tar.gz: 43851081b6406fe8a876824ef034c548665382707db0aaf41c84c186a98419b0
5
5
  SHA512:
6
- metadata.gz: b4d03a71a6c00e2fa55affd4af5633c2c1ef58093c8bd82b95d4a1603523d940e35b8db4643becf20236224ef065fc879b70585933569efa893e0e05481bffb9
7
- data.tar.gz: 4fac10a26e3507c70927ad8689c2d8903d452cc9ed25a6522dc5c2c7e5e7fcb13d8412013eadb435a9a2feecab51130ad516553c4bbb49c72b2b36827f75c3cf
6
+ metadata.gz: 617032e226ffc898b1c411b0f7598169272bc8521156b9eadcb35b48a139cd854f1b12a2fd98e7fd174128727f0b8c60917780cd2b6dec82cb1370a6260b20ee
7
+ data.tar.gz: 5e56e3840a5f0a4f437ec298de7b68ef796dcfa7d31e69117398ceb22b4ed07fbb4eac4e711b344f5134fd748f9afa476d0d4ffc216cc02cd4eec5b9db90a9c2
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'gitlab-sidekiq-fetcher'
3
- s.version = '0.5.4'
3
+ s.version = '0.5.5'
4
4
  s.authors = ['TEA', 'GitLab']
5
5
  s.email = 'valery@gitlab.com'
6
6
  s.license = 'LGPL-3.0'
@@ -21,6 +21,10 @@ module Sidekiq
21
21
  # How much time a job can be interrupted
22
22
  DEFAULT_MAX_RETRIES_AFTER_INTERRUPTION = 3
23
23
 
24
+ # Regexes for matching working queue keys
25
+ WORKING_QUEUE_REGEX = /#{WORKING_QUEUE_PREFIX}:(queue:.*):([^:]*:[0-9]*:[0-9a-f]*)\z/.freeze
26
+ LEGACY_WORKING_QUEUE_REGEX = /#{WORKING_QUEUE_PREFIX}:(queue:.*):([^:]*:[0-9]*)\z/.freeze
27
+
24
28
  UnitOfWork = Struct.new(:queue, :job) do
25
29
  def acknowledge
26
30
  Sidekiq.redis { |conn| conn.lrem(Sidekiq::BaseReliableFetch.working_queue_name(queue), 1, job) }
@@ -123,12 +127,17 @@ module Sidekiq
123
127
  end
124
128
  end
125
129
 
126
- def self.valid_identity_format?(identity)
127
- # New format is "{hostname}:{pid}:{randomhex}
128
- # Old format is "{hostname}:{pid}"
130
+ def self.extract_queue_and_identity(key)
131
+ # New identity format is "{hostname}:{pid}:{randomhex}
132
+ # Old identity format is "{hostname}:{pid}"
133
+ # Queue names may also have colons (namespaced).
134
+ # Expressing this in a single regex is unreadable
135
+
136
+ # Test the newer expected format first, only checking the older if necessary
137
+ original_queue, identity = key.scan(WORKING_QUEUE_REGEX).flatten
138
+ return original_queue, identity unless original_queue.nil? || identity.nil?
129
139
 
130
- # Test the newer format first, only checking the older if necessary
131
- identity.match(/[^:]*:[0-9]*:[0-9a-f]*\z/) || identity.match(/([^:]*):([0-9]*)\z/)
140
+ key.scan(LEGACY_WORKING_QUEUE_REGEX).flatten
132
141
  end
133
142
 
134
143
  # Detect "old" jobs and requeue them because the worker they were assigned
@@ -138,9 +147,9 @@ module Sidekiq
138
147
 
139
148
  Sidekiq.redis do |conn|
140
149
  conn.scan_each(match: "#{WORKING_QUEUE_PREFIX}:queue:*", count: SCAN_COUNT) do |key|
141
- original_queue, identity = key.scan(/#{WORKING_QUEUE_PREFIX}:(queue:[^:]*):(.*)\z/).flatten
150
+ original_queue, identity = extract_queue_and_identity(key)
142
151
 
143
- next unless valid_identity_format?(identity)
152
+ next if original_queue.nil? || identity.nil?
144
153
 
145
154
  clean_working_queue!(original_queue, key) if worker_dead?(identity, conn)
146
155
  end
@@ -133,6 +133,86 @@ shared_examples 'a Sidekiq fetcher' do
133
133
  expect(jobs).to include 'this_job_should_not_stuck'
134
134
  end
135
135
 
136
+ context 'with namespaced queues' do
137
+ let (:queue) { 'namespace:assigned' }
138
+ let (:fetcher) { described_class.new(queues: [queue]) }
139
+
140
+ it 'requeues jobs from dead namespaced working queue with incremented interrupted_count' do
141
+ Sidekiq.redis do |conn|
142
+ conn.rpush(other_process_working_queue_name(queue), job)
143
+ end
144
+
145
+ expected_job = Sidekiq.load_json(job)
146
+ expected_job['interrupted_count'] = 1
147
+ expected_job = Sidekiq.dump_json(expected_job)
148
+
149
+ uow = fetcher.retrieve_work
150
+
151
+ expect(uow).to_not be_nil
152
+ expect(uow.job).to eq expected_job
153
+
154
+ Sidekiq.redis do |conn|
155
+ expect(conn.llen(other_process_working_queue_name(queue))).to eq 0
156
+ end
157
+ end
158
+
159
+ it 'does not requeue jobs in a namespaced queue from live working queue' do
160
+ working_queue = live_other_process_working_queue_name(queue)
161
+
162
+ Sidekiq.redis do |conn|
163
+ conn.rpush(working_queue, job)
164
+ end
165
+
166
+ uow = fetcher.retrieve_work
167
+
168
+ expect(uow).to be_nil
169
+
170
+ Sidekiq.redis do |conn|
171
+ expect(conn.llen(working_queue)).to eq 1
172
+ end
173
+ end
174
+ end
175
+
176
+ context 'with deeper namespaced queues' do
177
+ let (:queue) { 'deep:namespace:assigned' }
178
+ let (:fetcher) { described_class.new(queues: [queue]) }
179
+
180
+ it 'requeues jobs from dead namespaced working queue with incremented interrupted_count' do
181
+ Sidekiq.redis do |conn|
182
+ conn.rpush(other_process_working_queue_name(queue), job)
183
+ end
184
+
185
+ expected_job = Sidekiq.load_json(job)
186
+ expected_job['interrupted_count'] = 1
187
+ expected_job = Sidekiq.dump_json(expected_job)
188
+
189
+ uow = fetcher.retrieve_work
190
+
191
+ expect(uow).to_not be_nil
192
+ expect(uow.job).to eq expected_job
193
+
194
+ Sidekiq.redis do |conn|
195
+ expect(conn.llen(other_process_working_queue_name(queue))).to eq 0
196
+ end
197
+ end
198
+
199
+ it 'does not requeue jobs in a deeper namespaced queue from live working queue' do
200
+ working_queue = live_other_process_working_queue_name(queue)
201
+
202
+ Sidekiq.redis do |conn|
203
+ conn.rpush(working_queue, job)
204
+ end
205
+
206
+ uow = fetcher.retrieve_work
207
+
208
+ expect(uow).to be_nil
209
+
210
+ Sidekiq.redis do |conn|
211
+ expect(conn.llen(working_queue)).to eq 1
212
+ end
213
+ end
214
+ end
215
+
136
216
  context 'with short cleanup interval' do
137
217
  let(:short_interval) { 1 }
138
218
  let(:fetcher) { described_class.new(queues: queues, lease_interval: short_interval, cleanup_interval: short_interval) }
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-sidekiq-fetcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - TEA
8
8
  - GitLab
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-02-22 00:00:00.000000000 Z
12
+ date: 2021-02-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sidekiq
@@ -63,7 +63,7 @@ homepage: https://gitlab.com/gitlab-org/sidekiq-reliable-fetch/
63
63
  licenses:
64
64
  - LGPL-3.0
65
65
  metadata: {}
66
- post_install_message:
66
+ post_install_message:
67
67
  rdoc_options: []
68
68
  require_paths:
69
69
  - lib
@@ -79,7 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
79
  version: '0'
80
80
  requirements: []
81
81
  rubygems_version: 3.1.4
82
- signing_key:
82
+ signing_key:
83
83
  specification_version: 4
84
84
  summary: Reliable fetch extension for Sidekiq
85
85
  test_files: []