gitlab-sidekiq-fetcher 0.5.4 → 0.5.5

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.
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: []