sidekiq-unique-jobs 4.0.0 → 4.0.7

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.

Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +1 -1
  3. data/.travis.yml +1 -2
  4. data/Appraisals +1 -1
  5. data/CHANGELOG.md +44 -1
  6. data/Gemfile +1 -2
  7. data/README.md +49 -51
  8. data/circle.yml +3 -1
  9. data/gemfiles/sidekiq_2.17.gemfile +7 -5
  10. data/gemfiles/sidekiq_3.0.gemfile +6 -4
  11. data/gemfiles/sidekiq_3.1.gemfile +6 -4
  12. data/gemfiles/sidekiq_3.2.gemfile +6 -4
  13. data/gemfiles/sidekiq_3.3.gemfile +6 -4
  14. data/gemfiles/sidekiq_develop.gemfile +6 -4
  15. data/lib/sidekiq-unique-jobs.rb +3 -6
  16. data/lib/sidekiq_unique_jobs/config.rb +1 -6
  17. data/lib/sidekiq_unique_jobs/constants.rb +17 -0
  18. data/lib/sidekiq_unique_jobs/core_ext.rb +28 -23
  19. data/lib/sidekiq_unique_jobs/lock.rb +1 -1
  20. data/lib/sidekiq_unique_jobs/lock/until_and_while_executing.rb +13 -0
  21. data/lib/sidekiq_unique_jobs/lock/until_executed.rb +17 -3
  22. data/lib/sidekiq_unique_jobs/lock/until_executing.rb +4 -0
  23. data/lib/sidekiq_unique_jobs/lock/until_timeout.rb +9 -2
  24. data/lib/sidekiq_unique_jobs/lock/while_executing.rb +17 -5
  25. data/lib/sidekiq_unique_jobs/options_with_fallback.rb +14 -5
  26. data/lib/sidekiq_unique_jobs/server/middleware.rb +3 -40
  27. data/lib/sidekiq_unique_jobs/sidekiq_unique_ext.rb +29 -2
  28. data/lib/sidekiq_unique_jobs/testing/sidekiq_overrides.rb +6 -2
  29. data/lib/sidekiq_unique_jobs/timeout_calculator.rb +42 -0
  30. data/lib/sidekiq_unique_jobs/unique_args.rb +31 -29
  31. data/lib/sidekiq_unique_jobs/version.rb +1 -1
  32. data/redis/synchronize.lua +1 -1
  33. data/sidekiq-unique-jobs.gemspec +1 -2
  34. data/spec/{workers/unique_worker.rb → jobs/another_unique_job.rb} +3 -3
  35. data/spec/{workers/queue_worker.rb → jobs/custom_queue_job.rb} +1 -1
  36. data/spec/jobs/custom_queue_job_with_filter_method.rb +7 -0
  37. data/spec/{workers/queue_worker_with_filter_proc.rb → jobs/custom_queue_job_with_filter_proc.rb} +2 -3
  38. data/spec/jobs/expiring_job.rb +4 -0
  39. data/spec/{workers → jobs}/inline_worker.rb +1 -1
  40. data/spec/jobs/just_a_worker.rb +8 -0
  41. data/spec/jobs/main_job.rb +8 -0
  42. data/spec/{workers/my_worker.rb → jobs/my_job.rb} +2 -3
  43. data/spec/jobs/my_unique_job.rb +7 -0
  44. data/spec/{workers → jobs}/plain_class.rb +0 -0
  45. data/spec/{workers → jobs}/test_class.rb +0 -0
  46. data/spec/{workers → jobs}/unique_job_with_filter_method.rb +2 -2
  47. data/spec/{workers/unique_on_all_queues_worker.rb → jobs/unique_on_all_queues_job.rb} +3 -3
  48. data/spec/jobs/until_and_while_executing_job.rb +8 -0
  49. data/spec/{workers/another_unique_worker.rb → jobs/until_executed_job.rb} +6 -2
  50. data/spec/jobs/until_executing_job.rb +8 -0
  51. data/spec/jobs/until_global_timeout_job.rb +8 -0
  52. data/spec/{workers/inline_expiration_worker.rb → jobs/until_timeout_job.rb} +2 -2
  53. data/spec/{workers/after_unlock_worker.rb → jobs/while_executing_job.rb} +2 -3
  54. data/spec/lib/sidekiq_unique_jobs/client/middleware_spec.rb +60 -44
  55. data/spec/lib/sidekiq_unique_jobs/lock/until_and_while_executing_spec.rb +39 -0
  56. data/spec/lib/sidekiq_unique_jobs/lock/until_executed_spec.rb +40 -0
  57. data/spec/lib/sidekiq_unique_jobs/lock/while_executing_spec.rb +15 -4
  58. data/spec/lib/sidekiq_unique_jobs/options_with_fallback_spec.rb +25 -0
  59. data/spec/lib/sidekiq_unique_jobs/scripts_spec.rb +3 -4
  60. data/spec/lib/sidekiq_unique_jobs/server/middleware_spec.rb +51 -68
  61. data/spec/lib/sidekiq_unique_jobs/sidekiq_testing_enabled_spec.rb +75 -79
  62. data/spec/lib/sidekiq_unique_jobs/sidekiq_unique_ext_spec.rb +2 -2
  63. data/spec/lib/sidekiq_unique_jobs/{lock/time_calculator_spec.rb → timeout_calculator_spec.rb} +10 -11
  64. data/spec/lib/sidekiq_unique_jobs/unique_args_spec.rb +28 -45
  65. data/spec/spec_helper.rb +23 -15
  66. data/spec/support/unique_macros.rb +20 -1
  67. metadata +30 -42
  68. data/lib/sidekiq_unique_jobs/lock/time_calculator.rb +0 -44
  69. data/spec/workers/after_yield_worker.rb +0 -17
  70. data/spec/workers/before_yield_worker.rb +0 -9
  71. data/spec/workers/expiring_worker.rb +0 -4
  72. data/spec/workers/inline_unlock_order_worker.rb +0 -8
  73. data/spec/workers/just_a_worker.rb +0 -8
  74. data/spec/workers/main_job.rb +0 -8
  75. data/spec/workers/my_unique_worker.rb +0 -8
  76. data/spec/workers/queue_worker_with_filter_method.rb +0 -7
  77. data/spec/workers/run_lock_with_retries_worker.rb +0 -12
  78. data/spec/workers/run_lock_worker.rb +0 -7
  79. data/spec/workers/while_executing_worker.rb +0 -13
