resque-unique_by_arity 1.0.12 → 2.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f5928902e215fcf41c92705e36c57cc6a56e6d41aa200a0877ceb573bab8831d
4
- data.tar.gz: 5bf582a91c934187ef71a192dbcfa6bfb4374c2d6bd735cdaf5c9e467efebdcd
3
+ metadata.gz: 4ffc61efab34c9af47299c3527bee8da39876ed1e0a2bfd1144c05c0698f8f1b
4
+ data.tar.gz: f5604f556244558ff6893cfc57f09b5315f708db073463dd2644928d1cb51d1d
5
5
  SHA512:
6
- metadata.gz: 154e126d3b23d5646c2fcee110bf184cec637813cd6fcf5ab5f6f06dd89f9f58353c3b06413ccdc217ad049954638785418d44b96a8fc67d751482629179dfb6
7
- data.tar.gz: adae368b0a19f9d5ea756bbad1bc5384376515bcc083ce140a9e884ff376c66e8d6073df0a0677b1d07de2c1805220f6ea6293a7c6e1fb2f9ba3c149f0020355
6
+ metadata.gz: 3a71f1fc0529d0d1a42685a239b65e3d787d9650d4e96b217e3bdf8feed18b8cb5c45a7327e44b25ef83e0e11ca6a36a1f57ea5fb2d405726bdc694c18d54693
7
+ data.tar.gz: bdefff7d32f6f61df917344be934206e188c9c661db6692fe79f9ec0388b8a4b5dd57a5ac6f0e5fb1ca49930048412ec08ccdaf3138f4f45a4bfd9be8464ad82
data/.gitignore CHANGED
@@ -1,12 +1,17 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
-
11
- # rspec failure tracking
12
- .rspec_status
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec_status ADDED
@@ -0,0 +1,35 @@
1
+ example_id | status | run_time |
2
+ -------------------------------------------------- | ------ | --------------- |
3
+ ./spec/resque/unique_by_arity_spec.rb[1:1] | passed | 0.00088 seconds |
4
+ ./spec/resque/unique_by_arity_spec.rb[1:2:1:1] | passed | 0.00094 seconds |
5
+ ./spec/resque/unique_by_arity_spec.rb[1:3:1] | passed | 0.00017 seconds |
6
+ ./spec/resque/unique_by_arity_spec.rb[1:4:1:1] | passed | 0.00016 seconds |
7
+ ./spec/resque/unique_by_arity_spec.rb[1:5:1:1] | passed | 0.00159 seconds |
8
+ ./spec/resque/unique_by_arity_spec.rb[1:5:2:1] | passed | 0.00029 seconds |
9
+ ./spec/resque/unique_by_arity_spec.rb[1:5:3:1] | passed | 0.0003 seconds |
10
+ ./spec/resque/unique_by_arity_spec.rb[1:6:1] | passed | 0.00016 seconds |
11
+ ./spec/resque/unique_by_arity_spec.rb[1:7:1] | passed | 0.00033 seconds |
12
+ ./spec/resque/unique_by_arity_spec.rb[1:7:2:1] | passed | 0.00028 seconds |
13
+ ./spec/resque/unique_by_arity_spec.rb[1:7:3:1] | passed | 0.00036 seconds |
14
+ ./spec/resque/unique_by_arity_spec.rb[1:7:4:1] | passed | 0.00035 seconds |
15
+ ./spec/resque/unique_by_arity_spec.rb[1:8:1:1:1:1] | passed | 0.00811 seconds |
16
+ ./spec/resque/unique_by_arity_spec.rb[1:8:1:2:1:1] | passed | 0.0006 seconds |
17
+ ./spec/resque/unique_by_arity_spec.rb[1:8:1:3:1:1] | passed | 0.00104 seconds |
18
+ ./spec/resque/unique_by_arity_spec.rb[1:8:2:1:1:1] | passed | 0.00079 seconds |
19
+ ./spec/resque/unique_by_arity_spec.rb[1:8:2:2:1:1] | passed | 0.0003 seconds |
20
+ ./spec/resque/unique_by_arity_spec.rb[1:8:2:3:1:1] | passed | 0.00026 seconds |
21
+ ./spec/resque/unique_by_arity_spec.rb[1:8:3:1:1:1] | passed | 0.00042 seconds |
22
+ ./spec/resque/unique_by_arity_spec.rb[1:8:3:2:1:1] | passed | 0.00083 seconds |
23
+ ./spec/resque/unique_by_arity_spec.rb[1:8:3:3:1:1] | passed | 0.00028 seconds |
24
+ ./spec/resque/unique_by_arity_spec.rb[1:8:4:1:1:1] | passed | 0.00032 seconds |
25
+ ./spec/resque/unique_by_arity_spec.rb[1:8:4:2:1:1] | passed | 0.00076 seconds |
26
+ ./spec/resque/unique_by_arity_spec.rb[1:8:4:3:1:1] | passed | 0.00031 seconds |
27
+ ./spec/resque/unique_by_arity_spec.rb[1:8:5:1:1:1] | passed | 0.00032 seconds |
28
+ ./spec/resque/unique_by_arity_spec.rb[1:8:5:2:1:1] | passed | 0.001 seconds |
29
+ ./spec/resque/unique_by_arity_spec.rb[1:8:5:3:1] | passed | 0.00078 seconds |
30
+ ./spec/resque/unique_by_arity_spec.rb[1:9:1] | passed | 0.00452 seconds |
31
+ ./spec/resque/unique_by_arity_spec.rb[1:10:1:1] | passed | 0.00026 seconds |
32
+ ./spec/resque/unique_by_arity_spec.rb[1:11:1:1] | passed | 0.00052 seconds |
33
+ ./spec/resque/unique_by_arity_spec.rb[1:11:2:1:1] | passed | 0.00083 seconds |
34
+ ./spec/resque/unique_by_arity_spec.rb[1:11:2:2:1] | passed | 0.00264 seconds |
35
+ ./spec/resque/unique_by_arity_spec.rb[1:11:2:3:1] | passed | 0.00328 seconds |
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ inherit_from: .rubocop_todo.yml
2
+ TargetRubyVersion: 2.5
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,72 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-11-07 04:06:55 -0800 using RuboCop version 0.60.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: Include.
11
+ # Include: **/*.gemspec
12
+ Gemspec/RequiredRubyVersion:
13
+ Exclude:
14
+ - 'resque-unique_by_arity.gemspec'
15
+
16
+ # Offense count: 5
17
+ Metrics/AbcSize:
18
+ Max: 97
19
+
20
+ # Offense count: 8
21
+ # Configuration parameters: CountComments, ExcludedMethods.
22
+ # ExcludedMethods: refine
23
+ Metrics/BlockLength:
24
+ Max: 525
25
+
26
+ # Offense count: 4
27
+ Metrics/CyclomaticComplexity:
28
+ Max: 20
29
+
30
+ # Offense count: 5
31
+ # Configuration parameters: CountComments, ExcludedMethods.
32
+ Metrics/MethodLength:
33
+ Max: 72
34
+
35
+ # Offense count: 4
36
+ Metrics/PerceivedComplexity:
37
+ Max: 22
38
+
39
+ # Offense count: 4
40
+ Style/Documentation:
41
+ Exclude:
42
+ - 'spec/**/*'
43
+ - 'test/**/*'
44
+ - 'lib/resque/unique_by_arity.rb'
45
+ - 'lib/resque/unique_by_arity/configuration.rb'
46
+ - 'lib/resque/unique_by_arity/modulizer.rb'
47
+ - 'lib/resque/unique_by_arity/validation.rb'
48
+
49
+ # Offense count: 3
50
+ # Configuration parameters: MinBodyLength.
51
+ Style/GuardClause:
52
+ Exclude:
53
+ - 'lib/resque/unique_by_arity/configuration.rb'
54
+ - 'lib/resque/unique_by_arity/validation.rb'
55
+
56
+ # Offense count: 1
57
+ Style/IfInsideElse:
58
+ Exclude:
59
+ - 'lib/resque/unique_by_arity/configuration.rb'
60
+
61
+ # Offense count: 4
62
+ # Cop supports --auto-correct.
63
+ Style/IfUnlessModifier:
64
+ Exclude:
65
+ - 'lib/resque/unique_by_arity/configuration.rb'
66
+ - 'lib/resque/unique_by_arity/modulizer.rb'
67
+
68
+ # Offense count: 83
69
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
70
+ # URISchemes: http, https
71
+ Metrics/LineLength:
72
+ Max: 385
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.5.1
data/Gemfile CHANGED
@@ -2,12 +2,17 @@ source 'https://rubygems.org'
2
2
 
