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 +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
|