@@ -34,11 +34,15 @@ module Sidekiq
34
34
  end
35
35
  jobs.clear
36
36
  end
37
+
38
+ def execute_job(worker, args)
39
+ worker.perform(*args)
40
+ end unless respond_to?(:execute_job)
37
41
  end
38
42
 
39
43
  module Overrides
40
44
  def self.included(base)
41
- base.extend Sidekiq::Worker::Overrides::ClassMethods
45
+ base.extend Testing
42
46
  base.class_eval do
43
47
  class << self
44
48
  alias_method :clear_all_orig, :clear_all
@@ -47,7 +51,7 @@ module Sidekiq
47
51
  end
48
52
  end
49
53
 
50
- module ClassMethods
54
+ module Testing
51
55
  def clear_all_ext
52
56
  Sidekiq.redis do |c|
53
57
  unique_keys = c.keys("#{SidekiqUniqueJobs.config.unique_prefix}:*")
@@ -0,0 +1,42 @@
1
+ module SidekiqUniqueJobs
2
+ class TimeoutCalculator
3
+ def self.for_item(item)
4
+ new(item)
5
+ end
6
+
7
+ def initialize(item)
8
+ @item = item
9
+ end
10
+
11
+ def seconds
12
+ time_until_scheduled + unique_expiration
13
+ end
14
+
15
+ def time_until_scheduled
16
+ scheduled = item[AT_KEY]
17
+ return 0 unless scheduled
18
+ (Time.at(scheduled) - Time.now.utc).to_i
19
+ end
20
+
21
+ def unique_expiration
22
+ @unique_expiration ||=
23
+ (
24
+ worker_class_unique_expiration ||
25
+ SidekiqUniqueJobs.config.default_expiration
26
+ ).to_i
27
+ end
28
+
29
+ def worker_class_unique_expiration
30
+ return unless worker_class.respond_to?(:get_sidekiq_options)
31
+ worker_class.get_sidekiq_options[UNIQUE_TIMEOUT_KEY]
32
+ end
33
+
34
+ def worker_class
35
+ @worker_class ||= SidekiqUniqueJobs.worker_class_constantize(item[CLASS_KEY])
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :item
41
+ end
42
+ end
@@ -1,26 +1,28 @@
1
+ require 'digest'
1
2
  require 'sidekiq_unique_jobs/normalizer'
2
3
 
3
4
  module SidekiqUniqueJobs
4
5
  # This class exists to be testable and the entire api should be considered private
5
6
  # rubocop:disable ClassLength
6
7
  class UniqueArgs
8
+ CLASS_NAME = 'SidekiqUniqueJobs::UniqueArgs'.freeze
7
9
  extend Forwardable
8
10
  include Normalizer
9
11
 
