resque-unique_at_runtime 2.0.4 → 3.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 +4 -4
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +75 -0
- data/Gemfile +10 -6
- data/README.md +17 -10
- data/Rakefile +6 -4
- data/lib/resque-unique_at_runtime.rb +58 -75
- data/lib/resque/plugins/unique_at_runtime.rb +111 -0
- data/lib/resque/unique_at_runtime/configuration.rb +47 -0
- data/lib/resque/unique_at_runtime/resque_ext/resque.rb +9 -0
- data/lib/resque/unique_at_runtime/version.rb +7 -0
- data/resque-unique_at_runtime.gemspec +52 -41
- metadata +118 -19
- data/lib/resque-unique_at_runtime/version.rb +0 -7
- data/spec/lib/unique_at_runtime_spec.rb +0 -180
- data/spec/spec_helper.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 645ac4f759c2b0721d782071985fdec3d14de968eeef88ae760c0a6e1deb0c67
|
4
|
+
data.tar.gz: f2a99e565e17ae87b290b8a834cfb9f6d5d9474fa7ae158eba361344f33c7850
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acbfec52b562d31dc543fa4de471700d485cc3654a0ab7813e07a68f029f7d6e43e953e3de849cca9f39f62359ea29b216b2dec3d0e9b3c8a1e9264c595ac777
|
7
|
+
data.tar.gz: 7941f8e4a0eabd5a222fd832b46f32f73b52b14ec4a94aa842ba948f26037cbc8b1d1c3e115dad91beba494aa40dd925aa26a8f598cb57e88227642ba337d68e
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2018-11-07 04:06:03 -0800 using RuboCop version 0.59.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_at_runtime.gemspec'
|
15
|
+
|
16
|
+
# Offense count: 1
|
17
|
+
Metrics/AbcSize:
|
18
|
+
Max: 17
|
19
|
+
|
20
|
+
# Offense count: 3
|
21
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
22
|
+
# ExcludedMethods: refine
|
23
|
+
Metrics/BlockLength:
|
24
|
+
Max: 102
|
25
|
+
|
26
|
+
# Offense count: 2
|
27
|
+
# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms.
|
28
|
+
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
|
29
|
+
Naming/FileName:
|
30
|
+
Exclude:
|
31
|
+
- 'lib/resque-unique_at_runtime.rb'
|
32
|
+
- 'resque-unique_at_runtime.gemspec'
|
33
|
+
|
34
|
+
# Offense count: 1
|
35
|
+
# Configuration parameters: EnforcedStyle.
|
36
|
+
# SupportedStyles: lowercase, uppercase
|
37
|
+
Naming/HeredocDelimiterCase:
|
38
|
+
Exclude:
|
39
|
+
- 'resque-unique_at_runtime.gemspec'
|
40
|
+
|
41
|
+
# Offense count: 1
|
42
|
+
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
43
|
+
# AllowedNames: io, id, to, by, on, in, at, ip, db
|
44
|
+
Naming/UncommunicativeMethodParamName:
|
45
|
+
Exclude:
|
46
|
+
- 'lib/resque/plugins/unique_at_runtime.rb'
|
47
|
+
|
48
|
+
# Offense count: 1
|
49
|
+
# Configuration parameters: AllowedChars.
|
50
|
+
Style/AsciiComments:
|
51
|
+
Exclude:
|
52
|
+
- 'lib/resque/plugins/unique_at_runtime.rb'
|
53
|
+
|
54
|
+
# Offense count: 4
|
55
|
+
Style/Documentation:
|
56
|
+
Exclude:
|
57
|
+
- 'spec/**/*'
|
58
|
+
- 'test/**/*'
|
59
|
+
- 'lib/resque-unique_at_runtime.rb'
|
60
|
+
- 'lib/resque/plugins/unique_at_runtime.rb'
|
61
|
+
- 'lib/resque/unique_at_runtime/configuration.rb'
|
62
|
+
- 'lib/resque/unique_at_runtime/resque_ext/resque.rb'
|
63
|
+
|
64
|
+
# Offense count: 1
|
65
|
+
# Cop supports --auto-correct.
|
66
|
+
# Configuration parameters: AllowAsExpressionSeparator.
|
67
|
+
Style/Semicolon:
|
68
|
+
Exclude:
|
69
|
+
- 'spec/lib/unique_at_runtime_spec.rb'
|
70
|
+
|
71
|
+
# Offense count: 26
|
72
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
73
|
+
# URISchemes: http, https
|
74
|
+
Metrics/LineLength:
|
75
|
+
Max: 120
|
data/Gemfile
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
6
|
|
5
7
|
group :test do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
unless ENV['TRAVIS']
|
9
|
+
gem 'byebug', '~> 10', platform: :mri, require: false
|
10
|
+
gem 'pry', '~> 0', platform: :mri, require: false
|
11
|
+
gem 'pry-byebug', '~> 3', platform: :mri, require: false
|
12
|
+
end
|
13
|
+
gem 'rubocop', '~> 0.60.0'
|
14
|
+
gem 'rubocop-rspec', '~> 1.30.0'
|
11
15
|
gem 'simplecov', '~> 0', require: false
|
12
16
|
end
|
13
17
|
|
14
|
-
# Specify your gem's dependencies in
|
18
|
+
# Specify your gem's dependencies in unique_at_runtime.gemspec
|
15
19
|
gemspec
|
data/README.md
CHANGED
@@ -63,7 +63,7 @@ Or install it yourself as:
|
|
63
63
|
require 'resque-unique_at_runtime'
|
64
64
|
|
65
65
|
class StrictlySerialJob
|
66
|
-
|
66
|
+
include Resque::Plugins::UniqueAtRuntime
|
67
67
|
|
68
68
|
@queue = :serial_work
|
69
69
|
|
@@ -82,7 +82,7 @@ method.
|
|
82
82
|
require 'resque-unique_at_runtime'
|
83
83
|
|
84
84
|
class StrictlySerialJob
|
85
|
-
|
85
|
+
include Resque::Plugins::UniqueAtRuntime
|
86
86
|
|
87
87
|
@queue = :serial_work
|
88
88
|
|
@@ -171,7 +171,7 @@ for its job (data x, data y, data z).
|
|
171
171
|
|
172
172
|
#### Example #4 -- Requeue interval
|
173
173
|
|
174
|
-
The behavior when multiple jobs exist in a queue protected by resque-unique_at_runtime
|
174
|
+
The behavior when multiple jobs exist in a queue protected by `resque-unique_at_runtime`
|
175
175
|
is for one job to be worked, while the other is continuously dequeued and
|
176
176
|
requeued until the first job is finished. This can result in that worker
|
177
177
|
process pegging a CPU/core on a worker server. To guard against this, the
|
@@ -185,7 +185,7 @@ in your job like so:
|
|
185
185
|
require 'resque-unique_at_runtime'
|
186
186
|
|
187
187
|
class StrictlySerialJob
|
188
|
-
|
188
|
+
include Resque::Plugins::UniqueAtRuntime
|
189
189
|
|
190
190
|
@queue = :serial_work
|
191
191
|
@runtime_requeue_interval = 5 # sleep for 5 seconds before requeueing
|
@@ -195,18 +195,26 @@ in your job like so:
|
|
195
195
|
end
|
196
196
|
end
|
197
197
|
|
198
|
+
#### Example #5 -- Check if a job is running
|
199
|
+
|
200
|
+
`resque-unique_at_runtime` extends `Resque` with a new method `running?`.
|
201
|
+
|
202
|
+
It can tell you if a job with a specific signature is running, based on the
|
203
|
+
presence of the runtime uniqueness key.
|
204
|
+
|
205
|
+
Caveat: It can be difficult to get the signature right, especially if you have
|
206
|
+
tools that enhance job signatures with options.
|
207
|
+
|
198
208
|
## Contributing
|
199
209
|
|
210
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pboling/resque-unique_at_runtime. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
211
|
+
|
200
212
|
1. Fork it
|
201
213
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
202
214
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
203
215
|
4. Push to the branch (`git push origin my-new-feature`)
|
204
216
|
5. Create new Pull Request
|
205
217
|
|
206
|
-
## Contributing
|
207
|
-
|
208
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/pboling/resque-unique_at_runtime. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
209
|
-
|
210
218
|
## Code of Conduct
|
211
219
|
|
212
220
|
Everyone interacting in the Resque::Plugins::UniqueAtRuntime project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/pboling/resque-unique_at_runtime/blob/master/CODE_OF_CONDUCT.md).
|
@@ -226,10 +234,9 @@ dependency on this gem using the [Pessimistic Version Constraint][pvc] with two
|
|
226
234
|
For example:
|
227
235
|
|
228
236
|
```ruby
|
229
|
-
spec.add_dependency 'resque-unique_at_runtime', '~>
|
237
|
+
spec.add_dependency 'resque-unique_at_runtime', '~> 1.0'
|
230
238
|
```
|
231
239
|
|
232
|
-
|
233
240
|
## License
|
234
241
|
|
235
242
|
* Copyright (c) 2012 Jonathan R. Wallace
|
data/Rakefile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
|
3
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/gem_tasks'
|
5
|
+
require 'rspec/core/rake_task'
|
4
6
|
|
5
7
|
RSpec::Core::RakeTask.new
|
6
8
|
|
7
|
-
task :
|
8
|
-
task :
|
9
|
+
task default: :spec
|
10
|
+
task test: :spec
|
@@ -1,91 +1,74 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
module Plugins
|
5
|
-
module UniqueAtRuntime
|
6
|
-
LOCK_TIMEOUT = 60 * 60 * 24 * 5
|
7
|
-
REQUEUE_INTERVAL = 1
|
8
|
-
|
9
|
-
def runtime_lock_timeout_at(now)
|
10
|
-
now + runtime_lock_timeout + 1
|
11
|
-
end
|
3
|
+
require 'resque/unique_at_runtime/version'
|
12
4
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
5
|
+
# Ruby Std Lib
|
6
|
+
require 'digest/md5'
|
16
7
|
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
# External Gems
|
9
|
+
require 'colorized_string'
|
10
|
+
require 'resque'
|
20
11
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
"resque-unique_at_runtime:#{@queue}"
|
26
|
-
end
|
12
|
+
# This Gem
|
13
|
+
require 'resque/plugins/unique_at_runtime'
|
14
|
+
require 'resque/unique_at_runtime/resque_ext/resque'
|
15
|
+
require 'resque/unique_at_runtime/configuration'
|
27
16
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
17
|
+
# See lib/resque/plugins/unique_at_runtime.rb for the actual plugin
|
18
|
+
#
|
19
|
+
# This is not that ^. Rather, it is an API used by the plugin or as tools by a
|
20
|
+
# developer. These methods are not intended to be included/extended into
|
21
|
+
# Resque, Resque::Job, or Resque::Queue.
|
22
|
+
module Resque
|
23
|
+
module UniqueAtRuntime
|
24
|
+
PLUGIN_TAG = (ColorizedString['[R-UAR] '].blue).freeze
|
36
25
|
|
37
|
-
|
26
|
+
def runtime_unique_log(message, config_proxy = nil)
|
27
|
+
config_proxy ||= uniqueness_configuration
|
28
|
+
config_proxy.unique_logger&.send(config_proxy.unique_log_level, message)
|
29
|
+
end
|
38
30
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
return key
|
44
|
-
end
|
31
|
+
def runtime_unique_debug(message, config_proxy = nil)
|
32
|
+
config_proxy ||= uniqueness_configuration
|
33
|
+
config_proxy.unique_logger&.debug("#{PLUGIN_TAG}#{message}") if config_proxy.debug_mode
|
34
|
+
end
|
45
35
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
36
|
+
# There are times when the class will need access to the configuration object,
|
37
|
+
# such as to override it per instance method
|
38
|
+
def uniq_config
|
39
|
+
@uniqueness_configuration
|
40
|
+
end
|
51
41
|
|
52
|
-
|
53
|
-
|
54
|
-
|
42
|
+
# For per-class config with a block
|
43
|
+
def uniqueness_configure
|
44
|
+
@uniqueness_configuration ||= Configuration.new
|
45
|
+
yield(@uniqueness_configuration)
|
46
|
+
end
|
55
47
|
|
56
|
-
|
57
|
-
|
58
|
-
|
48
|
+
#### CONFIG ####
|
49
|
+
class << self
|
50
|
+
attr_accessor :uniqueness_configuration
|
51
|
+
end
|
52
|
+
def uniqueness_config_reset(config = Configuration.new)
|
53
|
+
@uniqueness_configuration = config
|
54
|
+
end
|
59
55
|
|
60
|
-
|
61
|
-
|
56
|
+
def uniqueness_log_level
|
57
|
+
@uniqueness_configuration.log_level
|
58
|
+
end
|
62
59
|
|
63
|
-
|
64
|
-
|
60
|
+
def uniqueness_log_level=(log_level)
|
61
|
+
@uniqueness_configuration.log_level = log_level
|
62
|
+
end
|
65
63
|
|
66
|
-
|
67
|
-
raise Resque::Job::DontPerform
|
68
|
-
else
|
69
|
-
puts "will perform"
|
70
|
-
true
|
71
|
-
end
|
72
|
-
end
|
64
|
+
self.uniqueness_configuration = Configuration.new # setup defaults
|
73
65
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
# There may be scenarios where the around_perform's ensure unlock
|
83
|
-
# duplicates the on_failure unlock, but that's a small price to pay for
|
84
|
-
# uniqueness.
|
85
|
-
def on_failure_unlock_runtime(*args)
|
86
|
-
puts "resque-unique_at_runtime: on failure unlock" if ENV['RESQUE_DEBUG']
|
87
|
-
unlock_queue(*args)
|
88
|
-
end
|
89
|
-
end
|
66
|
+
module_function(:runtime_unique_log,
|
67
|
+
:runtime_unique_debug,
|
68
|
+
:uniq_config,
|
69
|
+
:uniqueness_configure,
|
70
|
+
:uniqueness_config_reset,
|
71
|
+
:uniqueness_log_level,
|
72
|
+
:uniqueness_log_level=)
|
90
73
|
end
|
91
74
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Resque
|
4
|
+
module Plugins
|
5
|
+
# If you want your job to support uniqueness at runtime, simply include
|
6
|
+
# this module into your job class.
|
7
|
+
#
|
8
|
+
# class RunAlone
|
9
|
+
# @queue = :run_alone
|
10
|
+
# include Resque::Plugins::UniqueAtRuntime
|
11
|
+
#
|
12
|
+
# def self.perform(arg1, arg2)
|
13
|
+
# alone_stuff
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
module UniqueAtRuntime
|
18
|
+
def self.included(base)
|
19
|
+
base.extend ClassMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
def runtime_lock_timeout_at(now)
|
24
|
+
now + runtime_lock_timeout + 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def runtime_lock_timeout
|
28
|
+
instance_variable_get(:@runtime_lock_timeout) || Resque::UniqueAtRuntime.uniq_config&.lock_timeout
|
29
|
+
end
|
30
|
+
|
31
|
+
def runtime_requeue_interval
|
32
|
+
instance_variable_get(:@runtime_requeue_interval) || Resque::UniqueAtRuntime.uniq_config&.requeue_interval
|
33
|
+
end
|
34
|
+
|
35
|
+
# Overwrite this method to uniquely identify which mutex should be used
|
36
|
+
# for a resque worker.
|
37
|
+
def unique_at_runtime_redis_key(*_)
|
38
|
+
Resque::UniqueAtRuntime.runtime_unique_debug("getting key for #{@queue}!")
|
39
|
+
"#{unique_at_runtime_key_base}:#{@queue}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns true if the job signature can be locked (is not currently locked)
|
43
|
+
def can_lock_queue?(*args)
|
44
|
+
!queue_locked?(*args)
|
45
|
+
end
|
46
|
+
|
47
|
+
# returns the locking key if locked, otherwise false
|
48
|
+
def queue_locked?(*args)
|
49
|
+
now = Time.now.to_i
|
50
|
+
key = unique_at_runtime_redis_key(*args)
|
51
|
+
timeout = runtime_lock_timeout_at(now)
|
52
|
+
|
53
|
+
Resque::UniqueAtRuntime.runtime_unique_debug("attempting to lock queue with #{key}")
|
54
|
+
|
55
|
+
# Per http://redis.io/commands/setnx
|
56
|
+
return false if Resque.redis.setnx(key, timeout)
|
57
|
+
return key if Resque.redis.get(key).to_i > now
|
58
|
+
return false if Resque.redis.getset(key, timeout).to_i <= now
|
59
|
+
|
60
|
+
key
|
61
|
+
end
|
62
|
+
|
63
|
+
def unlock_queue(*args)
|
64
|
+
key = unique_at_runtime_redis_key(*args)
|
65
|
+
Resque::UniqueAtRuntime.runtime_unique_debug("unlock queue with #{key}")
|
66
|
+
Resque.redis.del(key)
|
67
|
+
end
|
68
|
+
|
69
|
+
def reenqueue(*args)
|
70
|
+
Resque.enqueue(self, *args)
|
71
|
+
end
|
72
|
+
|
73
|
+
def before_perform_lock_runtime(*args)
|
74
|
+
if (key = queue_locked?(*args))
|
75
|
+
Resque::UniqueAtRuntime.runtime_unique_debug("failed to lock queue with #{key}")
|
76
|
+
|
77
|
+
# Sleep so the CPU's rest
|
78
|
+
sleep(runtime_requeue_interval)
|
79
|
+
|
80
|
+
# can't get the lock, so re-enqueue the task
|
81
|
+
reenqueue(*args)
|
82
|
+
|
83
|
+
# and don't perform
|
84
|
+
raise Resque::Job::DontPerform
|
85
|
+
else
|
86
|
+
Resque::UniqueAtRuntime.runtime_unique_debug('check passed will perform')
|
87
|
+
true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def around_perform_unlock_runtime(*args)
|
92
|
+
yield
|
93
|
+
ensure
|
94
|
+
unlock_queue(*args)
|
95
|
+
end
|
96
|
+
|
97
|
+
# There may be scenarios where the around_perform's ensure unlock±
|
98
|
+
# duplicates the on_failure unlock, but that's a small price to pay for
|
99
|
+
# uniqueness.
|
100
|
+
def on_failure_unlock_runtime(*args)
|
101
|
+
Resque::UniqueAtRuntime.runtime_unique_debug('on failure unlock')
|
102
|
+
unlock_queue(*args)
|
103
|
+
end
|
104
|
+
|
105
|
+
def unique_at_runtime_key_base
|
106
|
+
instance_variable_get(:@unique_at_runtime_key_base) || Resque::UniqueAtRuntime.uniq_config&.unique_at_runtime_key_base
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
module Resque
|
5
|
+
module UniqueAtRuntime
|
6
|
+
class Configuration
|
7
|
+
DEFAULT_AT_RUNTIME_KEY_BASE = 'r-uae'
|
8
|
+
DEFAULT_LOCK_TIMEOUT = 60 * 60 * 24 * 5
|
9
|
+
DEFAULT_REQUEUE_INTERVAL = 1
|
10
|
+
|
11
|
+
attr_accessor :logger,
|
12
|
+
:log_level,
|
13
|
+
:unique_at_runtime_key_base,
|
14
|
+
:lock_timeout,
|
15
|
+
:requeue_interval,
|
16
|
+
:debug_mode
|
17
|
+
def initialize(**options)
|
18
|
+
@logger = options.key?(:logger) ? options[:logger] : Logger.new(STDOUT)
|
19
|
+
@log_level = options.key?(:log_level) ? options[:log_level] : :debug
|
20
|
+
@unique_at_runtime_key_base = options.key?(:unique_at_runtime_key_base) ? options[:unique_at_runtime_key_base] : DEFAULT_AT_RUNTIME_KEY_BASE
|
21
|
+
@lock_timeout = options.key?(:lock_timeout) ? options[:lock_timeout] : DEFAULT_LOCK_TIMEOUT
|
22
|
+
@requeue_interval = options.key?(:requeue_interval) ? options[:requeue_interval] : DEFAULT_REQUEUE_INTERVAL
|
23
|
+
env_debug = ENV['RESQUE_DEBUG']
|
24
|
+
@debug_mode = options.key?(:debug_mode) ? options[:debug_mode] : env_debug == 'true' || (env_debug.is_a?(String) && env_debug.match?(/runtime/))
|
25
|
+
end
|
26
|
+
|
27
|
+
def unique_logger
|
28
|
+
logger
|
29
|
+
end
|
30
|
+
|
31
|
+
def unique_log_level
|
32
|
+
log_level
|
33
|
+
end
|
34
|
+
|
35
|
+
def log(msg)
|
36
|
+
Resque::UniqueAtRuntime.runtime_unique_log(msg, self)
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_hash
|
40
|
+
{
|
41
|
+
logger: logger,
|
42
|
+
log_level: log_level
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,43 +1,54 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
gem.add_dependency 'resque', '>= 1.2'
|
20
|
-
gem.add_development_dependency 'mock_redis'
|
21
|
-
gem.add_development_dependency 'rake'
|
22
|
-
gem.add_development_dependency 'rspec', '>= 3.0'
|
23
|
-
gem.add_development_dependency 'timecop'
|
24
|
-
|
25
|
-
gem.description = <<desc
|
26
|
-
Ensures that for a given queue, only one worker is working on a job at any given time.
|
27
|
-
|
28
|
-
Example:
|
29
|
-
|
30
|
-
require 'resque/plugins/unique_at_runtime'
|
31
|
-
|
32
|
-
class StrictlySerialJob
|
33
|
-
extend Resque::Plugins::UniqueAtRuntime
|
34
|
-
|
35
|
-
@queue = :serial_work
|
36
|
-
|
37
|
-
def self.perform
|
38
|
-
# only one at a time in this block, no parallelism allowed for this
|
39
|
-
# particular queue
|
40
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('lib/resque/unique_at_runtime/version', __dir__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'resque-unique_at_runtime'
|
7
|
+
spec.version = Resque::UniqueAtRuntime::VERSION
|
8
|
+
spec.authors = ['Peter H. Boling', 'Jonathan R. Wallace']
|
9
|
+
spec.email = ['peter.boling@gmail.com', 'jonathan.wallace@gmail.com']
|
10
|
+
spec.license = 'MIT'
|
11
|
+
|
12
|
+
spec.summary = 'A resque plugin that ensures job uniqueness at runtime.'
|
13
|
+
spec.homepage = 'http://github.com/pboling/resque-unique_at_runtime'
|
14
|
+
spec.required_ruby_version = '>= 2.3'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
41
18
|
end
|
42
|
-
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_runtime_dependency 'colorize', '~> 0.8'
|
22
|
+
spec.add_runtime_dependency 'resque', '>= 1.2'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'fakeredis', '~> 0.7'
|
25
|
+
spec.add_development_dependency 'rake', '~> 12.3'
|
26
|
+
spec.add_development_dependency 'rspec', '>= 3.0'
|
27
|
+
spec.add_development_dependency 'rspec-block_is_expected', '~> 1.0'
|
28
|
+
spec.add_development_dependency 'rspec-stubbed_env', '~> 1.0'
|
29
|
+
spec.add_development_dependency 'timecop'
|
30
|
+
|
31
|
+
spec.add_development_dependency 'pry', '~> 0.11'
|
32
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.6'
|
33
|
+
spec.add_development_dependency 'rubocop', '~> 0.60'
|
34
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 1.30'
|
35
|
+
|
36
|
+
spec.description = <<~desc
|
37
|
+
Ensures that for a given queue, only one worker is working on a job at any given time.
|
38
|
+
|
39
|
+
Example:
|
40
|
+
|
41
|
+
require 'resque/plugins/unique_at_runtime'
|
42
|
+
|
43
|
+
class StrictlySerialJob
|
44
|
+
include Resque::Plugins::UniqueAtRuntime
|
45
|
+
|
46
|
+
@queue = :serial_work
|
47
|
+
|
48
|
+
def self.perform
|
49
|
+
# only one at a time in this block, no parallelism allowed for this
|
50
|
+
# particular queue
|
51
|
+
end
|
52
|
+
end
|
53
|
+
desc
|
43
54
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: resque-unique_at_runtime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter H. Boling
|
@@ -9,8 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-
|
12
|
+
date: 2018-11-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: colorize
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.8'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0.8'
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: resque
|
16
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -26,33 +40,33 @@ dependencies:
|
|
26
40
|
- !ruby/object:Gem::Version
|
27
41
|
version: '1.2'
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
43
|
+
name: fakeredis
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
31
45
|
requirements:
|
32
|
-
- - "
|
46
|
+
- - "~>"
|
33
47
|
- !ruby/object:Gem::Version
|
34
|
-
version: '0'
|
48
|
+
version: '0.7'
|
35
49
|
type: :development
|
36
50
|
prerelease: false
|
37
51
|
version_requirements: !ruby/object:Gem::Requirement
|
38
52
|
requirements:
|
39
|
-
- - "
|
53
|
+
- - "~>"
|
40
54
|
- !ruby/object:Gem::Version
|
41
|
-
version: '0'
|
55
|
+
version: '0.7'
|
42
56
|
- !ruby/object:Gem::Dependency
|
43
57
|
name: rake
|
44
58
|
requirement: !ruby/object:Gem::Requirement
|
45
59
|
requirements:
|
46
|
-
- - "
|
60
|
+
- - "~>"
|
47
61
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
62
|
+
version: '12.3'
|
49
63
|
type: :development
|
50
64
|
prerelease: false
|
51
65
|
version_requirements: !ruby/object:Gem::Requirement
|
52
66
|
requirements:
|
53
|
-
- - "
|
67
|
+
- - "~>"
|
54
68
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
69
|
+
version: '12.3'
|
56
70
|
- !ruby/object:Gem::Dependency
|
57
71
|
name: rspec
|
58
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,6 +81,34 @@ dependencies:
|
|
67
81
|
- - ">="
|
68
82
|
- !ruby/object:Gem::Version
|
69
83
|
version: '3.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec-block_is_expected
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '1.0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: rspec-stubbed_env
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '1.0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '1.0'
|
70
112
|
- !ruby/object:Gem::Dependency
|
71
113
|
name: timecop
|
72
114
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,6 +123,62 @@ dependencies:
|
|
81
123
|
- - ">="
|
82
124
|
- !ruby/object:Gem::Version
|
83
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: pry
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0.11'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0.11'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: pry-byebug
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - "~>"
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '3.6'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '3.6'
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: rubocop
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0.60'
|
161
|
+
type: :development
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - "~>"
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0.60'
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: rubocop-rspec
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - "~>"
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '1.30'
|
175
|
+
type: :development
|
176
|
+
prerelease: false
|
177
|
+
version_requirements: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - "~>"
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '1.30'
|
84
182
|
description: |
|
85
183
|
Ensures that for a given queue, only one worker is working on a job at any given time.
|
86
184
|
|
@@ -89,7 +187,7 @@ description: |
|
|
89
187
|
require 'resque/plugins/unique_at_runtime'
|
90
188
|
|
91
189
|
class StrictlySerialJob
|
92
|
-
|
190
|
+
include Resque::Plugins::UniqueAtRuntime
|
93
191
|
|
94
192
|
@queue = :serial_work
|
95
193
|
|
@@ -106,6 +204,8 @@ extensions: []
|
|
106
204
|
extra_rdoc_files: []
|
107
205
|
files:
|
108
206
|
- ".gitignore"
|
207
|
+
- ".rubocop.yml"
|
208
|
+
- ".rubocop_todo.yml"
|
109
209
|
- ".ruby-version"
|
110
210
|
- ".travis.yml"
|
111
211
|
- CODE_OF_CONDUCT.md
|
@@ -114,10 +214,11 @@ files:
|
|
114
214
|
- README.md
|
115
215
|
- Rakefile
|
116
216
|
- lib/resque-unique_at_runtime.rb
|
117
|
-
- lib/resque
|
217
|
+
- lib/resque/plugins/unique_at_runtime.rb
|
218
|
+
- lib/resque/unique_at_runtime/configuration.rb
|
219
|
+
- lib/resque/unique_at_runtime/resque_ext/resque.rb
|
220
|
+
- lib/resque/unique_at_runtime/version.rb
|
118
221
|
- resque-unique_at_runtime.gemspec
|
119
|
-
- spec/lib/unique_at_runtime_spec.rb
|
120
|
-
- spec/spec_helper.rb
|
121
222
|
homepage: http://github.com/pboling/resque-unique_at_runtime
|
122
223
|
licenses:
|
123
224
|
- MIT
|
@@ -130,7 +231,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
130
231
|
requirements:
|
131
232
|
- - ">="
|
132
233
|
- !ruby/object:Gem::Version
|
133
|
-
version:
|
234
|
+
version: '2.3'
|
134
235
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
236
|
requirements:
|
136
237
|
- - ">="
|
@@ -142,6 +243,4 @@ rubygems_version: 2.7.7
|
|
142
243
|
signing_key:
|
143
244
|
specification_version: 4
|
144
245
|
summary: A resque plugin that ensures job uniqueness at runtime.
|
145
|
-
test_files:
|
146
|
-
- spec/lib/unique_at_runtime_spec.rb
|
147
|
-
- spec/spec_helper.rb
|
246
|
+
test_files: []
|
@@ -1,180 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
class SerialJob
|
4
|
-
extend Resque::Plugins::UniqueAtRuntime
|
5
|
-
@queue = :serial_work
|
6
|
-
|
7
|
-
def self.perform(*args); end
|
8
|
-
end
|
9
|
-
|
10
|
-
class SerialJobWithCustomRedisKey
|
11
|
-
extend Resque::Plugins::UniqueAtRuntime
|
12
|
-
@queue = :serial_work
|
13
|
-
|
14
|
-
def self.unique_at_runtime_redis_key(account_id, *args)
|
15
|
-
"unique_at_runtime:#{@queue}:#{account_id}"
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.perform(account_id, *args); end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe Resque::Plugins::UniqueAtRuntime do
|
22
|
-
before do
|
23
|
-
Resque.redis.flushall
|
24
|
-
end
|
25
|
-
|
26
|
-
describe ".runtime_requeue_interval" do
|
27
|
-
it "should default to 5" do
|
28
|
-
expect(SerialJob.runtime_requeue_interval).to eql(1)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should be overridable with a class instance var" do
|
32
|
-
SerialJob.instance_variable_set(:@runtime_requeue_interval, 5)
|
33
|
-
expect(SerialJob.runtime_requeue_interval).to eql(5)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe ".can_lock_queue?" do
|
38
|
-
it 'can lock a queue' do
|
39
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(true)
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'cannot lock an already locked queue' do
|
43
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(true)
|
44
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(false)
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'cannot lock a queue with active lock' do
|
48
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(true)
|
49
|
-
Timecop.travel(Date.today + 1) do
|
50
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(false)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'can relock a queue with expired lock' do
|
55
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(true)
|
56
|
-
|
57
|
-
Timecop.travel(Date.today + 10) do
|
58
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(true)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'solves race condition with getset' do
|
63
|
-
expect(SerialJob.can_lock_queue?(:serial_work)).to eql(true)
|
64
|
-
|
65
|
-
Timecop.travel(Date.today + 10) do
|
66
|
-
threads = (1..10).to_a.map {
|
67
|
-
Thread.new {
|
68
|
-
Thread.current[:locked] = SerialJob.can_lock_queue?(:serial_work)
|
69
|
-
}
|
70
|
-
}
|
71
|
-
|
72
|
-
# Only one worker should acquire lock
|
73
|
-
locks = threads.map {|t| t.join; t[:locked] }
|
74
|
-
expect(locks.count(true)).to eql(1)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe ".perform" do
|
80
|
-
before do
|
81
|
-
SerialJob.instance_variable_set(:@runtime_requeue_interval, 0)
|
82
|
-
end
|
83
|
-
|
84
|
-
describe "using the default redis key" do
|
85
|
-
it 'should lock and unlock the queue' do
|
86
|
-
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJob', 'args' => %w[account_one job_one] })
|
87
|
-
|
88
|
-
# job is the first SerialJob to run so it can lock the queue and perform
|
89
|
-
expect(SerialJob).to receive(:queue_locked?).and_return(false)
|
90
|
-
|
91
|
-
# but it should also clean up after itself
|
92
|
-
expect(SerialJob).to receive(:unlock_queue)
|
93
|
-
|
94
|
-
job.perform
|
95
|
-
end
|
96
|
-
|
97
|
-
it 'should clean up lock even with catastrophic job failure' do
|
98
|
-
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJob', 'args' => %w[account_one job_one] })
|
99
|
-
|
100
|
-
# job is the first SerialJob to run so it can lock the queue and perform
|
101
|
-
expect(SerialJob).to receive(:queue_locked?).and_return(false)
|
102
|
-
|
103
|
-
# but we have a catastrophic job failure
|
104
|
-
expect(SerialJob).to receive(:perform).and_raise(Exception)
|
105
|
-
|
106
|
-
# and still it should clean up after itself
|
107
|
-
expect(SerialJob).to receive(:unlock_queue).at_least(1).times
|
108
|
-
|
109
|
-
# unfortunately, the job will be lost but resque doesn't guarantee jobs
|
110
|
-
# aren't lost
|
111
|
-
expect { job.perform }.to raise_error(Exception)
|
112
|
-
end
|
113
|
-
|
114
|
-
it 'should place self at the end of the queue if unable to acquire the lock' do
|
115
|
-
job1_payload = %w[account_one job_one]
|
116
|
-
job2_payload = %w[account_one job_two]
|
117
|
-
Resque::Job.create(:serial_work, 'SerialJob', job1_payload)
|
118
|
-
Resque::Job.create(:serial_work, 'SerialJob', job2_payload)
|
119
|
-
|
120
|
-
expect(SerialJob).to receive(:queue_locked?).and_return(true)
|
121
|
-
|
122
|
-
# perform returns false when DontPerform exception is raised in
|
123
|
-
# before_perform callback
|
124
|
-
job1 = Resque.reserve(:serial_work)
|
125
|
-
expect(job1.perform).to eql(false)
|
126
|
-
|
127
|
-
first_queue_element = Resque.reserve(:serial_work)
|
128
|
-
expect(first_queue_element.payload["args"]).to eql([job2_payload])
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
describe "with a custom unique_at_runtime_redis_key" do
|
133
|
-
it 'should lock and unlock the queue' do
|
134
|
-
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJobWithCustomRedisKey', 'args' => %w[account_one job_one] })
|
135
|
-
|
136
|
-
# job is the first SerialJobWithCustomRedisKey to run so it can lock the queue and perform
|
137
|
-
expect(SerialJobWithCustomRedisKey).to receive(:queue_locked?).and_return(false)
|
138
|
-
|
139
|
-
# but it should also clean up after itself
|
140
|
-
expect(SerialJobWithCustomRedisKey).to receive(:unlock_queue)
|
141
|
-
|
142
|
-
job.perform
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'should clean up lock even with catastrophic job failure' do
|
146
|
-
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJobWithCustomRedisKey', 'args' => %w[account_one job_one] })
|
147
|
-
|
148
|
-
# job is the first SerialJobWithCustomRedisKey to run so it can lock the queue and perform
|
149
|
-
expect(SerialJobWithCustomRedisKey).to receive(:queue_locked?).and_return(false)
|
150
|
-
|
151
|
-
# but we have a catastrophic job failure
|
152
|
-
expect(SerialJobWithCustomRedisKey).to receive(:perform).and_raise(Exception)
|
153
|
-
|
154
|
-
# and still it should clean up after itself
|
155
|
-
expect(SerialJobWithCustomRedisKey).to receive(:unlock_queue).at_least(1).times
|
156
|
-
|
157
|
-
# unfortunately, the job will be lost but resque doesn't guarantee jobs
|
158
|
-
# aren't lost
|
159
|
-
expect { job.perform }.to raise_error(Exception)
|
160
|
-
end
|
161
|
-
|
162
|
-
it 'should place self at the end of the queue if unable to acquire the lock' do
|
163
|
-
job1_payload = %w[account_one job_one]
|
164
|
-
job2_payload = %w[account_one job_two]
|
165
|
-
Resque::Job.create(:serial_work, 'SerialJobWithCustomRedisKey', job1_payload)
|
166
|
-
Resque::Job.create(:serial_work, 'SerialJobWithCustomRedisKey', job2_payload)
|
167
|
-
|
168
|
-
expect(SerialJobWithCustomRedisKey).to receive(:queue_locked?).and_return(true)
|
169
|
-
|
170
|
-
# perform returns false when DontPerform exception is raised in
|
171
|
-
# before_perform callback
|
172
|
-
job1 = Resque.reserve(:serial_work)
|
173
|
-
expect(job1.perform).to eql(false)
|
174
|
-
|
175
|
-
first_queue_element = Resque.reserve(:serial_work)
|
176
|
-
expect(first_queue_element.payload["args"]).to eql([job2_payload])
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'rspec'
|
2
|
-
|
3
|
-
require 'mock_redis'
|
4
|
-
require 'resque'
|
5
|
-
require 'timecop'
|
6
|
-
|
7
|
-
require 'byebug' if RbConfig::CONFIG['RUBY_INSTALL_NAME'] == 'ruby'
|
8
|
-
|
9
|
-
require 'simplecov'
|
10
|
-
SimpleCov.start
|
11
|
-
|
12
|
-
# This gem
|
13
|
-
require 'resque-unique_at_runtime'
|
14
|
-
|
15
|
-
RSpec.configure do |config|
|
16
|
-
config.before(:suite) do
|
17
|
-
Resque.redis = MockRedis.new
|
18
|
-
end
|
19
|
-
end
|