resque-unique_by_arity 1.0.12 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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