3
3
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
+ gem 'resque-unique_in_queue', path: '/Users/pboling/Documents/code/intricately/resque-unique_in_queue'
6
+ gem 'resque-unique_at_runtime', path: '/Users/pboling/Documents/code/intricately/resque-unique_at_runtime'
7
+
5
8
  group :test do
6
- gem 'rubocop', '~> 0.59.0'
7
- gem 'rubocop-rspec', '~> 1.24.0'
8
- gem 'byebug', '~> 10', platform: :mri, require: false
9
- gem 'pry', '~> 0', platform: :mri, require: false
10
- gem 'pry-byebug', '~> 3', platform: :mri, require: false
9
+ unless ENV['TRAVIS']
10
+ gem 'byebug', '~> 10', platform: :mri, require: false
11
+ gem 'pry', '~> 0', platform: :mri, require: false
12
+ gem 'pry-byebug', '~> 3', platform: :mri, require: false
13
+ end
14
+ gem 'rubocop', '~> 0.60.0'
15
+ gem 'rubocop-rspec', '~> 1.30.0'
11
16
  gem 'simplecov', '~> 0', require: false
12
17
  end
13
18
 
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2017 - 2018 Peter H. Boling
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -24,7 +24,11 @@ Why? `resque-lonely_job` and `resque_solo` can't be used together, because their
24
24
 
25
25
  ## Important Note
26
26
 
27
- You must configure this gem *after* you define the perform class method in your job or the arity validation will not work properly.
27
+ See `lib/resque/unique_by_arity/configuration.rb` for all config options. Only a smattering of what is available is documented in this README.
28
+
29
+ ## Most Important Note
30
+
31
+ You must configure this gem *after* you define the perform class method in your job or an error will be raised thanks to `perform` not having been defined yet.
28
32
 
29
33
  Example:
30
34
 
@@ -67,16 +71,13 @@ Some jobs have parameters that you do not want to consider for determination of
67
71
 
68
72
  ```ruby
69
73
  class MyJob
70
- def self.perform(arg1, arg2, arg3)
71
- # do stuff
74
+ def self.perform(my, cat, is, the, best, opts = {})
75
+ # Only the first 3: [my, cat, is] will be considered for determination of uniqueness
72
76
  end
73
77
  include UniqueByArity::Cop.new(
74
78
  arity_for_uniqueness: 3,
75
79
  unique_at_runtime: true
76
80
  )
77
- def self.perform(my, cat, is, the, best, opts = {})
78
- # Only the first 3: [my, cat, is] will be considered for determination of uniqueness
79
- end
80
81
  end
81
82
  ```
82
83
 
@@ -86,14 +87,6 @@ Want this gem to tell you when it is misconfigured? It can.
86
87
 
87
88
  ```ruby
88
89
  class MyJob
89
- def self.perform(arg1, arg2, arg3)
90
- # do stuff
91
- end
92
- include UniqueByArity::Cop.new(
93
- arity_for_uniqueness: 3,
94
- arity_validation: :warning, # or :skip, :error, or an error class to be raised, e.g. RuntimeError
95
- unique_at_runtime: true
96
- )
97
90
  def self.perform(my, cat, opts = {})
98
91
  # Because the third argument is optional the arity valdiation will not approve.
99
92
  # Arguments to be considered for uniqueness should be required arguments.
@@ -101,6 +94,11 @@ class MyJob
101
94
  #
102
95
  # MyJob.perform has the following required parameters: [:my, :cat], which is not enough to satisfy the configured arity_for_uniqueness of 3
103
96
  end
97
+ include UniqueByArity::Cop.new(
98
+ arity_for_uniqueness: 3,
99
+ arity_validation: :warning, # or :skip, :error, or an error class to be raised, e.g. RuntimeError
100
+ unique_at_runtime: true
101
+ )
104
102
  end
105
103
  ```
106
104
 
@@ -155,6 +153,17 @@ class MyJob
155
153
  end
156
154
  ```
157
155
 
156
+ #### Oops, I have stale runtime uniqueness keys for MyJob stored in Redis...
157
+
158
+ Preventing jobs with matching signatures from running, and they never get
159
+ dequeued because there is no actual corresponding job to dequeue.
160
+
161
+ *How to deal?*
162
+
163
+ ```ruby
164
+ MyJob.purge_unique_at_runtime_redis_keys
165
+ ```
166
+
158
167
  ### Unique At Queue Time
159
168
 
160
169
  #### Unique In Job's Specific Queue
@@ -189,6 +198,29 @@ class MyJob
189
198
  end
190
199
  ```
191
200
 
