sidekiq-unique-jobs 6.0.10 → 6.0.11

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sidekiq-unique-jobs might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fbbb9d542c2f503e41c0c1870ce0b3c924889060218f5e27328f266239476197
4
- data.tar.gz: 2d11eb5bd79e978f2cd03db40af5f443c7431286028cca3b28249a48764c9600
3
+ metadata.gz: 4794cab4e8c46ab8a1c2f8d3f1f4a0e40eee2f5c0a78c1750816a4f08298fb3e
4
+ data.tar.gz: 5542da14289cd0287001c997b439f77445c9d7b7c13cc8307801a55012217a7c
5
5
  SHA512:
6
- metadata.gz: 3245b73d1d2c432f8bbeb35c1b3b5eeaba7ed82283f0ff31e769ec887e48ef4dba1cbcf91e6fd59d28710a4ae801ac6914570d96c360713c61adb12391373c6c
7
- data.tar.gz: 940daa0baa646433ba4c83a310cd17b84aad1de814aa8714354d85cd69aa184fbf76d5c17dee3e30e0c2b4ec0504027473dc8c2a83474e8bd9b1c37ef8b198f8
6
+ metadata.gz: ee3cddb22fa61d68e5b209fbd129c5e8c1c88c3cb02feae0f1d0b869d3722ab9f8e5d08cf0a2d0bbcbb11be2205ee35e5f9202c24eb56cae360e79e4bacd54c9
7
+ data.tar.gz: e0c980ae65ac375cf0de4595b61ca4137c52ba0335d947560d7d7550f71db8873a4dca228e18f3319c3cdd551b7377a262133c1d7b66ad8daf9a8143b3fdd4f2
data/.travis.yml CHANGED
@@ -38,6 +38,10 @@ matrix:
38
38
  - rvm: 2.5.3
39
39
  gemfile: gemfiles/sidekiq_develop.gemfile
40
40
  env: COV=true
41
+ - rvm: 2.6.0
42
+ gemfile: gemfiles/sidekiq_6.0.gemfile
43
+ - rvm: 2.5.3
44
+ gemfile: gemfiles/sidekiq_6.0.gemfile
41
45
 
42
46
  gemfile:
43
47
  - gemfiles/sidekiq_develop.gemfile
data/Appraisals CHANGED
@@ -27,3 +27,7 @@ end
27
27
  appraise 'sidekiq-5.2' do
28
28
  gem 'sidekiq', '~> 5.2.0'
29
29
  end
30
+
31
+ appraise 'sidekiq-6.0' do
32
+ gem 'sidekiq', git: 'https://github.com/mperham/sidekiq.git', branch: '6-0'
33
+ end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Change Log
2
2
 
