sidekiq-unique-jobs 4.0.8 → 4.0.9

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.

Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.fasterer.yml +23 -0
  3. data/.rubocop.yml +2 -1
  4. data/CHANGELOG.md +12 -1
  5. data/Gemfile +4 -3
  6. data/README.md +22 -5
  7. data/bin/jobs +6 -0
  8. data/gemfiles/sidekiq_2.15.gemfile +5 -5
  9. data/gemfiles/sidekiq_2.16.gemfile +5 -5
  10. data/gemfiles/sidekiq_2.17.gemfile +3 -2
  11. data/gemfiles/sidekiq_3.0.gemfile +3 -2
  12. data/gemfiles/sidekiq_3.1.gemfile +3 -2
  13. data/gemfiles/sidekiq_3.2.gemfile +3 -2
  14. data/gemfiles/sidekiq_3.3.gemfile +3 -2
  15. data/gemfiles/sidekiq_develop.gemfile +3 -2
  16. data/lib/sidekiq-unique-jobs.rb +13 -8
  17. data/lib/sidekiq/simulator.rb +75 -0
  18. data/lib/sidekiq_unique_jobs/cli.rb +34 -0
  19. data/lib/sidekiq_unique_jobs/lock/until_timeout.rb +5 -2
  20. data/lib/sidekiq_unique_jobs/lock/while_executing.rb +2 -3
  21. data/lib/sidekiq_unique_jobs/middleware.rb +5 -0
  22. data/lib/sidekiq_unique_jobs/scripts.rb +3 -7
  23. data/lib/sidekiq_unique_jobs/util.rb +77 -0
  24. data/lib/sidekiq_unique_jobs/version.rb +1 -1
  25. data/rails_example/.gitignore +13 -0
  26. data/rails_example/Gemfile +20 -0
  27. data/rails_example/Procfile +2 -0
  28. data/rails_example/README.rdoc +28 -0
  29. data/rails_example/Rakefile +6 -0
  30. data/rails_example/app/assets/images/.keep +0 -0
  31. data/rails_example/app/assets/javascripts/application.js +16 -0
  32. data/rails_example/app/assets/stylesheets/application.css +15 -0
  33. data/rails_example/app/controllers/application_controller.rb +5 -0
  34. data/rails_example/app/controllers/concerns/.keep +0 -0
  35. data/rails_example/app/controllers/work_controller.rb +10 -0
  36. data/rails_example/app/helpers/application_helper.rb +2 -0
  37. data/rails_example/app/mailers/.keep +0 -0
  38. data/rails_example/app/models/.keep +0 -0
  39. data/rails_example/app/models/concerns/.keep +0 -0
  40. data/rails_example/app/models/post.rb +2 -0
  41. data/rails_example/app/views/layouts/application.html.erb +15 -0
  42. data/rails_example/app/workers/simple_worker.rb +11 -0
  43. data/rails_example/app/workers/spawn_simple_worker.rb +7 -0
  44. data/rails_example/bin/bundle +3 -0
  45. data/rails_example/bin/rails +4 -0
  46. data/rails_example/bin/rake +4 -0
  47. data/rails_example/bin/setup +29 -0
  48. data/rails_example/config.ru +4 -0
  49. data/rails_example/config/application.rb +26 -0
  50. data/rails_example/config/boot.rb +3 -0
  51. data/rails_example/config/database.yml +26 -0
  52. data/rails_example/config/environment.rb +5 -0
  53. data/rails_example/config/environments/development.rb +41 -0
  54. data/rails_example/config/environments/production.rb +79 -0
  55. data/rails_example/config/environments/test.rb +42 -0
  56. data/rails_example/config/initializers/assets.rb +11 -0
  57. data/rails_example/config/initializers/backtrace_silencers.rb +8 -0
  58. data/rails_example/config/initializers/cookies_serializer.rb +3 -0
  59. data/rails_example/config/initializers/filter_parameter_logging.rb +4 -0
  60. data/rails_example/config/initializers/inflections.rb +16 -0
  61. data/rails_example/config/initializers/mime_types.rb +4 -0
  62. data/rails_example/config/initializers/session_store.rb +3 -0
  63. data/rails_example/config/initializers/sidekiq.rb +13 -0
  64. data/rails_example/config/initializers/wrap_parameters.rb +14 -0
  65. data/rails_example/config/locales/en.yml +23 -0
  66. data/rails_example/config/routes.rb +5 -0
  67. data/rails_example/config/secrets.yml +22 -0
  68. data/rails_example/config/sidekiq.yml +6 -0
  69. data/rails_example/db/development.sqlite3 +0 -0
  70. data/rails_example/db/migrate/20151107231835_create_posts.rb +10 -0
  71. data/rails_example/db/schema.rb +21 -0
  72. data/rails_example/db/seeds.rb +7 -0
  73. data/rails_example/db/test.sqlite3 +0 -0
  74. data/rails_example/lib/assets/.keep +0 -0
  75. data/rails_example/lib/tasks/.keep +0 -0
  76. data/rails_example/log/.keep +0 -0
  77. data/rails_example/public/404.html +67 -0
  78. data/rails_example/public/422.html +67 -0
  79. data/rails_example/public/500.html +66 -0
  80. data/rails_example/public/favicon.ico +0 -0
  81. data/rails_example/public/robots.txt +5 -0
  82. data/rails_example/simple.ru +12 -0
  83. data/rails_example/vendor/assets/javascripts/.keep +0 -0
  84. data/rails_example/vendor/assets/stylesheets/.keep +0 -0
  85. data/sidekiq-unique-jobs.gemspec +4 -2
  86. data/spec/celluloid_with_fallback.rb +9 -8
  87. data/spec/jobs/simple_worker.rb +11 -0
  88. data/spec/jobs/spawn_simple_worker.rb +8 -0
  89. data/spec/lib/sidekiq_unique_jobs/client/middleware_spec.rb +53 -1
  90. data/spec/lib/sidekiq_unique_jobs/lock/until_timeout_spec.rb +26 -0
  91. data/spec/lib/sidekiq_unique_jobs/options_with_fallback_spec.rb +58 -3
  92. data/spec/lib/sidekiq_unique_jobs/sidekiq_unique_jobs_spec.rb +6 -1
  93. data/spec/lib/sidekiq_unique_jobs/unique_args_spec.rb +2 -3
  94. data/spec/lib/sidekiq_unique_jobs/util_spec.rb +53 -0
  95. data/spec/spec_helper.rb +1 -0
  96. metadata +105 -6