201
+ #### Oops, I have stale Queue Time uniqueness keys...
202
+
203
+ Preventing jobs with matching signatures from being queued, and they never get
204
+ dequeued because there is no actual corresponding job to dequeue.
205
+
206
+ *How to deal?*
207
+
208
+ Option: Rampage
209
+
210
+ ```ruby
211
+ # Delete *all* queued jobs in the queue, and
212
+ # delete *all* unqueness keys for the queue.
213
+ Redis.remove_queue('queue_name')
214
+ ```
215
+
216
+ Option: Butterfly
217
+
218
+ ```ruby
219
+ # Delete *no* queued jobs at all, and
220
+ # delete *all* unqueness keys for the queue (might then allow duplicates).
221
+ Resque::UniqueInQueue::Queue.cleanup('queue_name')
222
+ ```
223
+
192
224
  ### All Together Now
193
225
 
194
226
  #### Unique At Runtime (across all queues) AND Unique In Job's Specific Queue
@@ -231,7 +263,7 @@ end
231
263
 
232
264
  ### Debugging
233
265
 
234
- Run your worker with `RESQUE_DEBUG=true` to see payloads printed before they are used to determine uniqueness.
266
+ Run your worker with `RESQUE_DEBUG=true` to see payloads printed before they are used to determine uniqueness, as well as a lot of other debugging output.
235
267
 
236
268
  ### Customize Unique Keys Per Job
237
269
 
@@ -249,28 +281,28 @@ class MyJob
249
281
  # Core hashing algorithm for a job used for *all 3 types* of uniqueness
250
282
  # @return [Array<String, arguments>], where the string is the unique digest, and arguments are the specific args that were used to calculate the digest
251
283
  def self.redis_unique_hash(payload)
252
- # ... See source @ lib/resque/unique_by_arity/cop_modulizer.rb
284
+ modulizer.rb
253
285
  # for how the built-in version works
254
286
  # uniqueness_args = payload["args"] # over simplified & ignoring arity
255
287
  # args = { class: job, args: uniqueness_args }
256
288
  # return [Digest::MD5.hexdigest(Resque.encode(args)), uniqueness_args]
257
289
  end
258
290
 
259
- # Prefix to the unique key for a job for resque_solo, queue time uniqueness
260
- def self.solo_redis_key_prefix
291
+ unique_in_queue
292
+ def self.unique_at_runtime_redis_key_prefix
261
293
  # "unique_job:#{self}" # <= default value
262
294
  end
263
295
 
264
- # Prefix to the unique redis key for a job for resque_solo, queue time uniqueness
265
- def self.solo_key_namespace(queue = nil)
296
+ unique_in_queue
297
+ def self.unique_at_runtime_key_namespace(queue = nil)
266
298
  # definition depends on which type of uniqueness is chosen, be careful if you customize
267
- # "solo:queue:#{queue}:job" # <= is for unique within queue at queue time
268
- # "solo:across_queues:job" # <= is for unique across all queues at queue time
299
+ # "r-uiq:queue:#{queue}:job" # <= is for unique within queue at queue time
300
+ # "r-uiq:across_queues:job" # <= is for unique across all queues at queue time
269
301
  end
270
302
 
271
- def self.unique_at_queue_time_redis_key(queue, payload)
303
+ def self.unique_in_queue_redis_key(queue, payload)
272
304
  # unique_hash, _args_for_uniqueness = redis_unique_hash(payload)
273
- # "#{solo_key_namespace(queue)}:#{solo_redis_key_prefix}:#{unique_hash}"
305
+ # "#{unique_at_runtime_key_namespace(queue)}:#{unique_at_runtime_redis_key_prefix}:#{unique_hash}"
274
306
  end
275
307
 
276
308
  def self.runtime_key_namespace
data/Rakefile CHANGED
@@ -1,6 +1,10 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ #!/usr/bin/env rake
2
+ # frozen_string_literal: true
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
4
+ require 'bundler/gem_tasks'
5
+ require 'rspec/core/rake_task'
5
6
 
6
- task :default => :spec
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task default: :spec
10
+ task test: :spec
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "resque/unique_by_arity"
3
+ require 'bundler/setup'
4
+ require 'resque/unique_by_arity'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +10,5 @@ require "resque/unique_by_arity"
10
10
  # require "pry"
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
@@ -0,0 +1,55 @@
1
+ module Resque
2
+ module Plugins
3
+ # If you want your job to support uniqueness either at enqueue-time or at
4
+ # runtime, or both, and you want that uniqueness based on a specific arity
5
+ # of arguments, simply include this module into your job class.
6
+ #
7
+ # NOTE: This module gets instantiated.
8
+ # It is a module - class hybrid.
9
+ # That's unconventional, and extremely powerful.
10
+ #
11
+ # class EnqueueAndRunAlone
12
+ # @queue = :enqueue_and_run_alone
13
+ #
14
+ # def self.perform(arg1, arg2)
15
+ # alone_stuff
16
+ # end
17
+ # include Resque::Plugins::UniqueByArity.new(
18
+ # arity_for_uniqueness: 1,
19
+ # arity_validation: :warning, # or nil, false, or :error
20
+ # unique_at_runtime: true,
21
+ # unique_in_queue: true
22
+ # )
23
+ # end
24
+ #
25
+ class UniqueByArity < Module
26
+ def initialize(**config)
27
+ @configuration = Resque::UniqueByArity::Configuration.new(**config)
28
+ end
29
+
30
+ def included(base)
31
+ return unless @configuration
32
+
33
+ @configuration.base_klass_name = base.to_s
34
+ @configuration.validate
35
+ base.send(:extend, Resque::UniqueByArity)
36
+ base.uniqueness_config_reset(@configuration.dup)
37
+
38
+ # gem is unique_in_queue, which is a rewrite of resque-loner
39
+ # see: https://github.com/neighborland/resque_solo
40
+ # defines a redis_key method, which we have to override.
41
+ base.send(:include, Resque::Plugins::UniqueInQueue) if @configuration.unique_in_queue || @configuration.unique_across_queues
42
+
43
+ # gem is resque-unique_at_runtime, which is a rewrite of resque-lonely_job
44
+ # see: https://github.com/pboling/resque-unique_at_runtime
45
+ base.send(:extend, Resque::Plugins::UniqueAtRuntime) if @configuration.unique_at_runtime
46
+
47
+ uniqueness_cop_module = Resque::UniqueByArity::Modulizer.to_mod(@configuration)
48
+ # This will override methods from both plugins above, if configured for both
49
+ base.send(:extend, uniqueness_cop_module)
50
+
51
+ base.include Resque::UniqueByArity::Validation unless @configuration.skip_arity_validation?
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,20 +1,24 @@
1
- require "colorized_string"
1
+ require 'resque/unique_by_arity/version'
2
2
 