10
12
  def_delegators :SidekiqUniqueJobs, :config, :worker_class_constantize
11
- def_delegators :'Sidekiq.logger', :logger, :debug, :warn, :error, :fatal
13
+ def_delegators :Sidekiq, :logger
12
14
 
13
15
  def self.digest(item)
14
16
  new(item).unique_digest
15
17
  end
16
18
 
17
19
  def initialize(job)
18
- Sidekiq::Logging.with_context(self.class.name) do
20
+ Sidekiq::Logging.with_context(CLASS_NAME) do
19
21
  @item = job
20
- @worker_class ||= worker_class_constantize(@item['class'.freeze])
21
- @item['unique_prefix'.freeze] ||= unique_prefix
22
- @item['unique_args'.freeze] ||= unique_args(@item['args'.freeze])
23
- @item['unique_digest'.freeze] ||= unique_digest
22
+ @worker_class ||= worker_class_constantize(@item[CLASS_KEY])
23
+ @item[UNIQUE_PREFIX_KEY] ||= unique_prefix
24
+ @item[UNIQUE_ARGS_KEY] ||= unique_args(@item[ARGS_KEY])
25
+ @item[UNIQUE_DIGEST_KEY] ||= unique_digest
24
26
  end
25
27
  end
26
28
 
@@ -28,22 +30,24 @@ module SidekiqUniqueJobs
28
30
  @unique_digest ||= begin
29
31
  digest = Digest::MD5.hexdigest(Sidekiq.dump_json(digestable_hash))
30
32
  digest = "#{unique_prefix}:#{digest}"
31
- debug { "#{__method__} : #{digestable_hash} into #{digest}" }
33
+ logger.debug { "#{__method__} : #{digestable_hash} into #{digest}" }
32
34
  digest
33
35
  end
34
36
  end
35
37
 
36
38
  def unique_prefix
37
39
  return config.unique_prefix unless sidekiq_worker_class?
38
- @worker_class.get_sidekiq_options['unique_prefix'.freeze] || config.unique_prefix
40
+ @worker_class.get_sidekiq_options[UNIQUE_PREFIX_KEY] || config.unique_prefix
39
41
  end
40
42
 
41
43
  def digestable_hash
42
- hash = @item.slice('class', 'queue', 'unique_args')
44
+ hash = @item.slice(CLASS_KEY, QUEUE_KEY, UNIQUE_ARGS_KEY)
43
45
 
44
46
  if unique_on_all_queues?
45
- debug { "uniqueness specified across all queues (deleting queue: #{@item['queue']} from hash)" }
46
- hash.delete('queue')
47
+ logger.debug do
48
+ "uniqueness specified across all queues (deleting queue: #{@item[QUEUE_KEY]} from hash)"
49
+ end
50
+ hash.delete(QUEUE_KEY)
47
51
  end
48
52
  hash
49
53
  end
@@ -52,7 +56,7 @@ module SidekiqUniqueJobs
52
56
  if unique_args_enabled?
53
57
  filtered_args(args)
54
58
  else
55
- debug { "#{__method__} : unique arguments disabled" }
59
+ logger.debug { "#{__method__} : unique arguments disabled" }
56
60
  args
57
61
  end
58
62
  rescue NameError
@@ -62,26 +66,19 @@ module SidekiqUniqueJobs
62
66
 
63
67
  def unique_on_all_queues?
64
68
  return unless sidekiq_worker_class?
65
- return unless unique_args_enabled?
66
- @worker_class.get_sidekiq_options['unique_on_all_queues'.freeze]
69
+ @item[UNIQUE_ON_ALL_QUEUES_KEY] || @worker_class.get_sidekiq_options[UNIQUE_ON_ALL_QUEUES_KEY]
67
70
  end
68
71
 
69
72
  def unique_args_enabled?
70
- unique_args_enabled_in_worker? ||
71
- config.unique_args_enabled
72
- end
73
-
74
- def unique_args_enabled_in_worker?
75
73
  return unless sidekiq_worker_class?
76
- @worker_class.get_sidekiq_options['unique_args_enabled'.freeze] ||
77
- @worker_class.get_sidekiq_options['unique_args'.freeze]
74
+ unique_args_method # && !unique_args_method.is_a?(Boolean)
78
75
  end
79
76
 
80
77
  def sidekiq_worker_class?
81
78
  if @worker_class.respond_to?(:get_sidekiq_options)
82
79
  true
83
80
  else
84
- debug { "#{@worker_class} does not respond to :get_sidekiq_options" }
81
+ logger.debug { "#{@worker_class} does not respond to :get_sidekiq_options" }
85
82
  nil
86
83
  end
87
84
  end