@@ -0,0 +1,67 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/422.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>The change you wanted was rejected.</h1>
62
+ <p>Maybe you tried to change something you didn't have access to.</p>
63
+ </div>
64
+ <p>If you are the application owner check the logs for more information.</p>
65
+ </div>
66
+ </body>
67
+ </html>
@@ -0,0 +1,66 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <style>
7
+ body {
8
+ background-color: #EFEFEF;
9
+ color: #2E2F30;
10
+ text-align: center;
11
+ font-family: arial, sans-serif;
12
+ margin: 0;
13
+ }
14
+
15
+ div.dialog {
16
+ width: 95%;
17
+ max-width: 33em;
18
+ margin: 4em auto 0;
19
+ }
20
+
21
+ div.dialog > div {
22
+ border: 1px solid #CCC;
23
+ border-right-color: #999;
24
+ border-left-color: #999;
25
+ border-bottom-color: #BBB;
26
+ border-top: #B00100 solid 4px;
27
+ border-top-left-radius: 9px;
28
+ border-top-right-radius: 9px;
29
+ background-color: white;
30
+ padding: 7px 12% 0;
31
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
32
+ }
33
+
34
+ h1 {
35
+ font-size: 100%;
36
+ color: #730E15;
37
+ line-height: 1.5em;
38
+ }
39
+
40
+ div.dialog > p {
41
+ margin: 0 0 1em;
42
+ padding: 1em;
43
+ background-color: #F7F7F7;
44
+ border: 1px solid #CCC;
45
+ border-right-color: #999;
46
+ border-left-color: #999;
47
+ border-bottom-color: #999;
48
+ border-bottom-left-radius: 4px;
49
+ border-bottom-right-radius: 4px;
50
+ border-top-color: #DADADA;
51
+ color: #666;
52
+ box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
53
+ }
54
+ </style>
55
+ </head>
56
+
57
+ <body>
58
+ <!-- This file lives in public/500.html -->
59
+ <div class="dialog">
60
+ <div>
61
+ <h1>We're sorry, but something went wrong.</h1>
62
+ </div>
63
+ <p>If you are the application owner check the logs for more information.</p>
64
+ </div>
65
+ </body>
66
+ </html>
File without changes
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-agent: *
5
+ # Disallow: /
@@ -0,0 +1,12 @@
1
+ # Easiest way to run Sidekiq::Web.
2
+ # Run with "bundle exec rackup simple.ru"
3
+
4
+ require 'sidekiq'
5
+
6
+ # A Web process always runs as client, no need to configure server
7
+ Sidekiq.configure_client do |config|
8
+ config.redis = { url: 'redis://localhost:6379/0', size: 1, namespace: 'foo' }
9
+ end
10
+
11
+ require 'sidekiq/web'
12
+ run Sidekiq::Web
@@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
8
8
  gem.homepage = 'https://github.com/mhenrixon/sidekiq-unique-jobs'