3
- require "resque-unique_at_runtime"
4
- require "resque_solo"
5
- # Little hack of the resque_solo gem
6
- require "resque/resque_solo/queue"
3
+ # External Gems
4
+ require 'colorized_string'
5
+ require 'resque'
7
6
 
8
- require "resque/unique_by_arity/version"
9
- require "resque/unique_by_arity/configuration"
10
- require "resque/unique_by_arity/cop"
11
- require "resque/unique_by_arity/cop_modulizer"
12
- require "resque/unique_by_arity/validation"
7
+ # External Resque Plugins
8
+ require 'resque-unique_in_queue'
9
+ require 'resque-unique_at_runtime'
10
+
11
+ require 'resque/plugins/unique_by_arity'
12
+ require 'resque/unique_by_arity/configuration'
13
+ require 'resque/unique_by_arity/modulizer'
14
+ require 'resque/unique_by_arity/validation'
13
15
 
14
16
  # Usage:
15
17
  #
16
18
  # class MyJob
17
- # include UniqueByArity::Cop.new(
19
+ # def self.perform(arg1, arg2)
20
+ # end
21
+ # include Resque::Plugins::UniqueByArity.new(
18
22
  # arity_for_uniqueness: 1,
19
23
  # arity_validation: :warning, # or nil, false, or :error
20
24
  # unique_at_runtime: true,
@@ -22,12 +26,23 @@ require "resque/unique_by_arity/validation"
22
26
  # )
23
27
  # end
24
28
  #
29
+ # NOTE: DO NOT include this module directly.
30
+ # Use the Resque::Plugins::UniqueByArity approach as above.
31
+ # This module is ultimately extended into the job class.
25
32
  module Resque
26
33
  module UniqueByArity
34
+ PLUGIN_TAG = (ColorizedString['[R-UBA] '].green).freeze
35
+
27
36
  def unique_log(message, config_proxy = nil)
28
37
  config_proxy ||= uniqueness_configuration
29
- config_proxy.unique_logger.send(config_proxy.unique_log_level, message) if config_proxy.unique_logger
38
+ config_proxy.unique_logger&.send(config_proxy.unique_log_level, message) if config_proxy.unique_logger
39
+ end
40
+
41
+ def unique_debug(message, config_proxy = nil)
42
+ config_proxy ||= uniqueness_configuration
43
+ config_proxy.unique_logger&.debug("#{Resque::UniqueByArity::PLUGIN_TAG}#{message}") if config_proxy.debug_mode
30
44
  end
45
+ module_function(:unique_log, :unique_debug)
31
46
 
32
47
  # There are times when the class will need access to the configuration object,
33
48
  # such as to override it per instance method
@@ -48,55 +63,70 @@ module Resque
48
63
  def uniqueness_config_reset(config = Configuration.new)
49
64
  @uniqueness_configuration = config
50
65
  end
66
+
51
67
  def uniqueness_log_level
52
68
  @uniqueness_configuration.log_level
53
69
  end
70
+
54
71
  def uniqueness_log_level=(log_level)
55
72
  @uniqueness_configuration.log_level = log_level
56
73
  end
74
+
57
75
  def uniqueness_arity_for_uniqueness
58
76
  @uniqueness_configuration.arity_for_uniqueness
59
77
  end
78
+
60
79
  def uniqueness_arity_for_uniqueness=(arity_for_uniqueness)
61
80
  @uniqueness_configuration.arity_for_uniqueness = arity_for_uniqueness
62
81
  end
82
+
63
83
  def uniqueness_arity_validation
64
84
  @uniqueness_configuration.arity_validation
65
85
  end
86
+
66
87
  def uniqueness_arity_validation=(arity_validation)
67
88
  @uniqueness_configuration.arity_validation = arity_validation
68
89
  end
90
+
69
91
  def uniqueness_lock_after_execution_period
70
92
  @uniqueness_configuration.lock_after_execution_period
71
93
  end
94
+
72
95
  def uniqueness_lock_after_execution_period=(lock_after_execution_period)
73
96
  @uniqueness_configuration.lock_after_execution_period = lock_after_execution_period
74
97
  end
98
+
75
99
  def uniqueness_runtime_lock_timeout
76
100
  @uniqueness_configuration.runtime_lock_timeout
77
101
  end
102
+
78
103
  def uniqueness_runtime_lock_timeout=(runtime_lock_timeout)
79
104
  @uniqueness_configuration.runtime_lock_timeout = runtime_lock_timeout
80
105
  end
106
+
81
107
  def uniqueness_unique_at_runtime
82
108
  @uniqueness_configuration.unique_at_runtime
83
109
  end
110
+
84
111
  def uniqueness_unique_at_runtime=(unique_at_runtime)
85
112
  @uniqueness_configuration.unique_at_runtime = unique_at_runtime
86
113
  end
114
+
87
115
  def uniqueness_unique_in_queue
88
116
  @uniqueness_configuration.unique_in_queue
89
117
  end
118
+
90
119
  def uniqueness_unique_in_queue=(unique_in_queue)
91
120
  @uniqueness_configuration.unique_in_queue = unique_in_queue
92
121
  end
122
+
93
123
  def uniqueness_unique_across_queues
94
124
  @uniqueness_configuration.unique_across_queues
95
125
  end
126
+
96
127
  def uniqueness_unique_across_queues=(unique_across_queues)
97
128
  @uniqueness_configuration.unique_across_queues = unique_across_queues
98
129
  end
99
130
  self.uniqueness_configuration = Configuration.new # setup defaults
100
- module_function(:unique_log)
101
131
  end
102
132
  end
@@ -2,36 +2,50 @@ require 'logger'
2
2
  module Resque
3
3
  module UniqueByArity
4
4
  class Configuration
5
- VALID_ARITY_VALIDATION_LEVELS = [ :warning, :error, :skip, nil, false ]
6
- SKIPPED_ARITY_VALIDATION_LEVELS = [ :skip, nil, false ]
5
+ VALID_ARITY_VALIDATION_LEVELS = [:warning, :error, :skip, nil, false].freeze
6
+ SKIPPED_ARITY_VALIDATION_LEVELS = [:skip, nil, false].freeze
7
+ DEFAULT_AT_RUNTIME_KEY_BASE = 'r-uar'.freeze
8
+ DEFAULT_IN_QUEUE_KEY_BASE = 'r-uiq'.freeze
7
9
  attr_accessor :logger
8
10
  attr_accessor :log_level
9
11
  attr_accessor :arity_for_uniqueness
10
12
  attr_accessor :arity_validation
11
13
  attr_accessor :lock_after_execution_period
12
14
  attr_accessor :runtime_lock_timeout
15
+ attr_accessor :runtime_requeue_interval
13
16
  attr_accessor :unique_at_runtime
