sidekiq-unique-jobs 2.2.1 → 2.3.2

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.

Potentially problematic release.


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

data/Gemfile CHANGED
@@ -1,20 +1,14 @@
1
1
  source 'http://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem 'celluloid'
5
- gem 'slim'
6
- gem 'sprockets'
7
- gem 'sass'
8
- gem 'rails', '3.2.8'
9
- gem 'sqlite3'
10
-
11
4
  group :test do
12
5
  gem 'simplecov', :require => false
13
6
  end
14
7
 
15
8
  group :development do
9
+ gem 'activesupport'
16
10
  gem 'pry'
17
11
  gem 'pry-doc'
18
12
  gem 'pry-stack_explorer'
19
13
  gem 'pry-debugger'
20
- end
14
+ end
data/README.md CHANGED
@@ -24,6 +24,12 @@ All that is required is that you specifically set the sidekiq option for *unique
24
24
  sidekiq_options unique: true
25
25
  ```
26
26
 
27
+ You can also control the expiration length of the uniqueness check. If you want to enforce uniqueness over a longer period than the default of 30 minutes then you can pass the number of seconds you want to use to the sidekiq options:
28
+
29
+ ```ruby
30
+ sidekiq_options unique: true, unique_job_expiration: 120 * 60 # 2 hours
31
+ ```
32
+
27
33
  Requiring the gem in your gemfile should be sufficient to enable unique jobs.
28
34
 
29
35
 
@@ -1,5 +1,4 @@
1
- require 'sidekiq/middleware/chain'
2
- require 'sidekiq/processor'
1
+ require 'sidekiq'
3
2
 
4
3
  Sidekiq.configure_server do |config|
5
4
  config.server_middleware do |chain|
@@ -13,4 +12,4 @@ Sidekiq.configure_client do |config|
13
12
  require 'sidekiq-unique-jobs/middleware/client/unique_jobs'
14
13
  chain.add SidekiqUniqueJobs::Middleware::Client::UniqueJobs
15
14
  end
16
- end
15
+ end
@@ -9,10 +9,12 @@ module SidekiqUniqueJobs
9
9
  def call(worker_class, item, queue)
10
10
 
11
11
  enabled = worker_class.get_sidekiq_options['unique']
12
+ unique_job_expiration = worker_class.get_sidekiq_options['unique_job_expiration']
12
13
 
13
14
  if enabled
14
15
 
15
- payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(item['args']))
16
+ md5_arguments = {:class => item['class'], :queue => item['queue'], :args => item['args']}
17
+ payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(md5_arguments))
16
18
 
17
19
  unique = false
18
20
 
@@ -23,8 +25,8 @@ module SidekiqUniqueJobs
23
25
  if conn.get(payload_hash)
24
26
  conn.unwatch
25
27
  else
26
- expires_at = HASH_KEY_EXPIRATION
27
- expires_at = ((Time.at(item['at']) - Time.now.utc) * 24 * 60 * 60).to_i if item['at']
28
+ expires_at = unique_job_expiration || HASH_KEY_EXPIRATION
29
+ expires_at = ((Time.at(item['at']) - Time.now.utc) + expires_at).to_i if item['at']
28
30
 
29
31
  unique = conn.multi do
30
32
  conn.setex(payload_hash, expires_at, 1)
@@ -40,4 +42,4 @@ module SidekiqUniqueJobs
40
42
  end
41
43
  end
42
44
  end
43
- end
45
+ end
@@ -5,13 +5,22 @@ module SidekiqUniqueJobs
5
5
  module Server
6
6
  class UniqueJobs
7
7
  def call(*args)
8
+ logger.info("About to process a job with args #{args.inspect}")
8
9
  yield
10
+ logger.info("Done processing a job with args #{args.inspect}")
9
11
  ensure
10
- json = Sidekiq.dump_json(args[1])
11
- hash = Digest::MD5.hexdigest(json)
12
+ item = args[1]
13
+ md5_arguments = {:class => item['class'], :queue => item['queue'], :args => item['args']}
14
+ hash = Digest::MD5.hexdigest(Sidekiq.dump_json(md5_arguments))
12
15
  Sidekiq.redis {|conn| conn.del(hash) }
13
16
  end
17
+
18
+ protected
19
+
20
+ def logger
21
+ Sidekiq.logger
22
+ end
14
23
  end
15
24
  end
16
25
  end
17
- end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module SidekiqUniqueJobs
2
- VERSION = "2.2.1"
2
+ VERSION = "2.3.2"
3
3
  end
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "sidekiq-unique-jobs"
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = SidekiqUniqueJobs::VERSION
17
- gem.add_dependency 'sidekiq', '~> 2.2.0'
17
+ gem.add_dependency 'sidekiq', '>= 2.2.0'
18
18
  gem.add_development_dependency 'minitest', '~> 3'
19
19
  gem.add_development_dependency 'sinatra'
20
20
  gem.add_development_dependency 'slim'
@@ -2,12 +2,14 @@ require 'helper'
2
2
  require 'sidekiq/worker'
3
3
  require "sidekiq-unique-jobs"
4
4
  require 'sidekiq/scheduled'
5
+ require 'sidekiq-unique-jobs/middleware/server/unique_jobs'
5
6
 
6
7
  class TestClient < MiniTest::Unit::TestCase
7
8
  describe 'with real redis' do
8
9
  before do
9
10
  Sidekiq.redis = REDIS
10
11
  Sidekiq.redis {|c| c.flushdb }
12
+ QueueWorker.sidekiq_options :unique => nil, :unique_job_expiration => nil
11
13
  end
12
14
 
13
15
  class QueueWorker
@@ -17,15 +19,47 @@ class TestClient < MiniTest::Unit::TestCase
17
19
  end
18
20
  end
19
21
 
22
+ # This spec sometimes fails (unless it's the only spec that runs)
23
+ # Not sure why, we tried a wide variety of ways to make sure that
24
+ # there aren't side effects between tests and it still happens
25
+ it 'is able to enqueue after the server middleware completes' do
26
+ QueueWorker.sidekiq_options :unique => true
27
+ request_item = {'class' => TestClient::QueueWorker, 'queue' => 'customqueue', 'args' => ["some arg"]}
28
+
29
+ Sidekiq::Client.push(request_item.dup)
30
+ assert_equal 1, Sidekiq.redis {|c| c.llen("queue:customqueue") }
31
+
32
+ # Simulate sidekiq processing the job
33
+ Sidekiq.redis {|c| c.lpop("queue:customqueue")}
34
+ assert_equal 0, Sidekiq.redis {|c| c.llen("queue:customqueue") }
35
+
36
+ SidekiqUniqueJobs::Middleware::Server::UniqueJobs.new.call("dummy arg", request_item.dup) {}
37
+
38
+ Sidekiq::Client.push(request_item.dup)
39
+ assert_equal 1, Sidekiq.redis {|c| c.llen("queue:customqueue") }
40
+ end
41
+
20
42
  it 'does not push duplicate messages when configured for unique only' do
21
43
  QueueWorker.sidekiq_options :unique => true
22
- 10.times { Sidekiq::Client.push('class' => QueueWorker, 'args' => [1, 2]) }
44
+ 10.times { Sidekiq::Client.push('class' => TestClient::QueueWorker, 'queue' => 'customqueue', 'args' => [1, 2]) }
23
45
  assert_equal 1, Sidekiq.redis {|c| c.llen("queue:customqueue") }
24
46
  end
25
47
 
48
+ it 'sets an expiration when provided by sidekiq options' do
49
+ one_hour_expiration = 60 * 60
50
+ QueueWorker.sidekiq_options :unique => true, :unique_job_expiration => one_hour_expiration
51
+ Sidekiq::Client.push('class' => TestClient::QueueWorker, 'queue' => 'customqueue', 'args' => [1, 2])
52
+
53
+ md5_arguments = {:class => "TestClient::QueueWorker", :queue => "customqueue", :args => [1, 2]}
54
+ payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(md5_arguments))
55
+ actual_expires_at = Sidekiq.redis {|c| c.ttl(payload_hash) }
56
+
57
+ assert_in_delta one_hour_expiration, actual_expires_at, 2
58
+ end
59
+
26
60
  it 'does push duplicate messages when not configured for unique only' do
27
61
  QueueWorker.sidekiq_options :unique => false
28
- 10.times { Sidekiq::Client.push('class' => QueueWorker, 'args' => [1, 2]) }
62
+ 10.times { Sidekiq::Client.push('class' => TestClient::QueueWorker, 'queue' => 'customqueue', 'args' => [1, 2]) }
29
63
  assert_equal 10, Sidekiq.redis {|c| c.llen("queue:customqueue") }
30
64
  end
31
65
 
@@ -36,16 +70,16 @@ class TestClient < MiniTest::Unit::TestCase
36
70
  QueueWorker.sidekiq_options :unique => true
37
71
 
38
72
  at = 15.minutes.from_now
39
- expected_expires_at = (Time.at(at) - Time.now.utc).to_f
73
+ expected_expires_at = (Time.at(at) - Time.now.utc) + SidekiqUniqueJobs::Middleware::Client::UniqueJobs::HASH_KEY_EXPIRATION
40
74
 
41
75
  QueueWorker.perform_in(at, 'mike')
42
- payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(['mike']))
76
+ md5_arguments = {:class => "TestClient::QueueWorker", :queue => "customqueue", :args => ['mike']}
77
+ payload_hash = Digest::MD5.hexdigest(Sidekiq.dump_json(md5_arguments))
43
78
 
44
79
  # deconstruct this into a time format we can use to get a decent delta for
45
- actual_expires_at = Sidekiq.redis {|c| c.ttl(payload_hash).to_f / 24 / 60 / 60 }
46
-
47
- assert_in_delta expected_expires_at, actual_expires_at, 0.05
80
+ actual_expires_at = Sidekiq.redis {|c| c.ttl(payload_hash) }
48
81
 
82
+ assert_in_delta expected_expires_at, actual_expires_at, 2
49
83
  end
50
84
  end
51
- end
85
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-unique-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,14 +9,14 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-19 00:00:00.000000000 Z
12
+ date: 2012-09-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sidekiq
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: 2.2.0
22
22
  type: :runtime
@@ -24,7 +24,7 @@ dependencies:
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ~>
27
+ - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: 2.2.0
30
30
  - !ruby/object:Gem::Dependency
@@ -158,21 +158,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
158
  - - ! '>='
159
159
  - !ruby/object:Gem::Version
160
160
  version: '0'
161
- segments:
162
- - 0
163
- hash: -556960269690268684
164
161
  required_rubygems_version: !ruby/object:Gem::Requirement
165
162
  none: false
166
163
  requirements:
167
164
  - - ! '>='
168
165
  - !ruby/object:Gem::Version
169
166
  version: '0'
170
- segments:
171
- - 0
172
- hash: -556960269690268684
173
167
  requirements: []
174
168
  rubyforge_project:
175
- rubygems_version: 1.8.24
169
+ rubygems_version: 1.8.23
176
170
  signing_key:
177
171
  specification_version: 3
178
172
  summary: The unique jobs that were removed from sidekiq