@@ -91,7 +88,7 @@ module SidekiqUniqueJobs
91
88
  def filtered_args(args)
92
89
  return args if args.empty?
93
90
  json_args = Normalizer.jsonify(args)
94
- debug { "#filtered_args #{args} => #{json_args}" }
91
+ logger.debug { "#filtered_args #{args} => #{json_args}" }
95
92
 
96
93
  case unique_args_method
97
94
  when Proc
@@ -99,20 +96,24 @@ module SidekiqUniqueJobs
99
96
  when Symbol
100
97
  filter_by_symbol(json_args)
101
98
  else
102
- debug { 'arguments not filtered (the combined arguments count towards uniqueness)' }
99
+ logger.debug { 'arguments not filtered (the combined arguments count towards uniqueness)' }
103
100
  json_args
104
101
  end
105
102
  end
106
103
 
107
104
  def filter_by_proc(args)
105
+ if unique_args_method.nil?
106
+ warn { "#{__method__} : Proc was nil, returning args as is #{args} -> #{filter_args}" }
107
+ return args
108
+ end
108
109
  filter_args = unique_args_method.call(args)
109
- debug { "#{__method__} : #{args} -> #{filter_args}" }
110
+ logger.debug { "#{__method__} : #{args} -> #{filter_args}" }
110
111
  filter_args
111
112
  end
112
113
 
113
114
  def filter_by_symbol(args)
114
115
  unless @worker_class.respond_to?(unique_args_method)
115
- warn do
116
+ logger.warn do
116
117
  "#{__method__} : #{unique_args_method}) not defined in #{@worker_class} " \
117
118
  "returning #{args} unchanged"
118
119
  end
@@ -120,13 +121,14 @@ module SidekiqUniqueJobs
120
121
  end
121
122
 
122
123
  filter_args = @worker_class.send(unique_args_method, args)
123
- debug { "#{__method__} : #{unique_args_method}(#{args}) => #{filter_args}" }
124
+ logger.debug { "#{__method__} : #{unique_args_method}(#{args}) => #{filter_args}" }
124
125
  filter_args
125
126
  end
126
127
 
127
128
  def unique_args_method
128
- @unique_args_method ||=
129
- @worker_class.get_sidekiq_options['unique_args'.freeze] if sidekiq_worker_class?
129
+ @unique_args_method ||= @worker_class.get_sidekiq_options[UNIQUE_ARGS_KEY] if sidekiq_worker_class?
130
+ @unique_args_method ||= :unique_args if @worker_class.respond_to?(:unique_args)
131
+ @unique_args_method ||= Sidekiq.default_worker_options.stringify_keys[UNIQUE_ARGS_KEY]
130
132
  end
131
133
  end
132
134
  end
@@ -1,3 +1,3 @@
1
1
  module SidekiqUniqueJobs
2
- VERSION = '4.0.0'
2
+ VERSION = '4.0.7'
3
3
  end
@@ -7,7 +7,7 @@ end
7
7
 
8
8
  local stored_time = redis.pcall('get', unique_key)
9
9
  if stored_time and stored_time < time then
10
- if redis.call('set', unique_key, time + 60, 'nx', 'ex') then
10
+ if redis.pcall('set', unique_key, time + 60, 'xx', 'ex', 60) then
11
11
  return 1
12
12
  end
13
13
  end
@@ -19,7 +19,6 @@ Gem::Specification.new do |gem|
19
19
  gem.add_development_dependency 'rspec', '~> 3.1.0'
20
20
  gem.add_development_dependency 'rake'
21
21
  gem.add_development_dependency 'rspec-sidekiq'
22
- gem.add_development_dependency 'activesupport', '>= 3'
23
22
  gem.add_development_dependency 'rubocop'
24
- gem.add_development_dependency 'simplecov'
23
+ gem.add_development_dependency 'timecop'
25
24
  end
@@ -1,7 +1,7 @@
1
- class UniqueWorker
1
+ class AnotherUniqueJob
2
2
  include Sidekiq::Worker
3
- sidekiq_options queue: :working, retry: 1, backtrace: 10
4
- sidekiq_options unique: true, unique_lock: :until_executed
3
+ sidekiq_options queue: :working, retry: 1, backtrace: 10,
4
+ unique: :until_executed
5
5
 
6
6
  sidekiq_retries_exhausted do |msg|
7
7
  Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
@@ -1,4 +1,4 @@
1
- class QueueWorker
1
+ class CustomQueueJob
2
2
  include Sidekiq::Worker
3
3
  sidekiq_options queue: :customqueue
4
4
  def perform(_)