9
9
  gem.license = 'WTFPL-2.0'
10
10
 
11
- # gem.executables = ['']
11
+ gem.executables = %w(jobs)
12
12
  gem.files = `git ls-files`.split("\n")
13
13
  gem.test_files = `git ls-files -- test/*`.split("\n")
14
14
  gem.name = 'sidekiq-unique-jobs'
@@ -16,9 +16,11 @@ Gem::Specification.new do |gem|
16
16
  gem.post_install_message = 'WARNING: VERSION 4.0.0 HAS BREAKING CHANGES! Please see Readme for info'
17
17
  gem.version = SidekiqUniqueJobs::VERSION
18
18
  gem.add_dependency 'sidekiq', '>= 2.6'
19
- gem.add_development_dependency 'rspec', '~> 3.1.0'
19
+ gem.add_dependency 'thor', '>= 0'
20
+ gem.add_development_dependency 'rspec', '~> 3.1'
20
21
  gem.add_development_dependency 'rake'
21
22
  gem.add_development_dependency 'rspec-sidekiq'
22
23
  gem.add_development_dependency 'rubocop'
23
24
  gem.add_development_dependency 'timecop'
25
+ gem.add_development_dependency 'yard'
24
26
  end
@@ -1,17 +1,18 @@
1
1
  begin
2
2
  require 'celluloid/current'
3
3
  rescue LoadError
4
- warn 'Celluloid is old'
4
+ warn 'Celluloid is old require the old way'
5
+
5
6
  begin
6
- require 'celluloid' rescue LoadError
7
+ require 'celluloid'
7
8
  rescue LoadError
8
- warn 'Celluloid not found'
9
+ warn 'Sidekiq removed dependency on celluloid'
9
10
  end
10
11
  end
12
+
11
13
  begin
12
- require 'celluloid' rescue LoadError
13
- rescue LoadError
14
- # do nothing we already know
14
+ require 'celluloid/test'
15
+ Celluloid.boot
16
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
17
+ # do nothing we already know celluloid is not in use
15
18
  end
16
-
17
- Celluloid.boot if defined?(Celluloid)
@@ -0,0 +1,11 @@
1
+ class SimpleWorker
2
+ include Sidekiq::Worker
3
+ sidekiq_options unique: :until_executed,
4
+ unique_args: ->(args) { [args.first] },
5
+ queue: :default,
6
+ default_expiration: 5 * 60 * 60
7
+
8
+ def perform(_arg)
9
+ sleep 5
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ class SpawnSimpleWorker
2
+ include Sidekiq::Worker
3
+ sidekiq_options queue: :not_default
4
+
5
+ def perform(arg)
6
+ SimpleWorker.perform_async arg
7
+ end
8
+ end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'sidekiq/worker'
3
3
  require 'sidekiq-unique-jobs'
4
- require 'sidekiq/scheduled'
4
+ require 'rspec/wait'
5
5
 
6
6
  RSpec.describe SidekiqUniqueJobs::Client::Middleware do
7
7
  def digest_for(item)
@@ -15,6 +15,38 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
15
15
  end
16
16
 
17
17
  describe 'when a job is already scheduled' do
18
+ it 'rejects nested subsequent jobs with the same arguments', sidekiq_ver: '>= 3.5.3' do
19
+ Sidekiq::Testing.disable! do
20
+ expect(SimpleWorker.perform_async 1).not_to eq(nil)
21
+ expect(SimpleWorker.perform_async 1).to eq(nil)
22
+ expect(SpawnSimpleWorker.perform_async 1).not_to eq(nil)
23
+
24
+ Sidekiq.redis do |c|
25
+ expect(c.llen('queue:default')).to eq(1)
26
+ expect(c.llen('queue:not_default')).to eq(1)
27
+ end
28
+
29
+ Sidekiq::Simulator.process_queue(:not_default) do
30
+ Sidekiq.redis do |c|
31
+ expect(c.llen('queue:default')).to eq(1)
32
+ wait(10).for { c.llen('queue:not_default') }.to eq(0)
33
+ expect(c.llen('queue:default')).to eq(1)
34
+ end
35
+ end
36
+
37
+ Sidekiq.redis do |c|
38
+ expect(c.llen('queue:default')).to eq(1)
39
+ end
40
+
41
+ Sidekiq::Simulator.process_queue(:default) do
42
+ Sidekiq.redis do |c|
43
+ expect(c.llen('queue:not_default')).to eq(0)
44
+ wait(10).for { c.llen('queue:default') }.to eq(0)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
18
50
  it 'rejects new scheduled jobs with the same argument' do
