resque-unique_by_arity 1.0.2 → 1.0.3
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 +4 -4
- data/README.md +1 -1
- data/lib/resque/unique_by_arity.rb +8 -0
- data/lib/resque/unique_by_arity/configuration.rb +34 -4
- data/lib/resque/unique_by_arity/cop.rb +3 -1
- data/lib/resque/unique_by_arity/cop_modulizer.rb +5 -5
- data/lib/resque/unique_by_arity/validation.rb +12 -0
- data/lib/resque/unique_by_arity/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74a015294d4c2dfa38a26395f3c83747c49cc380
|
4
|
+
data.tar.gz: 3a2aa2f9318deaab45185805561efde660c2dda0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f811ec7c91598ddd783b69c1eeedb6ca7f5bf0b2b75b04c5d637bd6cd143c4f3f292cb16f82cca03d2b72227c201a9690bbbe5f0dcd2ef45bd69e129859741e2
|
7
|
+
data.tar.gz: 7be024ae58c1a2a70c12add6f5b24d471bc7b85c6ac26db7c20b9d7236a7e3ee3d54a645d953ca350ca37a077a88460e2aca7655be8ad0f0f3cb8451d1774f40
|
data/README.md
CHANGED
@@ -158,7 +158,7 @@ class MyJob
|
|
158
158
|
def self.redis_unique_hash(payload)
|
159
159
|
# ... See source @ lib/resque/unique_by_arity/cop_modulizer.rb
|
160
160
|
# for how the built-in version works
|
161
|
-
# uniqueness_args = payload["args"] # over simplified
|
161
|
+
# uniqueness_args = payload["args"] # over simplified & ignoring arity
|
162
162
|
# args = { class: job, args: uniqueness_args }
|
163
163
|
# return [Digest::MD5.hexdigest(Resque.encode(args)), uniqueness_args]
|
164
164
|
end
|
@@ -9,12 +9,14 @@ require "resque/unique_by_arity/version"
|
|
9
9
|
require "resque/unique_by_arity/configuration"
|
10
10
|
require "resque/unique_by_arity/cop"
|
11
11
|
require "resque/unique_by_arity/cop_modulizer"
|
12
|
+
require "resque/unique_by_arity/validation"
|
12
13
|
|
13
14
|
# Usage:
|
14
15
|
#
|
15
16
|
# class MyJob
|
16
17
|
# include UniqueByArity::Cop.new(
|
17
18
|
# arity_for_uniqueness: 1,
|
19
|
+
# arity_for_validation: :warning, # or nil, false, or :error
|
18
20
|
# unique_at_runtime: true,
|
19
21
|
# unique_in_queue: true
|
20
22
|
# )
|
@@ -58,6 +60,12 @@ module Resque
|
|
58
60
|
def uniqueness_arity_for_uniqueness=(arity_for_uniqueness)
|
59
61
|
@uniqueness_configuration.arity_for_uniqueness = arity_for_uniqueness
|
60
62
|
end
|
63
|
+
def uniqueness_arity_for_validation
|
64
|
+
@uniqueness_configuration.arity_validation
|
65
|
+
end
|
66
|
+
def uniqueness_arity_for_validation=(arity_validation)
|
67
|
+
@uniqueness_configuration.arity_validation = arity_validation
|
68
|
+
end
|
61
69
|
def uniqueness_lock_after_execution_period
|
62
70
|
@uniqueness_configuration.lock_after_execution_period
|
63
71
|
end
|
@@ -2,9 +2,11 @@ require 'logger'
|
|
2
2
|
module Resque
|
3
3
|
module UniqueByArity
|
4
4
|
class Configuration
|
5
|
+
VALID_ARITY_VALIDATION_LEVELS = [ :warning, :error, nil, false ]
|
5
6
|
attr_accessor :logger
|
6
7
|
attr_accessor :log_level
|
7
8
|
attr_accessor :arity_for_uniqueness
|
9
|
+
attr_accessor :arity_validation
|
8
10
|
attr_accessor :lock_after_execution_period
|
9
11
|
attr_accessor :unique_at_runtime
|
10
12
|
attr_accessor :unique_in_queue
|
@@ -13,17 +15,20 @@ module Resque
|
|
13
15
|
@logger = options.key?(:logger) ? options[:logger] : Logger.new(STDOUT)
|
14
16
|
@log_level = options.key?(:log_level) ? options[:log_level] : :debug
|
15
17
|
@arity_for_uniqueness = options.key?(:arity_for_uniqueness) ? options[:arity_for_uniqueness] : 1
|
18
|
+
@arity_validation = options.key?(:arity_validation) ? options[:arity_validation] : :warning
|
19
|
+
raise ArgumentError, "UniqueByArity::Cop.new requires arity_validation values of nil, false, :warning, :error, or an class descending from Exception but the value is #{@arity_validation} (#{@arity_validation.class})" unless VALID_ARITY_VALIDATION_LEVELS.include?(@arity_validation) || @arity_validation.ancestors.include?(Exception)
|
16
20
|
@lock_after_execution_period = options.key?(:lock_after_execution_period) ? options[:lock_after_execution_period] : nil
|
17
21
|
@unique_at_runtime = options.key?(:unique_at_runtime) ? options[:unique_at_runtime] : false
|
18
22
|
@unique_in_queue = options.key?(:unique_in_queue) ? options[:unique_in_queue] : false
|
19
23
|
@unique_across_queues = options.key?(:unique_across_queues) ? options[:unique_across_queues] : false
|
20
24
|
# The default config initialization shouldn't trigger any warnings.
|
21
|
-
if options.keys.length > 0
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
if options.keys.length > 0 && @logger
|
26
|
+
Resque::UniqueByArity.unique_log ":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
|
27
|
+
Resque::UniqueByArity.unique_log ":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
|
28
|
+
Resque::UniqueByArity.unique_log ":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
|
25
29
|
end
|
26
30
|
end
|
31
|
+
|
27
32
|
def to_hash
|
28
33
|
{
|
29
34
|
logger: logger,
|
@@ -35,6 +40,31 @@ module Resque
|
|
35
40
|
unique_across_queues: unique_across_queues
|
36
41
|
}
|
37
42
|
end
|
43
|
+
|
44
|
+
def validate_arity(klass_string, perform_method)
|
45
|
+
return true unless arity_validation
|
46
|
+
# method.arity -
|
47
|
+
# Returns an indication of the number of arguments accepted by a method.
|
48
|
+
# Returns a non-negative integer for methods that take a fixed number of arguments.
|
49
|
+
# For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments.
|
50
|
+
# For methods written in C, returns -1 if the call takes a variable number of arguments.
|
51
|
+
# Example:
|
52
|
+
# for perform(opts = {}), method(:perform).arity # => -1
|
53
|
+
# which means that the only valid arity_for_uniqueness is 0
|
54
|
+
msg = if perform_method.arity < (arity_for_uniqueness - 1)
|
55
|
+
"#{klass_string}.#{perform_method.name} has arity of #{perform_method.arity} which will not work with arity_for_uniqueness of #{arity_for_uniqueness}"
|
56
|
+
elsif (required_parameter_names = perform_method.parameters.take_while { |a| a[0] == :req }.map { |b| b[1] }).length < arity_for_uniqueness
|
57
|
+
"#{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}"
|
58
|
+
end
|
59
|
+
case arity_validation
|
60
|
+
when :warning then
|
61
|
+
Resque::UniqueByArity.unique_log(msg)
|
62
|
+
when :error then
|
63
|
+
raise ArgumentError, msg
|
64
|
+
else
|
65
|
+
raise arity_validation, msg
|
66
|
+
end if msg
|
67
|
+
end
|
38
68
|
end
|
39
69
|
end
|
40
70
|
end
|
@@ -14,13 +14,15 @@ module Resque
|
|
14
14
|
# defines a redis_key method, which we have to override.
|
15
15
|
base.send(:include, Resque::Plugins::UniqueJob) if @configuration.unique_in_queue || @configuration.unique_across_queues
|
16
16
|
|
17
|
-
# gem is resque-unique_at_runtime
|
17
|
+
# gem is resque-unique_at_runtime, which is a rewrite of resque-lonely_job
|
18
18
|
# see: https://github.com/pboling/resque-unique_at_runtime
|
19
19
|
base.send(:extend, Resque::Plugins::UniqueAtRuntime) if @configuration.unique_at_runtime
|
20
20
|
|
21
21
|
uniqueness_cop_module = Resque::UniqueByArity::CopModulizer.to_mod(@configuration)
|
22
22
|
# This will override methods from both plugins above, if configured for both
|
23
23
|
base.send(:extend, uniqueness_cop_module)
|
24
|
+
|
25
|
+
base.singleton_class.prepend Resque::UniqueByArity::Validation
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -7,7 +7,7 @@ module Resque
|
|
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
|
-
|
10
|
+
Resque::UniqueByArity.unique_log "payload is #{payload.inspect}" if ENV['RESQUE_DEBUG'] == 'true'
|
11
11
|
job = payload["class"]
|
12
12
|
# It seems possible that some jobs may not have an "args" key in the payload.
|
13
13
|
args = payload["args"] || []
|
@@ -45,7 +45,7 @@ module Resque
|
|
45
45
|
define_method(:unique_at_queue_time_redis_key) do |queue, payload|
|
46
46
|
unique_hash, args_for_uniqueness = redis_unique_hash(payload)
|
47
47
|
key = "#{solo_key_namespace(queue)}:#{solo_redis_key_prefix}:#{unique_hash}"
|
48
|
-
|
48
|
+
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'
|
49
49
|
key
|
50
50
|
end
|
51
51
|
#
|
@@ -54,7 +54,7 @@ module Resque
|
|
54
54
|
# solo_key_namespace may or may not ignore the queue passed in, depending on config.
|
55
55
|
key_match = "#{solo_key_namespace(self.instance_variable_get(:@queue))}:#{solo_redis_key_prefix}:*"
|
56
56
|
keys = Resque.redis.keys(key_match)
|
57
|
-
|
57
|
+
Resque::UniqueByArity.unique_log "Purging #{keys.length} keys from #{ColorizedString[key_match].red}"
|
58
58
|
Resque.redis.del keys if keys.length > 0
|
59
59
|
end
|
60
60
|
if configuration.unique_in_queue
|
@@ -89,14 +89,14 @@ module Resque
|
|
89
89
|
define_method(:unique_at_runtime_redis_key) do |*args|
|
90
90
|
unique_hash, args_for_uniqueness = redis_unique_hash({"class" => self.to_s, "args" => args})
|
91
91
|
key = "#{runtime_key_namespace}:#{unique_hash}"
|
92
|
-
|
92
|
+
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'
|
93
93
|
key
|
94
94
|
end
|
95
95
|
# @return [Fixnum] number of keys that were deleted
|
96
96
|
define_method(:purge_unique_at_runtime_redis_keys) do
|
97
97
|
key_match = "#{runtime_key_namespace}:*"
|
98
98
|
keys = Resque.redis.keys(key_match)
|
99
|
-
|
99
|
+
Resque::UniqueByArity.unique_log "Purging #{keys.length} keys from #{ColorizedString[key_match].red}"
|
100
100
|
Resque.redis.del keys if keys.length > 0
|
101
101
|
end
|
102
102
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-unique_by_arity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Boling
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: resque-unique_at_runtime
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/resque/unique_by_arity/configuration.rb
|
115
115
|
- lib/resque/unique_by_arity/cop.rb
|
116
116
|
- lib/resque/unique_by_arity/cop_modulizer.rb
|
117
|
+
- lib/resque/unique_by_arity/validation.rb
|
117
118
|
- lib/resque/unique_by_arity/version.rb
|
118
119
|
- resque-unique_by_arity.gemspec
|
119
120
|
homepage: https://github.com/pboling/resque-unique_by_arity
|