resque-unique_by_arity 1.0.8 → 1.0.9
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 +39 -0
- data/lib/resque/unique_by_arity/configuration.rb +24 -7
- data/lib/resque/unique_by_arity/cop.rb +1 -1
- data/lib/resque/unique_by_arity/cop_modulizer.rb +6 -1
- data/lib/resque/unique_by_arity/validation.rb +4 -2
- data/lib/resque/unique_by_arity/version.rb +1 -1
- data/lib/resque/unique_by_arity.rb +7 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06ef1c526f5dea1a56e51bbf8053e41854ec9e94
|
4
|
+
data.tar.gz: 8bbd6cae274b5a245019e88b6297672eb66bfb92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08fec6b73c8f0cb6d28a82d4b0b639835088dbe180f3f28ec86201b2256687dc92839d2added60f36a64b7930c2d0bea132412e2c7787e17ab8251c37f500f5f'
|
7
|
+
data.tar.gz: bd024532330e4b82dac8e41f6b26c5747ec68f36a3a3a7db468c027a9e369dc003836ab150c20d18c36628dddc3b7ebc9ad33f568c508ae51378002937759df8
|
data/README.md
CHANGED
@@ -12,6 +12,7 @@ class MyJob
|
|
12
12
|
include UniqueByArity::Cop.new(
|
13
13
|
arity_for_uniqueness: 1,
|
14
14
|
lock_after_execution_period: 60,
|
15
|
+
runtime_lock_timeout: 60 * 60 * 24 * 5, # 5 days
|
15
16
|
unique_at_runtime: true,
|
16
17
|
unique_in_queue: true
|
17
18
|
)
|
@@ -52,6 +53,28 @@ class MyJob
|
|
52
53
|
end
|
53
54
|
```
|
54
55
|
|
56
|
+
#### Arity For Uniqueness Validation
|
57
|
+
|
58
|
+
Want this gem to tell you when it is misconfigured? It can.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class MyJob
|
62
|
+
include UniqueByArity::Cop.new(
|
63
|
+
arity_for_uniqueness: 3,
|
64
|
+
arity_validation: :warning, # or :skip, :error, or an error class to be raised, e.g. RuntimeError
|
65
|
+
unique_at_runtime: true
|
66
|
+
)
|
67
|
+
def self.perform(my, cat, opts = {})
|
68
|
+
# Because the third argument is optional the arity valdiation will not approve.
|
69
|
+
# Arguments to be considered for uniqueness should be required arguments.
|
70
|
+
# The warning log might look like:
|
71
|
+
#
|
72
|
+
# MyJob.perform has the following required parameters: [:my, :cat], which is not enough to satisfy the configured arity_for_uniqueness of 3
|
73
|
+
end
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
|
55
78
|
### Lock After Execution
|
56
79
|
|
57
80
|
Give the job a break after it finishes running, and don't allow another of the same, with matching args @ configured arity, to start within X seconds.
|
@@ -66,6 +89,20 @@ class MyJob
|
|
66
89
|
end
|
67
90
|
```
|
68
91
|
|
92
|
+
### Runtime Lock Timeout
|
93
|
+
|
94
|
+
If runtime lock keys get stale, they will expire on their own after some period. You can set the expiration period on a per class basis.
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
class MyJob
|
98
|
+
include UniqueByArity::Cop.new(
|
99
|
+
arity_for_uniqueness: 1,
|
100
|
+
runtime_lock_timeout: 60 * 60 * 24 * 5, # 5 days
|
101
|
+
unique_at_runtime: true
|
102
|
+
)
|
103
|
+
end
|
104
|
+
```
|
105
|
+
|
69
106
|
### Unique At Runtime (across all queues)
|
70
107
|
|
71
108
|
Prevent your app from running a job that is already running.
|
@@ -119,6 +156,7 @@ class MyJob
|
|
119
156
|
include UniqueByArity::Cop.new(
|
120
157
|
arity_for_uniqueness: 1,
|
121
158
|
unique_at_runtime: true,
|
159
|
+
runtime_lock_timeout: 60 * 60 * 24 * 5, # 5 days
|
122
160
|
unique_in_queue: true
|
123
161
|
)
|
124
162
|
end
|
@@ -134,6 +172,7 @@ class MyJob
|
|
134
172
|
include UniqueByArity::Cop.new(
|
135
173
|
arity_for_uniqueness: 1,
|
136
174
|
unique_at_runtime: true,
|
175
|
+
runtime_lock_timeout: 60 * 60 * 24 * 5, # 5 days
|
137
176
|
unique_across_queues: true
|
138
177
|
)
|
139
178
|
end
|
@@ -8,6 +8,7 @@ module Resque
|
|
8
8
|
attr_accessor :arity_for_uniqueness
|
9
9
|
attr_accessor :arity_validation
|
10
10
|
attr_accessor :lock_after_execution_period
|
11
|
+
attr_accessor :runtime_lock_timeout
|
11
12
|
attr_accessor :unique_at_runtime
|
12
13
|
attr_accessor :unique_in_queue
|
13
14
|
attr_accessor :unique_across_queues
|
@@ -15,9 +16,10 @@ module Resque
|
|
15
16
|
@logger = options.key?(:logger) ? options[:logger] : Logger.new(STDOUT)
|
16
17
|
@log_level = options.key?(:log_level) ? options[:log_level] : :debug
|
17
18
|
@arity_for_uniqueness = options.key?(:arity_for_uniqueness) ? options[:arity_for_uniqueness] : 1
|
18
|
-
@arity_validation = options.key?(:arity_validation) ? options[:arity_validation] :
|
19
|
+
@arity_validation = options.key?(:arity_validation) ? options[:arity_validation] : :warning
|
19
20
|
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)
|
20
21
|
@lock_after_execution_period = options.key?(:lock_after_execution_period) ? options[:lock_after_execution_period] : nil
|
22
|
+
@runtime_lock_timeout = options.key?(:runtime_lock_timeout) ? options[:runtime_lock_timeout] : nil
|
21
23
|
@unique_at_runtime = options.key?(:unique_at_runtime) ? options[:unique_at_runtime] : false
|
22
24
|
@unique_in_queue = options.key?(:unique_in_queue) ? options[:unique_in_queue] : false
|
23
25
|
@unique_across_queues = options.key?(:unique_across_queues) ? options[:unique_across_queues] : false
|
@@ -47,14 +49,19 @@ module Resque
|
|
47
49
|
log_level: log_level,
|
48
50
|
arity_for_uniqueness: arity_for_uniqueness,
|
49
51
|
lock_after_execution_period: lock_after_execution_period,
|
52
|
+
runtime_lock_timeout: runtime_lock_timeout,
|
50
53
|
unique_at_runtime: unique_at_runtime,
|
51
54
|
unique_in_queue: unique_in_queue,
|
52
55
|
unique_across_queues: unique_across_queues
|
53
56
|
}
|
54
57
|
end
|
55
58
|
|
59
|
+
def skip_arity_validation?
|
60
|
+
arity_validation == :skip
|
61
|
+
end
|
62
|
+
|
56
63
|
def validate_arity(klass_string, perform_method)
|
57
|
-
return true
|
64
|
+
return true if skip_arity_validation?
|
58
65
|
# method.arity -
|
59
66
|
# Returns an indication of the number of arguments accepted by a method.
|
60
67
|
# Returns a non-negative integer for methods that take a fixed number of arguments.
|
@@ -63,14 +70,24 @@ module Resque
|
|
63
70
|
# Example:
|
64
71
|
# for perform(opts = {}), method(:perform).arity # => -1
|
65
72
|
# which means that the only valid arity_for_uniqueness is 0
|
66
|
-
msg = if perform_method.arity
|
67
|
-
|
68
|
-
|
69
|
-
|
73
|
+
msg = if perform_method.arity >= 0
|
74
|
+
# takes a fixed number of arguments
|
75
|
+
# parform(a, b, c) # => arity == 3, so arity for uniqueness can be 0, 1, 2, or 3
|
76
|
+
if perform_method.arity < arity_for_uniqueness
|
77
|
+
"#{klass_string}.#{perform_method.name} has arity of #{perform_method.arity} which will not work with arity_for_uniqueness of #{arity_for_uniqueness}"
|
78
|
+
end
|
79
|
+
else
|
80
|
+
if (perform_method.arity).abs < arity_for_uniqueness
|
81
|
+
# parform(a, b, c, opts = {}) # => arity == -4
|
82
|
+
# and in this case arity for uniqueness can be 0, 1, 2, or 3, because 4 of the arguments are required
|
83
|
+
"#{klass_string}.#{perform_method.name} has arity of #{perform_method.arity} which will not work with arity_for_uniqueness of #{arity_for_uniqueness}"
|
84
|
+
elsif (required_parameter_names = perform_method.parameters.take_while { |a| a[0] == :req }.map { |b| b[1] }).length < arity_for_uniqueness
|
85
|
+
"#{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}"
|
86
|
+
end
|
70
87
|
end
|
71
88
|
case arity_validation
|
72
89
|
when :warning then
|
73
|
-
log(msg)
|
90
|
+
log(ColorizedString[msg].red)
|
74
91
|
when :error then
|
75
92
|
raise ArgumentError, msg
|
76
93
|
else
|
@@ -22,7 +22,7 @@ module Resque
|
|
22
22
|
# This will override methods from both plugins above, if configured for both
|
23
23
|
base.send(:extend, uniqueness_cop_module)
|
24
24
|
|
25
|
-
base.include Resque::UniqueByArity::Validation
|
25
|
+
base.include Resque::UniqueByArity::Validation unless @configuration.skip_arity_validation?
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -25,7 +25,11 @@ module Resque
|
|
25
25
|
if configuration.lock_after_execution_period
|
26
26
|
self.instance_variable_set(:@lock_after_execution_period, configuration.lock_after_execution_period)
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
|
+
if configuration.runtime_lock_timeout
|
30
|
+
self.instance_variable_set(:@runtime_lock_timeout, configuration.runtime_lock_timeout)
|
31
|
+
end
|
32
|
+
|
29
33
|
if configuration.unique_in_queue || configuration.unique_across_queues
|
30
34
|
### Gem: resque_solo
|
31
35
|
### Plugin Name: Resque::Plugins::UniqueJob
|
@@ -76,6 +80,7 @@ module Resque
|
|
76
80
|
if configuration.unique_at_runtime
|
77
81
|
# @return [String] the Redis namespace of the key used to enforce uniqueness (at runtime)
|
78
82
|
define_method(:runtime_key_namespace) do
|
83
|
+
puts "runtime_key_namespace for #{self}"
|
79
84
|
"unique_at_runtime:#{self}"
|
80
85
|
end
|
81
86
|
# Returns a string, used by Resque::Plugins::UniqueAtRuntime, that will be used as the redis key
|
@@ -2,8 +2,10 @@ module Resque
|
|
2
2
|
module UniqueByArity
|
3
3
|
module Validation
|
4
4
|
def self.included(base)
|
5
|
-
|
6
|
-
|
5
|
+
unless base.uniq_config.skip_arity_validation?
|
6
|
+
um = base.method(:perform)
|
7
|
+
base.uniq_config.validate_arity(base.to_s, um)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -25,7 +25,7 @@ require "resque/unique_by_arity/validation"
|
|
25
25
|
module Resque
|
26
26
|
module UniqueByArity
|
27
27
|
def unique_log(message, config_proxy = nil)
|
28
|
-
config_proxy ||=
|
28
|
+
config_proxy ||= uniqueness_configuration
|
29
29
|
config_proxy.unique_logger.send(config_proxy.unique_log_level, message) if config_proxy.unique_logger
|
30
30
|
end
|
31
31
|
|
@@ -72,6 +72,12 @@ module Resque
|
|
72
72
|
def uniqueness_lock_after_execution_period=(lock_after_execution_period)
|
73
73
|
@uniqueness_configuration.lock_after_execution_period = lock_after_execution_period
|
74
74
|
end
|
75
|
+
def uniqueness_runtime_lock_timeout
|
76
|
+
@uniqueness_configuration.runtime_lock_timeout
|
77
|
+
end
|
78
|
+
def uniqueness_runtime_lock_timeout=(runtime_lock_timeout)
|
79
|
+
@uniqueness_configuration.runtime_lock_timeout = runtime_lock_timeout
|
80
|
+
end
|
75
81
|
def uniqueness_unique_at_runtime
|
76
82
|
@uniqueness_configuration.unique_at_runtime
|
77
83
|
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.9
|
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-
|
11
|
+
date: 2017-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: resque-unique_at_runtime
|