19
51
  MyUniqueJob.perform_in(3600, 1)
20
52
  expect(MyUniqueJob.perform_in(3600, 1)).to eq(nil)
@@ -208,4 +240,24 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
208
240
  UntilExecutedJob.sidekiq_options log_duplicate_payload: true
209
241
  end
210
242
  end
243
+
244
+ describe '#call' do
245
+ let(:worker_class) { SimpleWorker }
246
+ let(:item) do
247
+ { 'class' => SimpleWorker,
248
+ 'queue' => 'default',
249
+ 'args' => [1] }
250
+ end
251
+ let(:queue) { 'default' }
252
+ context 'when ordinary_or_locked?' do
253
+ before do
254
+ allow(subject).to receive(:ordinary_or_locked?).and_return(false)
255
+ end
256
+
257
+ it 'returns nil' do
258
+ expect(subject.call(worker_class, item, queue))
259
+ .to eq(nil)
260
+ end
261
+ end
262
+ end
211
263
  end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe SidekiqUniqueJobs::Lock::UntilTimeout do
4
+ subject { described_class.new(item) }
5
+ let(:item) do
6
+ { 'jid' => 'maaaahjid',
7
+ 'class' => 'UntilExecutedJob',
8
+ 'unique' => 'until_timeout' }
9
+ end
10
+ let(:empty_callback) { -> {} }
11
+
12
+ describe '#unlock' do
13
+ context 'when provided :server' do
14
+ it 'returns true' do
15
+ expect(subject.unlock(:server)).to eq(true)
16
+ end
17
+ end
18
+
19
+ context 'when provided with anything else than :server' do
20
+ it 'raises a helpful error message' do
21
+ expect { subject.unlock(:client) }
22
+ .to raise_error(ArgumentError, /client middleware can't unlock uniquejobs:*/)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -4,9 +4,6 @@ RSpec.describe SidekiqUniqueJobs::OptionsWithFallback do
4
4
  include described_class
5
5
  subject { self }
6
6
 
7
- let(:options) { {} }
8
- let(:item) { {} }
9
-
10
7
  describe '#unique_lock' do
11
8
  context 'when options have `unique: true`' do
12
9
  let(:options) { { 'unique' => true } }
@@ -21,5 +18,63 @@ RSpec.describe SidekiqUniqueJobs::OptionsWithFallback do
21
18
  subject.unique_lock
22
19
  end
23
20
  end
21
+
22
+ context 'when options have `unique: :while_executing`' do
23
+ let(:options) { { 'unique' => 'while_executing' } }
24
+ end
25
+ end
26
+
27
+ describe '#unique_enabled?' do
28
+ let(:options) { {} }
29
+ let(:item) { {} }
30
+ its(:unique_enabled?) { is_expected.to eq(nil) }
31
+
32
+ context 'when options["unique"] is present' do
33
+ let(:options) { { 'unique' => 'while_executing' } }
34
+ let(:item) { { 'unique' => 'until_executed' } }
35
+ its(:unique_enabled?) { is_expected.to eq('while_executing') }
36
+ end
37
+
38
+ context 'when item["unique"] is present' do
39
+ let(:options) { {} }
40
+ let(:item) { { 'unique' => 'until_executed' } }
41
+ its(:unique_enabled?) { is_expected.to eq('until_executed') }
42
+ end
43
+ end
44
+
45
+ describe '#unique_disabled?' do
46
+ let(:options) { {} }
47
+ let(:item) { {} }
48
+ its(:unique_disabled?) { is_expected.to be_truthy }
49
+
50
+ context 'when options["unique"] is present' do
51
+ let(:options) { { 'unique' => 'while_executing' } }
52
+ let(:item) { { 'unique' => 'until_executed' } }
53
+ its(:unique_disabled?) { is_expected.to be_falsey }
54
+ end
55
+
56
+ context 'when item["unique"] is present' do
57
+ let(:options) { {} }
58
+ let(:item) { { 'unique' => 'until_executed' } }
59
+ its(:unique_disabled?) { is_expected.to be_falsey }
60
+ end
61
+ end
62
+
63
+ describe '#options' do
64
+ context 'when worker_class respond_to get_sidekiq_options' do
65
+ let(:worker_class) { SimpleWorker }
66
+ its(:options) { is_expected.to eq(SimpleWorker.get_sidekiq_options) }
67
+ end
68
+
69
+ context 'when default_worker_options has been configured' do
70
+ let(:worker_class) { PlainClass }
71
+ before do
72
+ allow(Sidekiq)
73
+ .to receive(:default_worker_options)
74
+ .and_return('unique' => 'while_executing')
75
+ end
76
+
77
+ its(:options) { is_expected.to eq(Sidekiq.default_worker_options) }
78
+ end
24
79
  end
25
80
  end
@@ -12,9 +12,14 @@ RSpec.describe SidekiqUniqueJobs do
12
12
  describe '.configure_server_middleware' do
13
13
  let(:server_config) { class_double(Sidekiq) }
14
14
  let(:server_middleware) { double(Sidekiq::Middleware::Chain) }
15
+ let(:client_middleware) { double(Sidekiq::Middleware::Chain) }
15
16
 
16
- it 'adds server middleware when required' do
17
+ it 'adds client and server middleware when required' do
17
18
  expect(Sidekiq).to receive(:configure_server).and_yield(server_config)
19
+
20
+ expect(server_config).to receive(:client_middleware).and_yield(client_middleware)
21
+ expect(client_middleware).to receive(:add).with(SidekiqUniqueJobs::Client::Middleware)
22
+
18
23
  expect(server_config).to receive(:server_middleware).and_yield(server_middleware)
19
24
  expect(server_middleware).to receive(:add).with(SidekiqUniqueJobs::Server::Middleware)
20
25
  described_class.configure_server_middleware
@@ -5,7 +5,7 @@ RSpec.describe SidekiqUniqueJobs::UniqueArgs do
5
5
  subject { described_class.new(item) }
6
6
 
7
7
  describe '#unique_digest' do
8
- let(:item) { item_options.merge('args' => [1, 2, 'type' => 'it'] ) }
8
+ let(:item) { item_options.merge('args' => [1, 2, 'type' => 'it']) }
9
9
 
10
10
  shared_examples 'unique digest' do
11
11
  context 'given another item' do
@@ -30,10 +30,9 @@ RSpec.describe SidekiqUniqueJobs::UniqueArgs do
30
30
  context 'when unique_args is a proc' do
31
31
  let(:item_options) do
32
32
  { 'class' => 'UntilExecutedJob', 'queue' => 'myqueue',
33
- 'unique_args' => Proc.new { |args| args[1] } }
33
+ 'unique_args' => proc { |args| args[1] } }
34
34
  end
