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