3
+ ## [v6.0.10](https://github.com/mhenrixon/sidekiq-unique-jobs/tree/v6.0.10) (2019-02-23)
4
+ [Full Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v6.0.9...v6.0.10)
5
+
6
+ **Closed issues:**
7
+
8
+ - Unsure of sane defaults [\#372](https://github.com/mhenrixon/sidekiq-unique-jobs/issues/372)
9
+
10
+ **Merged pull requests:**
11
+
12
+ - Log job silently complete [\#371](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/371) ([tadejm](https://github.com/tadejm))
13
+
3
14
  ## [v6.0.9](https://github.com/mhenrixon/sidekiq-unique-jobs/tree/v6.0.9) (2019-02-11)
4
15
  [Full Changelog](https://github.com/mhenrixon/sidekiq-unique-jobs/compare/v6.0.8...v6.0.9)
5
16
 
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gem "appraisal", "~> 2.2.0"
7
7
  gem "rspec-eventually", require: false
8
8
  gem "rspec-its", require: false
9
9
  gem "rspec-retry", require: false
10
+ gem "sidekiq", git: "https://github.com/mperham/sidekiq.git", branch: "6-0"
10
11
 
11
12
  platforms :mri_25 do
12
13
  gem "benchmark-ips"
data/README.md CHANGED
@@ -94,15 +94,13 @@ See [Locking & Unlocking](https://github.com/mhenrixon/sidekiq-unique-jobs/wiki/
94
94
 
95
95
  ### Lock Expiration
96
96
 
97
- This is probably not the configuration option you want...
97
+ Lock expiration is used for two things. For the `UntilExpired` job releases the lock upon expiry. This is done from the client.
98
98
 
99
- Since the client and the server are disconnected and not running inside the same process, setting a lock expiration is probably not what you want. Any keys that are used by this gem WILL be removed at the time of the expiration. For jobs that are scheduled in the future the key will expire when that job is scheduled + whatever expiration you have set.
100
-
101
- In previous versions there was a default expiration of 30 minutes which didn't work for a lot of long running jobs. Since version 6 there will be no expiration of any jobs from the default configuration. Please don't use `lock_expiration` unless you really know what you are doing.
99
+ Since v6.0.11 the other locks will expire after the server is done processing.
102
100
 
103
101
  ```ruby
104
102
  sidekiq_options lock_expiration: nil # default - don't expire keys
105
- sidekiq_options lock_expiration: 20.days # expire this lock in 20 days
103
+ sidekiq_options lock_expiration: 20.days.to_i # expire this lock in 20 days
106
104
  ```
107
105
 
108
106
  ### Lock Timeout
@@ -363,7 +361,7 @@ end
363
361
 
364
362
  ### Cleanup Dead Locks
365
363
 
366
- For sidekiq versions before 5.1 a `sidekiq_retries_exhausted` block is required per worker class.
364
+ For sidekiq versions before 5.1 a `sidekiq_retries_exhausted` block is required per worker class. This is deprecated in Sidekiq 6.0
367
365
 
368
366
  ```ruby
369
367
  class MyWorker
@@ -39,7 +39,7 @@ module SidekiqUniqueJobs
39
39
 
40
40
  def locked?
41
41
  SidekiqUniqueJobs::Job.add_uniqueness(item)
42
- Sidekiq::Logging.with_context(logging_context(self.class, item)) do
42
+ SidekiqUniqueJobs.with_context(logging_context(self.class, item)) do
43
43
  locked = lock.lock
44
44
  warn_about_duplicate unless locked
45
45
  locked
@@ -4,6 +4,7 @@ module SidekiqUniqueJobs
4
4
  # Lock manager class that handles all the various locks
5
5
  #
6
6
  # @author Mikael Henriksson <mikael@zoolutions.se>
7
+ # rubocop:disable ClassLength
7
8
  class Locksmith
8
9
  include SidekiqUniqueJobs::Connection
9
10
 
@@ -13,35 +14,23 @@ module SidekiqUniqueJobs
13
14
  # @option item [String] :unique_digest the unique digest (See: {UniqueArgs#unique_digest})
14
15
  # @param [Sidekiq::RedisConnection, ConnectionPool] redis_pool the redis connection
15
16
  def initialize(item, redis_pool = nil)
16
- @concurrency = 1 # removed in a0cff5bc42edbe7190d6ede7e7f845074d2d7af6
17
- @expiration = item[LOCK_EXPIRATION_KEY]
17
+ # @concurrency = 1 # removed in a0cff5bc42edbe7190d6ede7e7f845074d2d7af6
18
+ @ttl = item[LOCK_EXPIRATION_KEY]
18
19
  @jid = item[JID_KEY]
19
20
  @unique_digest = item[UNIQUE_DIGEST_KEY]
21
+ @lock_type = item[LOCK_KEY]
22
+ @lock_type &&= @lock_type.to_sym
20
23
  @redis_pool = redis_pool
21
24
  end
22
25
 
23
- # Checks if the exists key is created in redis
24
- # @return [true, false]
25
- def exists?
26
- redis(redis_pool) { |conn| conn.exists(exists_key) }
27
- end
28
-
29
- # The number of available resourced for this lock
30
- # @return [Integer] the number of available resources
31
- def available_count
32
- return concurrency unless exists?
33
-
34
- redis(redis_pool) { |conn| conn.llen(available_key) }
35
- end
36
-
37
- # Deletes the lock unless it has an expiration set
26
+ # Deletes the lock unless it has a ttl set
38
27
  def delete
39
- return if expiration
28
+ return if ttl
40
29
 
41
30
  delete!
42
31
  end
43
32
 
44
- # Deletes the lock regardless of if it has an expiration set
33
+ # Deletes the lock regardless of if it has a ttl set
45
34
  def delete!
46
35
  Scripts.call(
47
36
  :delete,
@@ -58,7 +47,7 @@ module SidekiqUniqueJobs
58
47
  def lock(timeout = nil, &block)
59
48
  Scripts.call(:lock, redis_pool,
60
49
  keys: [exists_key, grabbed_key, available_key, UNIQUE_SET, unique_digest],
61
- argv: [jid, expiration])
50
+ argv: [jid, ttl, lock_type])
62
51
 
63
52
  grab_token(timeout) do |token|
64
53
  touch_grabbed_token(token)
@@ -87,7 +76,7 @@ module SidekiqUniqueJobs
87
76
  :unlock,
88
77
  redis_pool,
89
78
  keys: [exists_key, grabbed_key, available_key, version_key, UNIQUE_SET, unique_digest],
90
- argv: [token, expiration],
79
+ argv: [token, ttl, lock_type],
91
80
  )
92
81
  end
93
82
 
@@ -97,12 +86,19 @@ module SidekiqUniqueJobs
97
86
  # @return [true, false]
98
87
  def locked?(token = nil)
99
88
  token ||= jid
89
+ Scripts.call(
90
+ :convert_legacy_lock,
91
+ redis_pool,
92
+ keys: [grabbed_key, unique_digest],
93
+ argv: [token],
94
+ )
95
+
100
96
  redis(redis_pool) { |conn| conn.hexists(grabbed_key, token) }
101
97
  end
102
98
 
103
99
  private
104
100
 
105
- attr_reader :concurrency, :unique_digest, :expiration, :jid, :redis_pool
101
+ attr_reader :unique_digest, :ttl, :jid, :redis_pool, :lock_type
106
102
 
107
103
  def grab_token(timeout = nil)
108
104
  redis(redis_pool) do |conn|
@@ -118,7 +114,10 @@ module SidekiqUniqueJobs
118
114
  end
119
115
 
120
116
  def touch_grabbed_token(token)
121
- redis(redis_pool) { |conn| conn.hset(grabbed_key, token, current_time.to_f) }
117
+ redis(redis_pool) do |conn|
118
+ conn.hset(grabbed_key, token, current_time.to_f)
119
+ conn.expire(grabbed_key, ttl) if ttl && lock_type == :until_expired
120
+ end
122
121
  end
123
122
 
124
123
  def return_token_or_block_value(token)
@@ -161,4 +160,5 @@ module SidekiqUniqueJobs
161
160
  redis(&:time)
162
161
  end
163
162
  end
163
+ # rubocop:enable ClassLength
164
164
  end
@@ -52,7 +52,11 @@ module SidekiqUniqueJobs
52
52
 
53
53
  def logging_context(middleware_class, job_hash)
54
54
  digest = job_hash["unique_digest"]
55
- "#{middleware_class} #{"DIG-#{digest}" if digest}"
55
+ if defined?(Sidekiq::Logging)
56
+ "#{middleware_class} #{"DIG-#{digest}" if digest}"
57
+ else
58
+ { middleware: middleware_class, unique_digest: digest }
59
+ end
56
60
  end
57
61
  end
58
62
  end
@@ -23,7 +23,7 @@ module SidekiqUniqueJobs
23
23
  return yield if unique_disabled?
24
24
 
25
25
  SidekiqUniqueJobs::Job.add_uniqueness(item)
26
- Sidekiq::Logging.with_context(logging_context(self.class, item)) do
26
+ SidekiqUniqueJobs.with_context(logging_context(self.class, item)) do
27
27
  lock.execute do
28
28
  yield
29
29
  end
@@ -33,6 +33,15 @@ module SidekiqUniqueJobs
33
33
  config.logger
34
34
  end
35
35
 
36
+ # :reek:ManualDispatch
37
+ def with_context(context, &block)
38
+ if logger.respond_to?(:with_context)
39
+ logger.with_context(context, &block)
40
+ elsif defined?(Sidekiq::Logging)
41
+ Sidekiq::Logging.with_context(context, &block)
42
+ end
43
+ end
44
+
36
45
  # Set a new logger
37
46
  # @param [Logger] other a new logger
38
47
  def logger=(other)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SidekiqUniqueJobs
4
- VERSION = "6.0.10"
4
+ VERSION = "6.0.11"
5
5
  end
@@ -0,0 +1,21 @@
1
+ local grabbed_key = KEYS[1]
2
+ local unique_digest = KEYS[2]
3
+
4
+ local job_id = ARGV[1]
5
+
6
+ local function current_time()
7
+ local time = redis.call('time')
8
+ local s = time[1]
9
+ local ms = time[2]
10
+ local number = tonumber((s .. '.' .. ms))
11
+
12
+ return number
13
+ end
14
+
15
+ local old_token = redis.call('GET', unique_digest)
16
+ if old_token then
17
+ if old_token == job_id or old_token == '2' then
18
+ redis.call('DEL', unique_digest)
19
+ redis.call('HSET', grabbed_key, job_id, current_time())
20
+ end
21
+ end
data/redis/lock.lua CHANGED
@@ -6,8 +6,9 @@ local available_key = KEYS[3]
6
6
  local unique_keys = KEYS[4]
7
7
  local unique_digest = KEYS[5]
8
8
 
9
- local job_id = ARGV[1]
10
- local expiration = tonumber(ARGV[2])
9
+ local job_id = ARGV[1]
10
+ local ttl = tonumber(ARGV[2])
11
+ local lock = ARGV[3]
11
12
 
12
13
  local function current_time()
13
14
  local time = redis.call('time')
@@ -18,11 +19,8 @@ local function current_time()
18
19
  return number
19
20
  end
20
21
 
21
- -- redis.log(redis.LOG_DEBUG, "create.lua - investigate possibility of locking jid: " .. job_id)
22
-
23
- local stored_token = redis.call('GET', exists_key)
22
+ local stored_token = redis.call('GET', exists_key)
24
23
  if stored_token and stored_token ~= job_id then
25
- -- redis.log(redis.LOG_DEBUG, "create.lua - jid: " .. job_id .. " - returning existing jid: " .. stored_token)
26
24
  return stored_token
27
25
  end
28
26
 
@@ -49,10 +47,15 @@ redis.call('DEL', grabbed_key)
49
47
  redis.call('DEL', available_key)
50
48
  redis.call('RPUSH', available_key, job_id)
51
49
 
52
- if expiration then
53
- redis.call('EXPIRE', available_key, expiration)
54
- redis.call('EXPIRE', exists_key, expiration)
55
- redis.call('EXPIRE', grabbed_key, expiration)
50
+ -- The client should only set ttl for until_expired
51
+ -- The server should set ttl for all other jobs
52
+ if lock == "until_expired" and ttl then
53
+ -- We can't keep the key here because it will otherwise never be deleted
54
+ redis.call('SREM', unique_keys, unique_digest)
55
+
56
+ redis.call('EXPIRE', available_key, ttl)
57
+ redis.call('EXPIRE', exists_key, ttl)
58
+ redis.call('EXPIRE', unique_digest, ttl)
56
59
  end
57
60
 
58
61
  return job_id
data/redis/unlock.lua CHANGED
@@ -5,19 +5,19 @@ local version_key = KEYS[4]
5
5
  local unique_keys = KEYS[5]
6
6
  local unique_digest = KEYS[6] -- TODO: Legacy support (Remove in v6.1)
7
7
 
8
- local token = ARGV[1]
9
- local expiration = tonumber(ARGV[2])
8
+ local token = ARGV[1]
9
+ local ttl = tonumber(ARGV[2])
10
+ local lock = ARGV[3]
10
11
 
11
- redis.call('HDEL', grabbed_key, token)
12
12
  redis.call('SREM', unique_keys, unique_digest)
13
13
 
14
- if expiration then
15
- redis.log(redis.LOG_DEBUG, "signal_locks.lua - expiring stale locks")
14
+ if ttl then
16
15
  redis.call('SREM', unique_keys, unique_digest)
17
- redis.call('EXPIRE', exists_key, expiration)
18
- redis.call('EXPIRE', available_key, expiration)
19
- redis.call('EXPIRE', version_key, expiration) -- TODO: Legacy support (Remove in v6.1)
20
- redis.call('EXPIRE', unique_digest, expiration) -- TODO: Legacy support (Remove in v6.1)
16
+ redis.call('EXPIRE', exists_key, ttl)
17
+ redis.call('EXPIRE', grabbed_key, ttl)
18
+ redis.call('EXPIRE', available_key, ttl)
19
+ redis.call('EXPIRE', version_key, ttl) -- TODO: Legacy support (Remove in v6.1)
20
+ redis.call('EXPIRE', unique_digest, ttl) -- TODO: Legacy support (Remove in v6.1)
21
21
  else
22
22
  redis.call('DEL', exists_key)
23
23
  redis.call('SREM', unique_keys, unique_digest)
@@ -28,6 +28,7 @@ else
28
28
  redis.call('DEL', unique_digest) -- TODO: Legacy support (Remove in v6.1)
29
29
  end
30
30
 
31
+ redis.call('HDEL', grabbed_key, token)
31
32
  local count = redis.call('LPUSH', available_key, token)
32
33
  redis.call('EXPIRE', available_key, 5)
33
34
  return count
@@ -42,7 +42,7 @@ Gem::Specification.new do |spec|
42
42
 
43
43
  spec.require_paths = ["lib"]
44
44
  spec.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.5"
45
- spec.add_dependency "sidekiq", ">= 4.0", "< 6.0"
45
+ spec.add_dependency "sidekiq", ">= 4.0", "< 7.0"
46
46
  spec.add_dependency "thor", "~> 0"
47
47
 
48
48
  spec.add_development_dependency "bundler", ">= 2.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-unique-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.10
4
+ version: 6.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-23 00:00:00.000000000 Z
11
+ date: 2019-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: '4.0'
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '6.0'
42
+ version: '7.0'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: '4.0'
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '6.0'
52
+ version: '7.0'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: thor
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -340,6 +340,7 @@ files:
340
340
  - lib/sidekiq_unique_jobs/web/views/unique_digests.erb
341
341
  - lib/tasks/changelog.rake
342
342
  - redis/acquire_lock.lua
343
+ - redis/convert_legacy_lock.lua
343
344
  - redis/delete.lua
344
345
  - redis/delete_by_digest.lua
345
346
  - redis/delete_job_by_digest.lua