17
+ attr_accessor :unique_at_runtime_key_base
14
18
  attr_accessor :unique_in_queue
19
+ attr_accessor :unique_in_queue_key_base
15
20
  attr_accessor :unique_across_queues
16
21
  attr_accessor :base_klass_name
22
+ attr_accessor :debug_mode
17
23
  def initialize(**options)
18
24
  @logger = options.key?(:logger) ? options[:logger] : Logger.new(STDOUT)
19
25
  @log_level = options.key?(:log_level) ? options[:log_level] : :debug
20
26
  @arity_for_uniqueness = options.key?(:arity_for_uniqueness) ? options[:arity_for_uniqueness] : 1
21
27
  @arity_validation = options.key?(:arity_validation) ? options[:arity_validation] : :warning
22
- raise ArgumentError, "UniqueByArity::Cop.new requires arity_validation values of #{arity_validation.inspect}, or a class inheriting from Exception, but the value is #{@arity_validation} (#{@arity_validation.class})" unless VALID_ARITY_VALIDATION_LEVELS.include?(@arity_validation) || !@arity_validation.respond_to?(:ancestors) || @arity_validation.ancestors.include?(Exception)
28
+ raise ArgumentError, "Resque::Plugins::UniqueByArity.new requires arity_validation values of #{arity_validation.inspect}, or a class inheriting from Exception, but the value is #{@arity_validation} (#{@arity_validation.class})" unless VALID_ARITY_VALIDATION_LEVELS.include?(@arity_validation) || !@arity_validation.respond_to?(:ancestors) || @arity_validation.ancestors.include?(Exception)
29
+
23
30
  @lock_after_execution_period = options.key?(:lock_after_execution_period) ? options[:lock_after_execution_period] : nil
24
31
  @runtime_lock_timeout = options.key?(:runtime_lock_timeout) ? options[:runtime_lock_timeout] : nil
32
+ @runtime_requeue_interval = options.key?(:runtime_requeue_interval) ? options[:runtime_requeue_interval] : nil
25
33
  @unique_at_runtime = options.key?(:unique_at_runtime) ? options[:unique_at_runtime] : false
34
+ @unique_at_runtime_key_base = options.key?(:unique_at_runtime_key_base) ? options[:unique_at_runtime_key_base] : DEFAULT_AT_RUNTIME_KEY_BASE
35
+ @unique_in_queue_key_base = options.key?(:unique_in_queue_key_base) ? options[:unique_in_queue_key_base] : DEFAULT_IN_QUEUE_KEY_BASE
26
36
  @unique_in_queue = options.key?(:unique_in_queue) ? options[:unique_in_queue] : false
27
37
  @unique_across_queues = options.key?(:unique_across_queues) ? options[:unique_across_queues] : false
38
+ env_debug = ENV['RESQUE_DEBUG']
39
+ @debug_mode = options.key?(:debug_mode) ? options[:debug_mode] : env_debug == 'true' || (env_debug.is_a?(String) && env_debug.match?(/arity/))
28
40
  end
29
41
 
30
42
  def validate
31
43
  # The default config initialization shouldn't trigger any warnings.
32
44
  if base_klass_name && logger
33
45
  log "[#{base_klass_name}] :arity_for_uniqueness is set to #{arity_for_uniqueness}, but no uniqueness enforcement was turned on [:unique_at_runtime, :unique_in_queue, :unique_across_queues]" unless unique_at_runtime || unique_in_queue || unique_across_queues
34
- log "[#{base_klass_name}] :lock_after_execution_period is set to #{lock_after_execution_period}, but :unique_at_runtime is not set" if lock_after_execution_period && !unique_at_runtime
46
+ log "[#{base_klass_name}] :lock_after_execution_period is set to #{lock_after_execution_period}, but :unique_at_runtime is not set" if lock_after_execution_period && !(unique_in_queue || unique_across_queues)
47
+ log "[#{base_klass_name}] :runtime_lock_timeout is set to #{runtime_lock_timeout}, but :unique_at_runtime is not set" if runtime_lock_timeout && !unique_at_runtime
48
+ log "[#{base_klass_name}] :runtime_requeue_interval is set to #{runtime_requeue_interval}, but :unique_at_runtime is not set" if runtime_requeue_interval && !unique_at_runtime
35
49
  log "[#{base_klass_name}] :unique_in_queue and :unique_across_queues should not be set at the same time, as :unique_across_queues will always supercede :unique_in_queue" if unique_in_queue && unique_across_queues
36
50
  end
37
51
  end
@@ -50,15 +64,15 @@ module Resque
50
64
 
51
65
  def to_hash
52
66
  {
53
- logger: logger,
54
- log_level: log_level,
55
- arity_for_uniqueness: arity_for_uniqueness,
56
- arity_validation: arity_validation,
57
- lock_after_execution_period: lock_after_execution_period,
58
- runtime_lock_timeout: runtime_lock_timeout,
59
- unique_at_runtime: unique_at_runtime,
60
- unique_in_queue: unique_in_queue,
61
- unique_across_queues: unique_across_queues
67
+ logger: logger,
68
+ log_level: log_level,
69
+ arity_for_uniqueness: arity_for_uniqueness,
70
+ arity_validation: arity_validation,
71
+ lock_after_execution_period: lock_after_execution_period,
72
+ runtime_lock_timeout: runtime_lock_timeout,
73
+ unique_at_runtime: unique_at_runtime,
74
+ unique_in_queue: unique_in_queue,
75
+ unique_across_queues: unique_across_queues
62
76
  }
63
77
  end
64
78
 
@@ -68,6 +82,7 @@ module Resque
68
82
 
69
83
  def validate_arity(klass_string, perform_method)
70
84
  return true if skip_arity_validation?
85
+
71
86
  # method.arity -
72
87
  # Returns an indication of the number of arguments accepted by a method.
73
88
  # Returns a non-negative integer for methods that take a fixed number of arguments.
@@ -83,7 +98,7 @@ module Resque
83
98
  "#{klass_string}.#{perform_method.name} has arity of #{perform_method.arity} which will not work with arity_for_uniqueness of #{arity_for_uniqueness}"
84
99
  end
85
100
  else
86
- if (perform_method.arity).abs < arity_for_uniqueness
101
+ if perform_method.arity.abs < arity_for_uniqueness
87
102
  # parform(a, b, c, opts = {}) # => arity == -4
88
103
  # and in this case arity for uniqueness can be 0, 1, 2, or 3, because 4 of the arguments are required
89
104
  "#{klass_string}.#{perform_method.name} has arity of #{perform_method.arity} which will not work with arity_for_uniqueness of #{arity_for_uniqueness}"