@@ -0,0 +1,7 @@
1
+ class CustomQueueJobWithFilterMethod < CustomQueueJob
2
+ sidekiq_options unique: :until_executed, unique_args: :args_filter
3
+
4
+ def self.args_filter(*args)
5
+ args.first
6
+ end
7
+ end
@@ -1,8 +1,7 @@
1
- class QueueWorkerWithFilterProc < QueueWorker
1
+ class CustomQueueJobWithFilterProc < CustomQueueJob
2
2
  # slightly contrived example of munging args to the
3
3
  # worker and removing a random bit.
4
- sidekiq_options unique: true,
5
- unique_lock: :until_timeout,
4
+ sidekiq_options unique: :until_timeout,
6
5
  unique_args: (lambda do |*args|
7
6
  options = args.extract_options!
8
7
  options.delete(:random)
@@ -0,0 +1,4 @@
1
+ class ExpiringJob
2
+ include Sidekiq::Worker
3
+ sidekiq_options unique: :until_executed, unique_expiration: 10 * 60
4
+ end
@@ -1,6 +1,6 @@
1
1
  class InlineWorker
2
2
  include Sidekiq::Worker
3
- sidekiq_options unique: true
3
+ sidekiq_options unique: :while_executing
4
4
 
5
5
  def perform(x)
6
6
  TestClass.run(x)
@@ -0,0 +1,8 @@
1
+ class JustAWorker
2
+ include Sidekiq::Worker
3
+
4
+ sidekiq_options unique: :until_executed, queue: 'testqueue'
5
+
6
+ def perform
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class MainJob
2
+ include Sidekiq::Worker
3
+ sidekiq_options queue: :customqueue, unique: :until_executed,
4
+ log_duplicate_payload: true
5
+
6
+ def perform(_)
7
+ end
8
+ end
@@ -1,7 +1,6 @@
1
- class MyWorker
1
+ class MyJob
2
2
  include Sidekiq::Worker
3
- sidekiq_options queue: :working, retry: 1, backtrace: 10
4
- sidekiq_options unique: false
3
+ sidekiq_options queue: :working, retry: 1, backtrace: 10, unique: false
5
4
 
6
5
  sidekiq_retries_exhausted do |msg|
7
6
  Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
@@ -0,0 +1,7 @@
1
+ class MyUniqueJob
2
+ include Sidekiq::Worker
3
+ sidekiq_options queue: :customqueue, retry: true, unique: :until_executed,
4
+ unique_expiration: 7_200, retry_count: 10
5
+ def perform(_)
6
+ end
7
+ end
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  class UniqueJobWithFilterMethod
2
2
  include Sidekiq::Worker
3
- sidekiq_options queue: :customqueue, retry: 1, backtrace: 10
4
- sidekiq_options unique: true, unique_args: :filtered_args
3
+ sidekiq_options queue: :customqueue, retry: 1, backtrace: 10,
4
+ unique: :while_executing, unique_args: :filtered_args
5
5
 
6
6
  sidekiq_retries_exhausted do |msg|
7
7
  Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
@@ -1,7 +1,7 @@
1
- class UniqueOnAllQueuesWorker
1
+ class UniqueOnAllQueuesJob
2
2
  include Sidekiq::Worker
3
- sidekiq_options queue: :working, retry: 1, backtrace: 10
4
- sidekiq_options unique: true, unique_on_all_queues: true, unique_lock: :until_executed
3
+ sidekiq_options queue: :working, retry: 1, backtrace: 10,
4
+ unique: :until_executed, unique_on_all_queues: true
5
5
 
6
6
  sidekiq_retries_exhausted do |msg|
7
7
  Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
@@ -0,0 +1,8 @@
1
+ class UntilAndWhileExecuting
2
+ include Sidekiq::Worker
3
+
4
+ sidekiq_options queue: :working, unique: :until_and_while_executing
5
+
6
+ def perform
7
+ end
8
+ end
@@ -1,7 +1,7 @@
1
- class AnotherUniqueWorker
1
+ class UntilExecutedJob
2
2
  include Sidekiq::Worker
3
3
  sidekiq_options queue: :working, retry: 1, backtrace: 10
4
- sidekiq_options unique: true, unique_lock: :until_executed
4
+ sidekiq_options unique: :until_executed
5
5
 
6
6
  sidekiq_retries_exhausted do |msg|
7
7
  Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
@@ -10,4 +10,8 @@ class AnotherUniqueWorker
10
10
  def perform(*)
11
11
  # NO-OP
12
12
  end
13
+
14
+ def after_unlock
15
+ fail 'HELL'
16
+ end
13
17
  end
@@ -0,0 +1,8 @@
1
+ class UntilExecutingJob
2
+ include Sidekiq::Worker
3
+
4
+ sidekiq_options queue: :working, unique: :until_executing
5
+
6
+ def perform
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class UntilGlobalTimeoutJob
2
+ include Sidekiq::Worker
3
+ sidekiq_options unique: :until_timeout
4
+
5
+ def perform(x)
6
+ TestClass.run(x)
7
+ end
8
+ end
@@ -1,6 +1,6 @@
1
- class InlineExpirationWorker
1
+ class UntilTimeoutJob
2
2
  include Sidekiq::Worker
3
- sidekiq_options unique: true, unique_lock: :until_timeout,
3
+ sidekiq_options unique: :until_timeout,
4
4
  unique_expiration: 10 * 60
5
5
  def perform(x)
6
6
  TestClass.run(x)
@@ -1,7 +1,6 @@
1
- class AfterUnlockWorker
1
+ class WhileExecutingJob
2
2
  include Sidekiq::Worker
3
- sidekiq_options queue: :working, retry: 1, backtrace: 10
4
- sidekiq_options unique: true, unique_lock: :until_executed
3
+ sidekiq_options queue: :working, retry: 1, backtrace: 10, unique: :while_executing
5
4
 
6
5
  sidekiq_retries_exhausted do |msg|
7
6
  Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}"
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'celluloid/current'
3
2
  require 'sidekiq/worker'
