sidekiq-unique-jobs 2.2.1 → 2.3.2
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.
- data/Gemfile +2 -8
- data/README.md +6 -0
- data/lib/sidekiq-unique-jobs/middleware.rb +2 -3
- data/lib/sidekiq-unique-jobs/middleware/client/unique_jobs.rb +6 -4
- data/lib/sidekiq-unique-jobs/middleware/server/unique_jobs.rb +12 -3
- data/lib/sidekiq-unique-jobs/version.rb +1 -1
- data/sidekiq-unique-jobs.gemspec +1 -1
- data/test/lib/sidekiq/test_client.rb +42 -8
- metadata +5 -11
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
|
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
|
-
|
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)
|
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
|
-
|
11
|
-
|
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
|
data/sidekiq-unique-jobs.gemspec
CHANGED
@@ -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', '
|
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)
|
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
|
-
|
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)
|
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
|
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-
|
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.
|
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
|