@@ -91,14 +106,16 @@ module Resque
91
106
  "#{klass_string}.#{perform_method.name} has the following required parameters: #{required_parameter_names}, which is not enough to satisfy the configured arity_for_uniqueness of #{arity_for_uniqueness}"
92
107
  end
93
108
  end
94
- case arity_validation
109
+ if msg
110
+ case arity_validation
95
111
  when :warning then
96
112
  log(ColorizedString[msg].red)
97
113
  when :error then
98
114
  raise ArgumentError, msg
99
115
  else
100
116
  raise arity_validation, msg
101
- end if msg
117
+ end
118
+ end
102
119
  end
103
120
  end
104
121
  end
@@ -1,42 +1,63 @@
1
1
  module Resque
2
2
  module UniqueByArity
3
- module CopModulizer
3
+ module Modulizer
4
4
  def self.to_mod(configuration)
5
5
  Module.new do
6
6
  if configuration.unique_in_queue || configuration.unique_at_runtime || configuration.unique_across_queues
7
7
  # @return [Array<String, arguments>] the key base hash used to enforce uniqueness, and the arguments from the payload used to calculate it
8
8
  define_method(:redis_unique_hash) do |payload|
9
9
  payload = Resque.decode(Resque.encode(payload))
10
- Resque::UniqueByArity.unique_log "payload is #{payload.inspect}" if ENV['RESQUE_DEBUG'] == 'true'
11
- job = payload["class"]
10
+ Resque::UniqueByArity.unique_debug("payload is #{payload.inspect}")
11
+ job = payload['class']
12
12
  # It seems possible that some jobs may not have an "args" key in the payload.
13
- args = payload["args"] || []
13
+ args = payload['args'] || []
14
14
  args.map! do |arg|
15
15
  arg.is_a?(Hash) ? arg.sort : arg
16
16
  end
17
17
  # what is the configured arity for uniqueness?
18
- # minus one because zero indexed
19
- uniqueness_args = args[0..(configuration.arity_for_uniqueness - 1)]
18
+ uniqueness_args = if configuration.arity_for_uniqueness.zero?
19
+ []
20
+ else
21
+ # minus one because zero indexed, so
22
+ # when arity_for_uniqueness is 2 we use args
23
+ # at indexes 0 and 1.
24
+ args[0..(configuration.arity_for_uniqueness - 1)]
25
+ end
20
26
  args = { class: job, args: uniqueness_args }
21
27
  return [Digest::MD5.hexdigest(Resque.encode(args)), uniqueness_args]
22
28
  end
23
29
  end
24
30
 
25
31
  if configuration.lock_after_execution_period
26
- self.instance_variable_set(:@lock_after_execution_period, configuration.lock_after_execution_period)
32
+ instance_variable_set(:@lock_after_execution_period, configuration.lock_after_execution_period)
27
33
  end
28
34
 
29
35
  if configuration.runtime_lock_timeout
30
- self.instance_variable_set(:@runtime_lock_timeout, configuration.runtime_lock_timeout)
36
+ instance_variable_set(:@runtime_lock_timeout, configuration.runtime_lock_timeout)
37
+ end
38
+
39
+ if configuration.runtime_requeue_interval
40
+ instance_variable_set(:@runtime_requeue_interval, configuration.runtime_requeue_interval)
41
+ end
42
+
43
+ if configuration.unique_at_runtime_key_base
44
+ instance_variable_set(:@unique_at_runtime_key_base, configuration.unique_at_runtime_key_base)
45
+ end
46
+
47
+ if configuration.unique_in_queue_key_base
48
+ # Can't be overridden per each class because it wouldn't make sense.
49
+ # It wouldn't be able to determine or enforce uniqueness across queues,
50
+ # and general cleanup of stray keys would be nearly impossible.
51
+ Resque::UniqueInQueue.uniq_config&.unique_in_queue_key_base = configuration.unique_in_queue_key_base
31
52
  end
32
53
 
33
54
  if configuration.unique_in_queue || configuration.unique_across_queues
34
- ### Gem: resque_solo
55
+ ### Gem: unique_in_queue
35
56
  ### Plugin Name: Resque::Plugins::UniqueJob
36
57
  ### Provides: Queue-time uniqueness for a single queue, or across queues
37
58
  #
38
59
  # Returns a string, used by Resque::Plugins::UniqueJob, that will be used as the prefix to the redis key
39
- define_method(:solo_redis_key_prefix) do
60
+ define_method(:unique_at_runtime_redis_key_prefix) do
40
61
  "unique_job:#{self}"
41
62
  end
42
63
  #
@@ -46,30 +67,30 @@ module Resque
46
67
  # Payload is what Resque stored for this job along with the job's class name:
47
68
  # a hash containing :class and :args
48
69
  # @return [String] the key used to enforce uniqueness (at queue-time)
49
- define_method(:unique_at_queue_time_redis_key) do |queue, payload|
70
+ define_method(:unique_in_queue_redis_key) do |queue, payload|
50
71
  unique_hash, args_for_uniqueness = redis_unique_hash(payload)
51
- key = "#{solo_key_namespace(queue)}:#{solo_redis_key_prefix}:#{unique_hash}"
52
- Resque::UniqueByArity.unique_log "#{ColorizedString['[Queue-Time]'].green} #{self}.unique_at_queue_time_redis_key for #{args_for_uniqueness} is: #{ColorizedString[key].green}" if ENV['RESQUE_DEBUG'] == 'true'
72
+ key = "#{unique_at_runtime_key_namespace(queue)}:#{unique_at_runtime_redis_key_prefix}:#{unique_hash}"
73
+ Resque::UniqueByArity.unique_debug("#{self}.unique_in_queue_redis_key for #{args_for_uniqueness} is: #{ColorizedString[key].green}")
53
74
  key
54
75
  end
55
76
  #
56
77
  # @return [Fixnum] number of keys that were deleted
57
78
  define_method(:purge_unique_queued_redis_keys) do
58
- # solo_key_namespace may or may not ignore the queue passed in, depending on config.
59
- key_match = "#{solo_key_namespace(self.instance_variable_get(:@queue))}:#{solo_redis_key_prefix}:*"
79
+ # unique_at_runtime_key_namespace may or may not ignore the queue passed in, depending on config.
80
+ key_match = "#{unique_at_runtime_key_namespace(instance_variable_get(:@queue))}:#{unique_at_runtime_redis_key_prefix}:*"
60
81
  keys = Resque.redis.keys(key_match)
