sidekiq-unique-jobs 4.0.17 → 4.0.18
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 +4 -4
- data/.dockerignore +4 -0
- data/.gitignore +1 -0
- data/.travis.yml +3 -3
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -0
- data/README.md +6 -3
- data/circle.yml +3 -6
- data/lib/sidekiq-unique-jobs.rb +4 -0
- data/lib/sidekiq_unique_jobs/cli.rb +2 -2
- data/lib/sidekiq_unique_jobs/lock/until_executed.rb +5 -1
- data/lib/sidekiq_unique_jobs/lock/while_executing.rb +3 -1
- data/lib/sidekiq_unique_jobs/script_mock.rb +68 -0
- data/lib/sidekiq_unique_jobs/scripts.rb +8 -5
- data/lib/sidekiq_unique_jobs/testing.rb +36 -0
- data/lib/sidekiq_unique_jobs/testing/sidekiq_overrides.rb +1 -1
- data/lib/sidekiq_unique_jobs/version.rb +1 -1
- data/rails_example/.env +12 -0
- data/rails_example/.rspec +2 -0
- data/rails_example/Gemfile +21 -7
- data/rails_example/app/channels/appearance_channel.rb +17 -0
- data/rails_example/app/channels/application_cable/channel.rb +4 -0
- data/rails_example/app/channels/application_cable/connection.rb +9 -0
- data/rails_example/app/channels/post_channel.rb +5 -0
- data/rails_example/app/controllers/work_controller.rb +8 -5
- data/rails_example/app/models/application_record.rb +3 -0
- data/rails_example/app/models/guest.rb +21 -0
- data/rails_example/app/models/post.rb +1 -1
- data/rails_example/app/workers/simple_worker.rb +5 -4
- data/rails_example/bin/check_or_setup_db +57 -0
- data/rails_example/bin/docker-setup +20 -0
- data/rails_example/bin/rails +1 -1
- data/rails_example/bin/setup +15 -10
- data/rails_example/bin/update +29 -0
- data/rails_example/cable.ru +6 -0
- data/rails_example/common-services.yml +50 -0
- data/rails_example/config/application.rb +5 -4
- data/rails_example/config/boot.rb +1 -1
- data/rails_example/config/cable.yml +9 -0
- data/rails_example/config/database.docker.yml +12 -0
- data/rails_example/config/database.yml +15 -22
- data/rails_example/config/environment.rb +1 -1
- data/rails_example/config/environments/development.rb +24 -11
- data/rails_example/config/environments/production.rb +24 -17
- data/rails_example/config/environments/test.rb +6 -6
- data/rails_example/config/initializers/application_controller_renderer.rb +6 -0
- data/rails_example/config/initializers/backtrace_silencers.rb +3 -2
- data/rails_example/config/initializers/cookies_serializer.rb +2 -0
- data/rails_example/config/initializers/new_framework_defaults.rb +23 -0
- data/rails_example/config/initializers/session_store.rb +1 -1
- data/rails_example/config/initializers/sidekiq.rb +2 -2
- data/rails_example/config/initializers/wrap_parameters.rb +2 -2
- data/rails_example/config/puma.rb +38 -0
- data/rails_example/config/routes.rb +2 -1
- data/rails_example/config/secrets.yml +3 -3
- data/rails_example/config/spring.rb +6 -0
- data/rails_example/db/migrate/20160724111322_create_posts.rb +12 -0
- data/rails_example/db/schema.rb +8 -4
- data/rails_example/dev-entrypoint.sh +55 -0
- data/rails_example/dev.env +12 -0
- data/rails_example/docker-compose.yml +90 -0
- data/rails_example/docker/rails.Dockerfile +27 -0
- data/rails_example/spec/controllers/work_controller_spec.rb +172 -0
- data/rails_example/spec/factories/posts.rb +8 -0
- data/rails_example/spec/models/post_spec.rb +4 -0
- data/rails_example/spec/rails_helper.rb +21 -0
- data/rails_example/spec/spec_helper.rb +20 -0
- data/rails_example/spec/support/sidekiq_meta.rb +12 -0
- data/rails_example/spec/workers/simple_worker_spec.rb +4 -0
- data/spec/jobs/my_unique_job.rb +7 -2
- data/spec/jobs/my_unique_job_with_filter_method.rb +17 -0
- data/spec/jobs/my_unique_job_with_filter_proc.rb +15 -0
- data/spec/jobs/notify_worker.rb +1 -1
- data/spec/lib/sidekiq_unique_jobs/client/middleware_spec.rb +34 -0
- data/spec/lib/sidekiq_unique_jobs/lock/until_and_while_executing_spec.rb +5 -1
- data/spec/lib/sidekiq_unique_jobs/lock/until_executed_spec.rb +5 -8
- data/spec/lib/sidekiq_unique_jobs/options_with_fallback_spec.rb +2 -1
- data/spec/lib/sidekiq_unique_jobs/script_mock_spec.rb +84 -0
- data/spec/lib/sidekiq_unique_jobs/scripts_spec.rb +4 -0
- data/spec/lib/sidekiq_unique_jobs/sidekiq_testing_enabled_spec.rb +7 -11
- data/spec/lib/sidekiq_unique_jobs/sidekiq_unique_ext_spec.rb +2 -1
- data/spec/spec_helper.rb +1 -2
- data/spec/support/sidekiq_meta.rb +16 -11
- metadata +39 -7
- data/rails_example/db/development.sqlite3 +0 -0
- data/rails_example/db/migrate/20151107231835_create_posts.rb +0 -10
- data/rails_example/db/test.sqlite3 +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e48826d7669ceaa951fae20cf68de7a3e9676b9
|
4
|
+
data.tar.gz: 42a874852687d4bba62d79fee6adc3119aec6ebe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a40449737349637916e6498dd0cb2408ec9f9300d3cf0f900effdfc290f4148a1acc672fcd0e85932d9d9198d5102807b103ec768346beeebe7cfdce06fabad7
|
7
|
+
data.tar.gz: 2ac854b6034970cb0609a9f855f576939d31e3dacfa8627bc4bbbccbed8d08e98e41ca478a29103e0991da599f7fc0378a6dd34f6ba7fcaca15a43751e580b14
|
data/.dockerignore
ADDED
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -13,10 +13,10 @@ script:
|
|
13
13
|
rvm:
|
14
14
|
- jruby-19mode
|
15
15
|
- jruby-9.0.4.0
|
16
|
-
-
|
16
|
+
- jruby-9.1.2.0
|
17
|
+
- rbx-3.9
|
17
18
|
- 2.1.8
|
18
19
|
- 2.2.4
|
19
|
-
- 2.3.0
|
20
20
|
env: STYLE=false
|
21
21
|
gemfile:
|
22
22
|
- gemfiles/sidekiq_develop.gemfile
|
@@ -35,7 +35,7 @@ notifications:
|
|
35
35
|
matrix:
|
36
36
|
fast_finish: true
|
37
37
|
include:
|
38
|
-
- rvm: 2.3.
|
38
|
+
- rvm: 2.3.1
|
39
39
|
gemfile: gemfiles/sidekiq_develop.gemfile
|
40
40
|
env: STYLE=true
|
41
41
|
addons:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## v4.0.18
|
2
|
+
|
3
|
+
- Allow mock_redis to be used over redis
|
4
|
+
- Fixes some locking inconsistencies
|
5
|
+
|
6
|
+
## v4.0.17
|
7
|
+
|
8
|
+
- Always release lock in the lua script `release_lock.lua` and return success [#169](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/169)
|
9
|
+
|
1
10
|
## v4.0.16
|
2
11
|
|
3
12
|
- Allow run & queue lock timeout (expiration) to be different [#164](https://github.com/mhenrixon/sidekiq-unique-jobs/pull/164)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -43,7 +43,7 @@ Due to discoverability of the different lock types `unique` sidekiq option it wa
|
|
43
43
|
sidekiq_options unique: :while_executing
|
44
44
|
```
|
45
45
|
|
46
|
-
Is to make sure that a job can be scheduled any number of times but only executed a single time per argument provided to the job we call this runtime uniqueness. This is probably most useful
|
46
|
+
Is to make sure that a job can be scheduled any number of times but only executed a single time per argument provided to the job we call this runtime uniqueness. This is probably most useful for background jobs that are fast to execute. (See mhenrixon/sidekiq-unique-jobs#111 for a great example of when this would be right.) While the job is executing/performing no other jobs can be executed at the same time.
|
47
47
|
|
48
48
|
### Until Executing
|
49
49
|
|
@@ -212,13 +212,16 @@ Start the console with the following command `bundle exec jobs console`.
|
|
212
212
|
|
213
213
|
## Communication
|
214
214
|
|
215
|
-
There is a [![Join the chat at https://gitter.im/mhenrixon/sidekiq-unique-jobs](https://badges.gitter.im/mhenrixon/sidekiq-unique-jobs.svg)](https://gitter.im/
|
216
|
-
xon/sidekiq-unique-jobs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) for praise or scorn. This would be a good place to have lengthy discuss or brilliant suggestions or simply just nudge me if I forget about anything.
|
215
|
+
There is a [![Join the chat at https://gitter.im/mhenrixon/sidekiq-unique-jobs](https://badges.gitter.im/mhenrixon/sidekiq-unique-jobs.svg)](https://gitter.im/mhenrixon/sidekiq-unique-jobs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) for praise or scorn. This would be a good place to have lengthy discuss or brilliant suggestions or simply just nudge me if I forget about anything.
|
217
216
|
|
218
217
|
## Testing
|
219
218
|
|
220
219
|
To enable the testing for `sidekiq-unique-jobs`, add `require 'sidekiq_unique_jobs/testing'` to your testing helper.
|
221
220
|
|
221
|
+
You can if you want use `gem 'mock_redis'` to prevent sidekiq unique jobs using redis.
|
222
|
+
|
223
|
+
See https://github.com/mhenrixon/sidekiq-unique-jobs/tree/master/rails_example/spec/controllers/work_controller_spec.rb for an example of how to configure sidekiq and unique jobs without redis.
|
224
|
+
|
222
225
|
## Contributing
|
223
226
|
|
224
227
|
1. Fork it
|
data/circle.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
machine:
|
2
2
|
ruby:
|
3
3
|
version:
|
4
|
-
2.3
|
4
|
+
2.2.3
|
5
5
|
java:
|
6
6
|
version: oraclejdk8
|
7
7
|
environment:
|
@@ -14,21 +14,19 @@ dependencies:
|
|
14
14
|
- rvm install rbx-2
|
15
15
|
- rvm install 2.0.0
|
16
16
|
- rvm install 2.1.7
|
17
|
-
- rvm install 2.2.3
|
18
17
|
override:
|
19
18
|
- rvm-exec jruby-9.0.0.0 bundle install
|
20
19
|
- rvm-exec jruby-1.7 bundle install
|
21
20
|
- rvm-exec rbx-2 bundle install
|
22
21
|
- rvm-exec 2.0.0 bundle install
|
23
|
-
- rvm-exec 2.1.
|
24
|
-
- rvm-exec 2.2.
|
22
|
+
- rvm-exec 2.1.7 bundle install
|
23
|
+
- rvm-exec 2.2.3 bundle install
|
25
24
|
- rvm-exec jruby-9.0.0.0 bundle exec appraisal install
|
26
25
|
- rvm-exec jruby-1.7 bundle exec appraisal install
|
27
26
|
- rvm-exec rbx-2 bundle exec appraisal install
|
28
27
|
- rvm-exec 2.0.0 bundle exec appraisal install
|
29
28
|
- rvm-exec 2.1.7 bundle exec appraisal install
|
30
29
|
- rvm-exec 2.2.3 bundle exec appraisal install
|
31
|
-
- rvm-exec 2.3.0 bundle exec appraisal install
|
32
30
|
|
33
31
|
test:
|
34
32
|
override:
|
@@ -38,4 +36,3 @@ test:
|
|
38
36
|
- rvm-exec 2.0.0 bundle exec appraisal rspec
|
39
37
|
- rvm-exec 2.1.7 bundle exec appraisal rspec
|
40
38
|
- rvm-exec 2.2.3 bundle exec appraisal rspec
|
41
|
-
- rvm-exec 2.3.0 bundle exec appraisal rspec
|
data/lib/sidekiq-unique-jobs.rb
CHANGED
@@ -12,10 +12,10 @@ module SidekiqUniqueJobs
|
|
12
12
|
option :dry_run, aliases: :d, type: :boolean, desc: 'set to false to perform deletion'
|
13
13
|
option :count, aliases: :c, type: :numeric, default: 1000, desc: 'The max number of keys to return'
|
14
14
|
def del(pattern)
|
15
|
-
Util.del(pattern, count, dry_run)
|
15
|
+
Util.del(pattern, options[:count], options[:dry_run])
|
16
16
|
end
|
17
17
|
|
18
|
-
desc 'drop into a console
|
18
|
+
desc 'console', 'drop into a console with easy access to helper methods'
|
19
19
|
def console
|
20
20
|
puts "Use `keys '*', 1000 to display the first 1000 unique keys matching '*'"
|
21
21
|
puts "Use `del '*', 1000, true (default) to see how many keys would be deleted for the pattern '*'"
|
@@ -20,7 +20,11 @@ module SidekiqUniqueJobs
|
|
20
20
|
operative = false
|
21
21
|
raise
|
22
22
|
ensure
|
23
|
-
|
23
|
+
if operative && unlock(:server)
|
24
|
+
callback.call
|
25
|
+
else
|
26
|
+
logger.fatal { "the unique_key: #{unique_key} needs to be unlocked manually" }
|
27
|
+
end
|
24
28
|
end
|
25
29
|
|
26
30
|
def unlock(scope)
|
@@ -17,7 +17,9 @@ module SidekiqUniqueJobs
|
|
17
17
|
sleep 0.001 until locked?
|
18
18
|
|
19
19
|
yield
|
20
|
-
|
20
|
+
rescue Sidekiq::Shutdown
|
21
|
+
logger.fatal { "the unique_key: #{@unique_digest} needs to be unlocked manually" }
|
22
|
+
raise
|
21
23
|
ensure
|
22
24
|
SidekiqUniqueJobs.connection(@redis_pool) { |c| c.del @unique_digest }
|
23
25
|
@mutex.unlock
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'digest/sha1'
|
3
|
+
|
4
|
+
module SidekiqUniqueJobs
|
5
|
+
module ScriptMock
|
6
|
+
module_function
|
7
|
+
|
8
|
+
extend SingleForwardable
|
9
|
+
def_delegator :SidekiqUniqueJobs, :connection
|
10
|
+
|
11
|
+
def call(file_name, redis_pool, options = {})
|
12
|
+
send(file_name, redis_pool, options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def acquire_lock(redis_pool, options = {})
|
16
|
+
connection(redis_pool) do |redis|
|
17
|
+
unique_key = options[:keys][0]
|
18
|
+
job_id = options[:argv][0]
|
19
|
+
expires = options[:argv][1].to_i
|
20
|
+
stored_jid = redis.get(unique_key)
|
21
|
+
|
22
|
+
return stored_jid == job_id ? 1 : 0 if stored_jid
|
23
|
+
|
24
|
+
if redis.set(unique_key, job_id, nx: true, ex: expires)
|
25
|
+
redis.hsetnx('uniquejobs', job_id, unique_key)
|
26
|
+
return 1
|
27
|
+
else
|
28
|
+
return 0
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def release_lock(redis_pool, options = {})
|
34
|
+
connection(redis_pool) do |redis|
|
35
|
+
unique_key = options[:keys][0]
|
36
|
+
job_id = options[:argv][0]
|
37
|
+
stored_jid = redis.get(unique_key)
|
38
|
+
|
39
|
+
return -1 unless stored_jid
|
40
|
+
return 0 unless stored_jid == job_id || stored_jid == '2'
|
41
|
+
|
42
|
+
redis.del(unique_key)
|
43
|
+
return 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def synchronize(redis_pool, options = {})
|
48
|
+
connection(redis_pool) do |redis|
|
49
|
+
unique_key = options[:keys][0]
|
50
|
+
time = options[:argv][0].to_i
|
51
|
+
expires = options[:argv][1].to_f
|
52
|
+
|
53
|
+
stored_jid = redis.get(unique_key).to_i
|
54
|
+
return 1 if redis.set(unique_key, time + expires, nx: true, ex: expires)
|
55
|
+
|
56
|
+
stored_time = redis.get(unique_key)
|
57
|
+
if stored_time && stored_time < time
|
58
|
+
if redis.set(unique_key, time + expires, xx: true, ex: expires)
|
59
|
+
return 1
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
return 0
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
# rubocop:enable MethodLength
|
68
|
+
end
|
@@ -28,11 +28,14 @@ module SidekiqUniqueJobs
|
|
28
28
|
redis.evalsha(script_shas[file_name], options)
|
29
29
|
end
|
30
30
|
rescue Redis::CommandError => ex
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
if ex.message == 'NOSCRIPT No matching script. Please use EVAL.'
|
32
|
+
script_shas[file_name] = nil
|
33
|
+
call(file_name, redis_pool, options)
|
34
|
+
else
|
35
|
+
raise ScriptError,
|
36
|
+
"#{file_name}.lua\n\n#{ex.message}\n\n#{script_source(file_name)}" \
|
37
|
+
"#{ex.backtrace.join("\n")}"
|
38
|
+
end
|
36
39
|
end
|
37
40
|
|
38
41
|
def script_source(file_name)
|
@@ -1,6 +1,42 @@
|
|
1
1
|
require 'sidekiq_unique_jobs/testing/sidekiq_overrides'
|
2
|
+
require 'sidekiq_unique_jobs/script_mock'
|
2
3
|
|
3
4
|
module SidekiqUniqueJobs
|
5
|
+
alias redis_version_real redis_version
|
6
|
+
def redis_version
|
7
|
+
if mocked?
|
8
|
+
'0.0'
|
9
|
+
else
|
10
|
+
redis_version_real
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Scripts
|
15
|
+
module Overrides
|
16
|
+
def self.included(base)
|
17
|
+
base.extend Testing
|
18
|
+
base.class_eval do
|
19
|
+
class << self
|
20
|
+
alias_method :call_orig, :call
|
21
|
+
alias_method :call, :call_ext
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Testing
|
27
|
+
def call_ext(file_name, redis_pool, options = {})
|
28
|
+
if SidekiqUniqueJobs.config.redis_test_mode == :mock
|
29
|
+
SidekiqUniqueJobs::ScriptMock.call(file_name, redis_pool, options)
|
30
|
+
else
|
31
|
+
call_orig(file_name, redis_pool, options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
include Overrides
|
38
|
+
end
|
39
|
+
|
4
40
|
module Client
|
5
41
|
class Middleware
|
6
42
|
alias call_real call
|
data/rails_example/.env
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
SECRET_KEY_BASE=10167c7f7654ed02b3557b05b88ece1866a9748a2e8e064016f76cb74ddae38264f7403ba65f301d63c21d770e0ee2ac6906f245e904b3b140d12297f67e0db1
|
2
|
+
APP_DOMAIN=localhost
|
3
|
+
APP_WEB_URL=http://localhost:3000
|
4
|
+
APP_CABLE_URL=ws://localhost:28080
|
5
|
+
WEB_CONSOLE_WHITELISTED_IPS=127.0.0.1 ::1 127.0.0.0/8 ::1
|
6
|
+
DB_HOST=postgres
|
7
|
+
DB_PORT=5432
|
8
|
+
DB_USERNAME=mhenrixon
|
9
|
+
DB_PASSWORD=
|
10
|
+
DB_POOL=25
|
11
|
+
DB_TIMEOUT=5000
|
12
|
+
DB_REAPING_FREQUENCY=10
|
data/rails_example/Gemfile
CHANGED
@@ -1,20 +1,34 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
ruby '2.
|
3
|
+
ruby '2.3.1'
|
4
|
+
|
5
|
+
gem 'rails', '~> 5.0'
|
6
|
+
gem 'puma'
|
7
|
+
gem 'json'
|
8
|
+
gem 'bigdecimal'
|
4
9
|
|
5
10
|
platforms :ruby do
|
6
|
-
gem '
|
11
|
+
gem 'pg'
|
7
12
|
gem 'pry-byebug'
|
8
13
|
gem 'ruby-prof'
|
9
14
|
end
|
10
15
|
|
11
16
|
platforms :jruby do
|
12
17
|
gem 'jruby-openssl'
|
13
|
-
gem '
|
18
|
+
gem 'jdbc-pg'
|
19
|
+
gem 'activerecord-jdbc-adapter'
|
14
20
|
end
|
15
21
|
|
16
|
-
gem '
|
17
|
-
gem '
|
18
|
-
|
19
|
-
|
22
|
+
gem 'sidekiq-unique-jobs', path: '../'
|
23
|
+
gem 'sinatra', github: 'sinatra/sinatra'
|
24
|
+
|
25
|
+
group :development do
|
26
|
+
gem 'web-console'
|
27
|
+
end
|
28
|
+
|
29
|
+
group :development, :test do
|
30
|
+
gem 'rspec-rails'
|
31
|
+
gem 'factory_girl_rails'
|
32
|
+
gem 'mock_redis'
|
33
|
+
end
|
20
34
|
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class AppearanceChannel < ApplicationCable::Channel
|
2
|
+
def subscribed
|
3
|
+
current_user.appear
|
4
|
+
end
|
5
|
+
|
6
|
+
def unsubscribed
|
7
|
+
current_user.disappear
|
8
|
+
end
|
9
|
+
|
10
|
+
def appear(data)
|
11
|
+
current_user.appear on: data['appearing_on']
|
12
|
+
end
|
13
|
+
|
14
|
+
def away
|
15
|
+
current_user.away
|
16
|
+
end
|
17
|
+
end
|
@@ -1,9 +1,12 @@
|
|
1
1
|
class WorkController < ApplicationController
|
2
|
-
def
|
3
|
-
SimpleWorker.perform_async(1)
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
def duplicate_simple
|
3
|
+
4.times { SimpleWorker.perform_async(1) }
|
4
|
+
|
5
|
+
redirect_to '/sidekiq'
|
6
|
+
end
|
7
|
+
|
8
|
+
def duplicate_nested
|
9
|
+
4.times { SpawnSimpleWorker.perform_async(1) }
|
7
10
|
|
8
11
|
redirect_to '/sidekiq'
|
9
12
|
end
|