4
3
  require 'sidekiq-unique-jobs'
5
4
  require 'sidekiq/scheduled'
@@ -13,36 +12,50 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
13
12
  before do
14
13
  Sidekiq.redis = REDIS
15
14
  Sidekiq.redis(&:flushdb)
16
- QueueWorker.sidekiq_options unique: nil, unique_expiration: nil
17
15
  end
18
16
 
19
17
  describe 'when a job is already scheduled' do
20
- context '#new_unique_for' do
21
- it 'rejects new scheduled jobs with the same argument' do
22
- MyUniqueWorker.perform_in(3600, 1)
23
- expect(MyUniqueWorker.perform_in(3600, 1)).to eq(nil)
18
+ it 'rejects new scheduled jobs with the same argument' do
19
+ MyUniqueJob.perform_in(3600, 1)
20
+ expect(MyUniqueJob.perform_in(3600, 1)).to eq(nil)
21
+ end
22
+
23
+ it 'will run a job in real time with the same arguments' do
24
+ WhileExecutingJob.perform_in(3600, 1)
25
+ expect(WhileExecutingJob.perform_async(1)).not_to eq(nil)
26
+ end
27
+
28
+ it 'schedules new jobs when arguments differ' do
29
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].each do |x|
30
+ MainJob.perform_in(x, x)
24
31
  end
25
32
 
26
- it 'will run a job in real time with the same arguments' do
27
- WhileExecutingWorker.perform_in(3600, 1)
28
- expect(WhileExecutingWorker.perform_async(1)).not_to eq(nil)
33
+ Sidekiq.redis do |c|
34
+ count = c.zcount('schedule', -1, Time.now.to_f + 2 * 60)
35
+ expect(count).to eq(20)
29
36
  end
37
+ end
30
38
 
31
- it 'schedules new jobs when arguments differ' do
32
- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].each do |x|
33
- MainJob.perform_in(x.seconds.from_now, x)
39
+ it 'schedules allows jobs to be scheduled ' do
40
+ class ShitClass
41
+ def do_it(_arg)
42
+ # whatever
34
43
  end
44
+ end
35
45
 
36
- Sidekiq.redis do |c|
37
- count = c.zcount('schedule', -1, Time.now.to_f + 2 * 60)
38
- expect(count).to eq(20)
39
- end
46
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20].each do |x|
47
+ ShitClass.delay_for(x, unique: :while_executing).do_it(1)
48
+ end
49
+
50
+ Sidekiq.redis do |c|
51
+ count = c.zcount('schedule', -1, Time.now.to_f + 2 * 60)
52
+ expect(count).to eq(20)
40
53
  end
41
54
  end
42
55
  end
43
56
 
44
57
  it 'does not push duplicate messages when configured for unique only' do
45
- item = { 'class' => MyUniqueWorker, 'queue' => 'customqueue', 'args' => [1, 2] }
58
+ item = { 'class' => MyUniqueJob, 'queue' => 'customqueue', 'args' => [1, 2] }
46
59
  10.times { Sidekiq::Client.push(item) }
47
60
  Sidekiq.redis do |c|
48
61
  expect(c.llen('queue:customqueue')).to eq(1)
@@ -50,8 +63,8 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
50
63
  end
51
64
 
52
65
  it 'does push duplicate messages to different queues' do