61
- Resque::UniqueByArity.unique_log "Purging #{keys.length} keys from #{ColorizedString[key_match].red}"
62
- Resque.redis.del keys if keys.length > 0
82
+ Resque::UniqueByArity.unique_log("#{Resque::UniqueByArity::PLUGIN_TAG}#{Resque::UniqueInQueue::PLUGIN_TAG} Purging #{keys.length} keys from #{ColorizedString[key_match].red}")
83
+ Resque.redis.del keys unless keys.empty?
63
84
  end
64
85
  if configuration.unique_in_queue
65
86
  # @return [String] the Redis namespace of the key used to enforce uniqueness (at queue-time)
66
- define_method(:solo_key_namespace) do |queue = nil|
67
- "solo:queue:#{queue}:job"
87
+ define_method(:unique_at_runtime_key_namespace) do |queue = nil|
88
+ "#{configuration.unique_in_queue_key_base}:queue:#{queue}:job"
68
89
  end
69
90
  elsif configuration.unique_across_queues
70
91
  # @return [String] the Redis namespace of the key used to enforce uniqueness (at queue-time)
71
- define_method(:solo_key_namespace) do |_queue = nil|
72
- "solo:across_queues:job"
92
+ define_method(:unique_at_runtime_key_namespace) do |_queue = nil|
93
+ "#{configuration.unique_in_queue_key_base}:across_queues:job"
73
94
  end
74
95
  end
75
96
  end
@@ -80,29 +101,28 @@ module Resque
80
101
  if configuration.unique_at_runtime
81
102
  # @return [String] the Redis namespace of the key used to enforce uniqueness (at runtime)
82
103
  define_method(:runtime_key_namespace) do
83
- puts "runtime_key_namespace for #{self}"
84
- "unique_at_runtime:#{self}"
104
+ "#{configuration.unique_at_runtime_key_base}:#{self}"
85
105
  end
86
106
  # Returns a string, used by Resque::Plugins::UniqueAtRuntime, that will be used as the redis key
87
- # The versions of redis_key from resque_solo and resque-lonely_job are incompatible.
107
+ # The versions of redis_key from unique_in_queue and resque-lonely_job are incompatible.
88
108
  # So we forked resque-lonely_job, change the name of the method so it would not conflict,
89
109
  # and now we can override it, and fix the params to be compatible with the redis_key
90
- # from resque_solo
110
+ # from unique_in_queue
91
111
  # Does not need any customization for arity, because it funnels down to redis_key,
92
112
  # and we handle the arity option there
93
113
  # @return [String] the key used to enforce loneliness (uniqueness at runtime)
94
114
  define_method(:unique_at_runtime_redis_key) do |*args|
95
- unique_hash, args_for_uniqueness = redis_unique_hash({"class" => self.to_s, "args" => args})
115
+ unique_hash, args_for_uniqueness = redis_unique_hash('class' => to_s, 'args' => args)
96
116
  key = "#{runtime_key_namespace}:#{unique_hash}"
97
- Resque::UniqueByArity.unique_log "#{ColorizedString['[Run-Time]'].yellow} #{self}.unique_at_runtime_redis_key for #{args_for_uniqueness} is: #{ColorizedString[key].yellow}" if ENV['RESQUE_DEBUG'] == 'true'
117
+ Resque::UniqueByArity.unique_debug("#{ColorizedString['[R-UAR]'].yellow} #{self}.unique_at_runtime_redis_key for #{args_for_uniqueness} is: #{ColorizedString[key].yellow}")
98
118
  key
99
119
  end
100
120
  # @return [Fixnum] number of keys that were deleted
101
121
  define_method(:purge_unique_at_runtime_redis_keys) do
102
122
  key_match = "#{runtime_key_namespace}:*"
103
123
  keys = Resque.redis.keys(key_match)
104
- Resque::UniqueByArity.unique_log "Purging #{keys.length} keys from #{ColorizedString[key_match].red}"
105
- Resque.redis.del keys if keys.length > 0
124
+ Resque::UniqueByArity.unique_log("#{ColorizedString['[R-UBA][R-UAR]'].red} Purging #{keys.length} keys from #{ColorizedString[key_match].red}")
125
+ Resque.redis.del keys unless keys.empty?
106
126
  end
107
127
  end
108
128
  end
@@ -10,4 +10,3 @@ module Resque
10
10
  end
11
11
  end
12
12
  end
13
-
@@ -1,5 +1,5 @@
1
1
  module Resque
2
2
  module UniqueByArity
3
- VERSION = "1.0.12"
3
+ VERSION = '2.0.0'.freeze
4
4
  end
5
5
  end
@@ -1,31 +1,37 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'resque/unique_by_arity/version'
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('lib/resque/unique_by_arity/version', __dir__)
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "resque-unique_by_arity"
6
+ spec.name = 'resque-unique_by_arity'
8
7
  spec.version = Resque::UniqueByArity::VERSION
9
- spec.authors = ["Peter Boling"]
10
- spec.email = ["peter.boling@gmail.com"]
11
- spec.license = "MIT"
8
+ spec.authors = ['Peter H. Boling']
9
+ spec.email = ['peter.boling@gmail.com']
10
+ spec.license = 'MIT'
12
11
 
13
- spec.summary = %q{Magic hacks which allow integration of resque_solo and resque-unique_at_runtime_simultaneously into Resque jobs}
14
- spec.description = %q{fixes incompatibilities between resque_solo and resque-unique_at_runtime}
15
- spec.homepage = "https://github.com/pboling/resque-unique_by_arity"
16
- spec.required_ruby_version = ">= 2.0.0"
12
+ spec.summary = 'Configure resque-unique_in_queue and resque-unique_at_runtime uniqueness by arity of perform method'
13
+ spec.description = 'Configure resque-unique_in_queue and resque-unique_at_runtime uniqueness by arity of perform method, with automated cleanup tools'
14
+ spec.homepage = 'https://github.com/pboling/resque-unique_by_arity'
15
+ spec.required_ruby_version = '>= 2.3.0'
17
16
 
18
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
18
  f.match(%r{^(test|spec|features)/})
20
19
  end
21
- spec.bindir = "exe"
22
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
- spec.require_paths = ["lib"]
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_runtime_dependency 'colorize', '~> 0.8'
23
+ spec.add_runtime_dependency 'resque', '>= 1.2'
24
+ spec.add_runtime_dependency 'resque-unique_in_queue', '~> 1.0'
25
+ spec.add_runtime_dependency 'resque-unique_at_runtime', '~> 3.0'
24
26
 
