resque-unique_at_runtime 2.0.1 → 2.0.2
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/.travis.yml +3 -3
- data/README.md +2 -2
- data/lib/resque-unique_at_runtime/version.rb +1 -1
- data/lib/resque-unique_at_runtime.rb +40 -16
- data/spec/lib/unique_at_runtime_spec.rb +13 -13
- 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: 3d3d6b55df9f56bfc4706242b0d7f1f6e47fae6d
|
4
|
+
data.tar.gz: 816c4042916af3a170e6af35b1978f4f2a3cc338
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c61abb7166768391285d3a0478a23d0b63564c134969cd099fd69c05b5cdd2f156aaf529b8b859e91bd40627beb258abb2b4c4d81ba2cc9e678314df92c8cce2
|
7
|
+
data.tar.gz: d900c6c92ad2cf28f94872ae014044b821ec488b974e78428bfdcec3cfc81ed3c069d93211cdccf06d625b0e47242d7c45a332a326d6291b65a0ffdfbf6108d7
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -165,7 +165,7 @@ process pegging a CPU/core on a worker server. To guard against this, the
|
|
165
165
|
default behavior is to sleep for 1 second before the requeue, which will allow
|
166
166
|
the cpu to perform other work.
|
167
167
|
|
168
|
-
This can be customized using a ```@
|
168
|
+
This can be customized using a ```@runtime_requeue_interval``` class instance variable
|
169
169
|
in your job like so:
|
170
170
|
|
171
171
|
|
@@ -175,7 +175,7 @@ in your job like so:
|
|
175
175
|
extend Resque::Plugins::UniqueAtRuntime
|
176
176
|
|
177
177
|
@queue = :serial_work
|
178
|
-
@
|
178
|
+
@runtime_requeue_interval = 5 # sleep for 5 seconds before requeueing
|
179
179
|
|
180
180
|
def self.perform
|
181
181
|
# some implementation
|
@@ -3,62 +3,86 @@ require 'resque-unique_at_runtime/version'
|
|
3
3
|
module Resque
|
4
4
|
module Plugins
|
5
5
|
module UniqueAtRuntime
|
6
|
-
|
6
|
+
def runtime_lock_timeout_at(now)
|
7
|
+
now + runtime_lock_timeout + 1
|
8
|
+
end
|
7
9
|
|
8
|
-
def
|
9
|
-
|
10
|
+
def runtime_lock_timeout
|
11
|
+
self.instance_variable_get(:@runtime_lock_timeout) || 60 * 60 * 24 * 5
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
self.instance_variable_get(:@
|
14
|
+
def runtime_requeue_interval
|
15
|
+
self.instance_variable_get(:@runtime_requeue_interval) || 1
|
14
16
|
end
|
15
17
|
|
16
18
|
# Overwrite this method to uniquely identify which mutex should be used
|
17
19
|
# for a resque worker.
|
18
20
|
def unique_at_runtime_redis_key(*_)
|
19
|
-
"unique_at_runtime
|
21
|
+
puts "resque-unique_at_runtime: getting key for #{@queue}!" if ENV['RESQUE_DEBUG']
|
22
|
+
"resque-unique_at_runtime:#{@queue}"
|
20
23
|
end
|
21
24
|
|
22
25
|
def can_lock_queue?(*args)
|
26
|
+
queue_locked?(*args) == false ? true : false
|
27
|
+
end
|
28
|
+
|
29
|
+
def queue_locked?(*args)
|
23
30
|
now = Time.now.to_i
|
24
31
|
key = unique_at_runtime_redis_key(*args)
|
25
|
-
timeout =
|
32
|
+
timeout = runtime_lock_timeout_at(now)
|
33
|
+
|
34
|
+
puts "resque-unique_at_runtime: attempting to lock queue with #{key}" if ENV['RESQUE_DEBUG']
|
26
35
|
|
27
36
|
# Per http://redis.io/commands/setnx
|
28
|
-
return
|
29
|
-
return
|
30
|
-
return
|
31
|
-
return
|
37
|
+
return false if Resque.redis.setnx(key, timeout)
|
38
|
+
return key if Resque.redis.get(key).to_i > now
|
39
|
+
return false if Resque.redis.getset(key, timeout).to_i <= now
|
40
|
+
return key
|
32
41
|
end
|
33
42
|
|
34
43
|
def unlock_queue(*args)
|
35
|
-
|
44
|
+
key = unique_at_runtime_redis_key(*args)
|
45
|
+
puts "resque-unique_at_runtime: unlock queue with #{key}" if ENV['RESQUE_DEBUG']
|
46
|
+
Resque.redis.del(key)
|
36
47
|
end
|
37
48
|
|
38
49
|
def reenqueue(*args)
|
39
50
|
Resque.enqueue(self, *args)
|
40
51
|
end
|
41
52
|
|
42
|
-
def
|
43
|
-
|
53
|
+
def before_perform_lock_runtime(*args)
|
54
|
+
if (key = queue_locked?(*args))
|
55
|
+
puts "resque-unique_at_runtime: failed to lock queue with #{key}" if ENV['RESQUE_DEBUG']
|
56
|
+
|
44
57
|
# Sleep so the CPU's rest
|
45
|
-
sleep(
|
58
|
+
sleep(runtime_requeue_interval)
|
46
59
|
|
47
60
|
# can't get the lock, so re-enqueue the task
|
48
61
|
reenqueue(*args)
|
49
62
|
|
50
63
|
# and don't perform
|
51
64
|
raise Resque::Job::DontPerform
|
65
|
+
else
|
66
|
+
puts "will perform"
|
67
|
+
true
|
52
68
|
end
|
53
69
|
end
|
54
70
|
|
55
|
-
def
|
71
|
+
def around_perform_unlock_runtime(*args)
|
56
72
|
begin
|
57
73
|
yield
|
58
74
|
ensure
|
59
75
|
unlock_queue(*args)
|
60
76
|
end
|
61
77
|
end
|
78
|
+
|
79
|
+
# There may be scenarios where the around_perform's ensure unlock
|
80
|
+
# duplicates the on_failure unlock, but that's a small price to pay for
|
81
|
+
# uniqueness.
|
82
|
+
def on_failure_unlock_runtime(*args)
|
83
|
+
puts "resque-unique_at_runtime: on failure unlock" if ENV['RESQUE_DEBUG']
|
84
|
+
unlock_queue(*args)
|
85
|
+
end
|
62
86
|
end
|
63
87
|
end
|
64
88
|
end
|
@@ -23,14 +23,14 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
23
23
|
Resque.redis.flushall
|
24
24
|
end
|
25
25
|
|
26
|
-
describe ".
|
26
|
+
describe ".runtime_requeue_interval" do
|
27
27
|
it "should default to 5" do
|
28
|
-
expect(SerialJob.
|
28
|
+
expect(SerialJob.runtime_requeue_interval).to eql(1)
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should be overridable with a class instance var" do
|
32
|
-
SerialJob.instance_variable_set(:@
|
33
|
-
expect(SerialJob.
|
32
|
+
SerialJob.instance_variable_set(:@runtime_requeue_interval, 5)
|
33
|
+
expect(SerialJob.runtime_requeue_interval).to eql(5)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -78,7 +78,7 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
78
78
|
|
79
79
|
describe ".perform" do
|
80
80
|
before do
|
81
|
-
SerialJob.instance_variable_set(:@
|
81
|
+
SerialJob.instance_variable_set(:@runtime_requeue_interval, 0)
|
82
82
|
end
|
83
83
|
|
84
84
|
describe "using the default redis key" do
|
@@ -86,7 +86,7 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
86
86
|
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJob', 'args' => %w[account_one job_one] })
|
87
87
|
|
88
88
|
# job is the first SerialJob to run so it can lock the queue and perform
|
89
|
-
expect(SerialJob).to receive(:
|
89
|
+
expect(SerialJob).to receive(:queue_locked?).and_return(false)
|
90
90
|
|
91
91
|
# but it should also clean up after itself
|
92
92
|
expect(SerialJob).to receive(:unlock_queue)
|
@@ -98,13 +98,13 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
98
98
|
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJob', 'args' => %w[account_one job_one] })
|
99
99
|
|
100
100
|
# job is the first SerialJob to run so it can lock the queue and perform
|
101
|
-
expect(SerialJob).to receive(:
|
101
|
+
expect(SerialJob).to receive(:queue_locked?).and_return(false)
|
102
102
|
|
103
103
|
# but we have a catastrophic job failure
|
104
104
|
expect(SerialJob).to receive(:perform).and_raise(Exception)
|
105
105
|
|
106
106
|
# and still it should clean up after itself
|
107
|
-
expect(SerialJob).to receive(:unlock_queue)
|
107
|
+
expect(SerialJob).to receive(:unlock_queue).at_least(1).times
|
108
108
|
|
109
109
|
# unfortunately, the job will be lost but resque doesn't guarantee jobs
|
110
110
|
# aren't lost
|
@@ -117,7 +117,7 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
117
117
|
Resque::Job.create(:serial_work, 'SerialJob', job1_payload)
|
118
118
|
Resque::Job.create(:serial_work, 'SerialJob', job2_payload)
|
119
119
|
|
120
|
-
expect(SerialJob).to receive(:
|
120
|
+
expect(SerialJob).to receive(:queue_locked?).and_return(true)
|
121
121
|
|
122
122
|
# perform returns false when DontPerform exception is raised in
|
123
123
|
# before_perform callback
|
@@ -134,7 +134,7 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
134
134
|
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJobWithCustomRedisKey', 'args' => %w[account_one job_one] })
|
135
135
|
|
136
136
|
# job is the first SerialJobWithCustomRedisKey to run so it can lock the queue and perform
|
137
|
-
expect(SerialJobWithCustomRedisKey).to receive(:
|
137
|
+
expect(SerialJobWithCustomRedisKey).to receive(:queue_locked?).and_return(false)
|
138
138
|
|
139
139
|
# but it should also clean up after itself
|
140
140
|
expect(SerialJobWithCustomRedisKey).to receive(:unlock_queue)
|
@@ -146,13 +146,13 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
146
146
|
job = Resque::Job.new(:serial_work, { 'class' => 'SerialJobWithCustomRedisKey', 'args' => %w[account_one job_one] })
|
147
147
|
|
148
148
|
# job is the first SerialJobWithCustomRedisKey to run so it can lock the queue and perform
|
149
|
-
expect(SerialJobWithCustomRedisKey).to receive(:
|
149
|
+
expect(SerialJobWithCustomRedisKey).to receive(:queue_locked?).and_return(false)
|
150
150
|
|
151
151
|
# but we have a catastrophic job failure
|
152
152
|
expect(SerialJobWithCustomRedisKey).to receive(:perform).and_raise(Exception)
|
153
153
|
|
154
154
|
# and still it should clean up after itself
|
155
|
-
expect(SerialJobWithCustomRedisKey).to receive(:unlock_queue)
|
155
|
+
expect(SerialJobWithCustomRedisKey).to receive(:unlock_queue).at_least(1).times
|
156
156
|
|
157
157
|
# unfortunately, the job will be lost but resque doesn't guarantee jobs
|
158
158
|
# aren't lost
|
@@ -165,7 +165,7 @@ describe Resque::Plugins::UniqueAtRuntime do
|
|
165
165
|
Resque::Job.create(:serial_work, 'SerialJobWithCustomRedisKey', job1_payload)
|
166
166
|
Resque::Job.create(:serial_work, 'SerialJobWithCustomRedisKey', job2_payload)
|
167
167
|
|
168
|
-
expect(SerialJobWithCustomRedisKey).to receive(:
|
168
|
+
expect(SerialJobWithCustomRedisKey).to receive(:queue_locked?).and_return(true)
|
169
169
|
|
170
170
|
# perform returns false when DontPerform exception is raised in
|
171
171
|
# before_perform callback
|
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: 2.0.
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter H. Boling
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: resque
|