53
- Sidekiq::Client.push('class' => MyUniqueWorker, 'queue' => 'customqueue', 'args' => [1, 2])
54
- Sidekiq::Client.push('class' => MyUniqueWorker, 'queue' => 'customqueue2', 'args' => [1, 2])
66
+ Sidekiq::Client.push('class' => MyUniqueJob, 'queue' => 'customqueue', 'args' => [1, 2])
67
+ Sidekiq::Client.push('class' => MyUniqueJob, 'queue' => 'customqueue2', 'args' => [1, 2])
55
68
  Sidekiq.redis do |c|
56
69
  expect(c.llen('queue:customqueue')).to eq 1
57
70
  expect(c.llen('queue:customqueue2')).to eq 1
@@ -59,14 +72,14 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
59
72
  end
60
73
 
61
74
  it 'does not queue duplicates when when calling delay' do
62
- 10.times { PlainClass.delay(unique_lock: :until_executed, unique: true, queue: 'customqueue').run(1) }
75
+ 10.times { PlainClass.delay(unique: :until_executed, queue: 'customqueue').run(1) }
63
76
  Sidekiq.redis do |c|
64
77
  expect(c.llen('queue:customqueue')).to eq(1)
65
78
  end
66
79
  end
67
80
 
68
81
  it 'does not schedule duplicates when calling perform_in' do
69
- 10.times { MyUniqueWorker.perform_in(60, [1, 2]) }
82
+ 10.times { MyUniqueJob.perform_in(60, [1, 2]) }
70
83
  Sidekiq.redis do |c|
71
84
  expect(c.zcount('schedule', -1, Time.now.to_f + 2 * 60))
72
85
  .to eq(1)
@@ -74,8 +87,8 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
74
87
  end
75
88
 
76
89
  it 'enqueues previously scheduled job' do
77
- jid = WhileExecutingWorker.perform_in(60 * 60, 1, 2)
78
- item = { 'class' => WhileExecutingWorker, 'queue' => 'customqueue', 'args' => [1, 2], 'jid' => jid }
90
+ jid = WhileExecutingJob.perform_in(60 * 60, 1, 2)
91
+ item = { 'class' => WhileExecutingJob, 'queue' => 'customqueue', 'args' => [1, 2], 'jid' => jid }
79
92
 
80
93
  # time passes and the job is pulled off the schedule:
81
94
  Sidekiq::Client.push(item)
@@ -86,18 +99,20 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
86
99
  end
87
100
 
88
101
  it 'sets an expiration when provided by sidekiq options' do
89
- item = { 'class' => ExpiringWorker, 'queue' => 'customqueue', 'args' => [1, 2] }
102
+ item = { 'class' => ExpiringJob, 'queue' => 'customqueue', 'args' => [1, 2] }
90
103
  Sidekiq::Client.push(item)
91
104
 
92
105
  Sidekiq.redis do |c|
93
106
  expect(c.llen('queue:customqueue')).to eq(1)
94
107
  expect(c.ttl(digest_for(item)))
95
- .to eq(ExpiringWorker.get_sidekiq_options['unique_expiration'])
108
+ .to eq(ExpiringJob.get_sidekiq_options['unique_expiration'])
96
109
  end
97
110
  end
98
111
 
99
112
  it 'does push duplicate messages when not configured for unique only' do
100
- 10.times { Sidekiq::Client.push('class' => QueueWorker, 'queue' => 'customqueue', 'args' => [1, 2]) }
113
+ 10.times do
114
+ Sidekiq::Client.push('class' => CustomQueueJob, 'queue' => 'customqueue', 'args' => [1, 2])
115
+ end
101
116
 
102
117
  Sidekiq.redis do |c|
103
118
  expect(c.llen('queue:customqueue')).to eq(10)
@@ -105,16 +120,13 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
105
120
  end
106
121
 
107
122
  describe 'when unique_args is defined' do
108
- before(:all) { SidekiqUniqueJobs.config.unique_args_enabled = true }
109
- after(:all) { SidekiqUniqueJobs.config.unique_args_enabled = false }
110
-
111
123
  it 'does not push duplicate messages based on args filter method' do
112
- expect(QueueWorkerWithFilterMethod).to respond_to(:args_filter)
113
- expect(QueueWorkerWithFilterMethod.get_sidekiq_options['unique_args']).to eq :args_filter
124
+ expect(CustomQueueJobWithFilterMethod).to respond_to(:args_filter)
125
+ expect(CustomQueueJobWithFilterMethod.get_sidekiq_options['unique_args']).to eq :args_filter
114
126
 
115
127
  (0..10).each do |i|