25
- spec.add_runtime_dependency "resque-unique_at_runtime", "~> 2.0"
26
- spec.add_runtime_dependency "resque_solo", "~> 0.3"
27
- spec.add_runtime_dependency "colorize", "~> 0.8"
28
- spec.add_development_dependency "bundler", "~> 1.14"
29
- spec.add_development_dependency "rake", "~> 12.3"
30
- spec.add_development_dependency "rspec", "~> 3.0"
27
+ spec.add_development_dependency 'bundler', '~> 1.16'
28
+ spec.add_development_dependency 'byebug', '~> 10.0'
29
+ spec.add_development_dependency 'pry', '~> 0.11'
30
+ spec.add_development_dependency 'pry-byebug', '~> 3.6'
31
+ spec.add_development_dependency 'rake', '~> 12.3'
32
+ spec.add_development_dependency 'rspec', '~> 3.0'
33
+ spec.add_development_dependency 'rspec-block_is_expected', '~> 1.0'
34
+ spec.add_development_dependency 'rspec-stubbed_env', '~> 1.0'
35
+ spec.add_development_dependency 'rubocop', '~> 0.60'
36
+ spec.add_development_dependency 'rubocop-rspec', '~> 1.30'
31
37
  end
metadata CHANGED
@@ -1,71 +1,127 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resque-unique_by_arity
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.12
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Peter Boling
7
+ - Peter H. Boling
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-10 00:00:00.000000000 Z
11
+ date: 2018-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: resque-unique_at_runtime
14
+ name: colorize
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '0.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '0.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: resque
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.2'
27
41
  - !ruby/object:Gem::Dependency
28
- name: resque_solo
42
+ name: resque-unique_in_queue
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '0.3'
47
+ version: '1.0'
34
48
  type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '0.3'
54
+ version: '1.0'
41
55
  - !ruby/object:Gem::Dependency
42
- name: colorize
56
+ name: resque-unique_at_runtime
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '0.8'
61
+ version: '3.0'
48
62
  type: :runtime
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '0.8'
68
+ version: '3.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '1.14'
75
+ version: '1.16'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.16'
83
+ - !ruby/object:Gem::Dependency
84
+ name: byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.11'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.11'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.6'
62
118
  type: :development
63
119
  prerelease: false
64
120
  version_requirements: !ruby/object:Gem::Requirement
65
121
  requirements:
66
122
  - - "~>"
67
123
  - !ruby/object:Gem::Version
68
- version: '1.14'
124
+ version: '3.6'
69
125
  - !ruby/object:Gem::Dependency
70
126
  name: rake
71
127
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +150,64 @@ dependencies:
94
150
  - - "~>"
95
151
  - !ruby/object:Gem::Version
96
152
  version: '3.0'
97
- description: fixes incompatibilities between resque_solo and resque-unique_at_runtime
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec-block_is_expected
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rspec-stubbed_env
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '1.0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '1.0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: '0.60'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '0.60'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rubocop-rspec
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '1.30'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '1.30'
209
+ description: Configure resque-unique_in_queue and resque-unique_at_runtime uniqueness
210
+ by arity of perform method, with automated cleanup tools
98
211
  email:
99
212
  - peter.boling@gmail.com
100
213
  executables: []
@@ -103,17 +216,21 @@ extra_rdoc_files: []
103
216
  files:
104
217
  - ".gitignore"
105
218
  - ".rspec"
219
+ - ".rspec_status"
220
+ - ".rubocop.yml"
221
+ - ".rubocop_todo.yml"
222
+ - ".ruby-version"
106
223
  - ".travis.yml"
107
224
  - Gemfile
225
+ - LICENSE
108
226
  - README.md
109
227
  - Rakefile
110
228
  - bin/console
111
229
  - bin/setup
112
- - lib/resque/resque_solo/queue.rb
230
+ - lib/resque/plugins/unique_by_arity.rb
113
231
  - lib/resque/unique_by_arity.rb
114
232
  - lib/resque/unique_by_arity/configuration.rb
115
- - lib/resque/unique_by_arity/cop.rb
116
- - lib/resque/unique_by_arity/cop_modulizer.rb
233
+ - lib/resque/unique_by_arity/modulizer.rb
117
234
  - lib/resque/unique_by_arity/validation.rb
118
235
  - lib/resque/unique_by_arity/version.rb
119
236
  - resque-unique_by_arity.gemspec
@@ -129,7 +246,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
129
246
  requirements:
130
247
  - - ">="
131
248
  - !ruby/object:Gem::Version
132
- version: 2.0.0
249
+ version: 2.3.0
133
250
  required_rubygems_version: !ruby/object:Gem::Requirement
134
251
  requirements:
135
252
  - - ">="
@@ -140,6 +257,6 @@ rubyforge_project:
140
257
  rubygems_version: 2.7.7
141
258
  signing_key:
142
259
  specification_version: 4
143
- summary: Magic hacks which allow integration of resque_solo and resque-unique_at_runtime_simultaneously
144
- into Resque jobs
260
+ summary: Configure resque-unique_in_queue and resque-unique_at_runtime uniqueness
261
+ by arity of perform method
145
262
  test_files: []
@@ -1,9 +0,0 @@
1
- module ResqueSoloUniqueHack
2
- def unique_key(queue, item)
3
- # "solo:queue:#{queue}:job:#{const_for(item).redis_key(item)}"
4
- const_for(item).unique_at_queue_time_redis_key(queue, item)
5
- # NOTE: DOES NOT CALL SUPER
6
- end
7
- end
8
-
9
- ResqueSolo::Queue.singleton_class.prepend ResqueSoloUniqueHack
@@ -1,31 +0,0 @@
1
- module Resque
2
- module UniqueByArity
3
- class Cop < Module
4
- def initialize(**config)
5
- @configuration = Resque::UniqueByArity::Configuration.new(**config)
6
- end
7
- def included(base)
8
- return unless @configuration
9
- @configuration.base_klass_name = base.to_s
10
- @configuration.validate
11
- base.send(:extend, Resque::UniqueByArity)
12
- base.uniqueness_config_reset(@configuration.dup)
13
-
14
- # gem is resque_solo, which is a rewrite of resque-loner
15
- # see: https://github.com/neighborland/resque_solo
16
- # defines a redis_key method, which we have to override.
17
- base.send(:include, Resque::Plugins::UniqueJob) if @configuration.unique_in_queue || @configuration.unique_across_queues
18
-
19
- # gem is resque-unique_at_runtime, which is a rewrite of resque-lonely_job
20
- # see: https://github.com/pboling/resque-unique_at_runtime
21
- base.send(:extend, Resque::Plugins::UniqueAtRuntime) if @configuration.unique_at_runtime
22
-
23
- uniqueness_cop_module = Resque::UniqueByArity::CopModulizer.to_mod(@configuration)
24
- # This will override methods from both plugins above, if configured for both
25
- base.send(:extend, uniqueness_cop_module)
26
-
27
- base.include Resque::UniqueByArity::Validation unless @configuration.skip_arity_validation?
28
- end
29
- end
30
- end
31
- end