35
35
 
36
-
37
36
  it_behaves_like 'unique digest'
38
37
  end
39
38
 
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe SidekiqUniqueJobs::Util do
4
+ let(:keys) { %w(uniquejobs:keyz) }
5
+
6
+ def set(key, value)
7
+ described_class.connection do |c|
8
+ c.set(key, value)
9
+ expect(c.keys('*')).to match_array([key])
10
+ end
11
+ end
12
+
13
+ before(:each) do
14
+ Sidekiq.redis = REDIS
15
+ Sidekiq.redis(&:flushdb)
16
+ end
17
+
18
+ describe '.keys' do
19
+ end
20
+
21
+ describe '.del_by' do
22
+ context 'given a key named "keyz" with value "valz"' do
23
+ before do
24
+ set('uniquejobs:keyz', 'valz')
25
+ end
26
+
27
+ it 'deletes the keys by pattern' do
28
+ expect(described_class.del_by('*', count: 100, dry_run: false)).to eq(1)
29
+ end
30
+
31
+ it 'deletes the keys by pattern' do
32
+ expect(described_class.del_by('keyz', count: 100, dry_run: false)).to eq(1)
33
+ end
34
+ end
35
+ end
36
+
37
+ describe '.prefix' do
38
+ context 'when .unique_prefix is nil?' do
39
+ it 'does not prefix with unique_prefix' do
40
+ allow(SidekiqUniqueJobs.config).to receive(:unique_prefix).and_return(nil)
41
+ expect(described_class.prefix('key')).to eq('key')
42
+ end
43
+ end
44
+
45
+ before do
46
+ allow(SidekiqUniqueJobs.config).to receive(:unique_prefix).and_return('test-uniqueness')
47
+ end
48
+
49
+ it 'returns a prefixed key' do
50
+ expect(described_class.prefix('key')).to eq('test-uniqueness:key')
51
+ end
52
+ end
53
+ end