116
128
  Sidekiq::Client.push(
117
- 'class' => QueueWorkerWithFilterMethod,
129
+ 'class' => CustomQueueJobWithFilterMethod,
118
130
  'queue' => 'customqueue',
119
131
  'args' => [1, i]
120
132
  )
@@ -126,11 +138,11 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
126
138
  end
127
139
 
128
140
  it 'does not push duplicate messages based on args filter proc' do
129
- expect(QueueWorkerWithFilterProc.get_sidekiq_options['unique_args']).to be_a(Proc)
141
+ expect(CustomQueueJobWithFilterProc.get_sidekiq_options['unique_args']).to be_a(Proc)
130
142
 
131
143
  100.times do
132
144
  Sidekiq::Client.push(
133
- 'class' => QueueWorkerWithFilterProc,
145
+ 'class' => CustomQueueJobWithFilterProc,
134
146
  'queue' => 'customqueue',
135
147
  'args' => [1, { random: rand, name: 'foobar' }]
136
148
  )
@@ -143,7 +155,7 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
143
155
 
144
156
  describe 'when unique_on_all_queues is set' do
145
157
  it 'does not push duplicate messages on different queues' do
146
- item = { 'class' => UniqueOnAllQueuesWorker, 'args' => [1, 2] }
158
+ item = { 'class' => UniqueOnAllQueuesJob, 'args' => [1, 2] }
147
159
  Sidekiq::Client.push(item.merge('queue' => 'customqueue'))
148
160
  Sidekiq::Client.push(item.merge('queue' => 'customqueue2'))
149
161
  Sidekiq.redis do |c|
@@ -158,9 +170,9 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
158
170
  # jobs are set around the same time as the scheduled job itself feel free to improve.
159
171
  it 'expires the digest when a scheduled job is scheduled at' do
160
172
  expected_expires_at =
161
- (Time.at(15.minutes.from_now) - Time.now.utc) + SidekiqUniqueJobs.config.default_expiration
162
- jid = MyUniqueWorker.perform_in(expected_expires_at, 'mike')
163
- item = { 'class' => MyUniqueWorker,
173
+ (Time.at(Time.now.to_i + 15 * 60) - Time.now.utc) + SidekiqUniqueJobs.config.default_expiration
174
+ jid = MyUniqueJob.perform_in(expected_expires_at, 'mike')
175
+ item = { 'class' => MyUniqueJob,
164
176
  'queue' => 'customqueue',
165
177
  'args' => ['mike'],
166
178
  'at' => expected_expires_at }
@@ -172,24 +184,28 @@ RSpec.describe SidekiqUniqueJobs::Client::Middleware do
172
184
 
173
185
  it 'logs duplicate payload when config turned on' do
174
186
  expect(Sidekiq.logger).to receive(:warn).with(/^payload is not unique/)
175
- UniqueWorker.sidekiq_options log_duplicate_payload: true
176
- 2.times { Sidekiq::Client.push('class' => UniqueWorker, 'queue' => 'customqueue', 'args' => [1, 2]) }
187
+ UntilExecutedJob.sidekiq_options log_duplicate_payload: true
188
+ 2.times do
189
+ Sidekiq::Client.push('class' => UntilExecutedJob, 'queue' => 'customqueue', 'args' => [1, 2])
190
+ end
177
191
  Sidekiq.redis do |c|
178
192
  expect(c.llen('queue:customqueue')).to eq 1
179
193
  end
180
- UniqueWorker.sidekiq_options log_duplicate_payload: true
194
+ UntilExecutedJob.sidekiq_options log_duplicate_payload: true
181
195
  end
182
196
 
183
197
  it 'does not log duplicate payload when config turned off' do
184
198
  expect(Sidekiq.logger).to_not receive(:warn).with(/^payload is not unique/)
185
199
 
186
- UniqueWorker.sidekiq_options log_duplicate_payload: false
200
+ UntilExecutedJob.sidekiq_options log_duplicate_payload: false
187
201
 
188
- 2.times { Sidekiq::Client.push('class' => UniqueWorker, 'queue' => 'customqueue', 'args' => [1, 2]) }
202
+ 2.times do
203
+ Sidekiq::Client.push('class' => UntilExecutedJob, 'queue' => 'customqueue', 'args' => [1, 2])
204
+ end
189
205
  Sidekiq.redis do |c|
190
206
  expect(c.llen('queue:customqueue')).to eq 1
191
207
  end
192
- UniqueWorker.sidekiq_options log_duplicate_payload: true
208
+ UntilExecutedJob.sidekiq_options log_duplicate_payload: true
193
209
  end
194
210
  end
195
211
  end