resque-loner 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +92 -0
- data/.simplecov +1 -0
- data/.travis.yml +12 -0
- data/CHANGELOG.markdown +11 -0
- data/Gemfile +4 -5
- data/README.markdown +4 -1
- data/Rakefile +13 -41
- data/lib/resque-ext/job.rb +9 -9
- data/lib/resque-ext/resque.rb +4 -9
- data/lib/resque-loner.rb +2 -1
- data/lib/resque-loner/helpers.rb +22 -9
- data/lib/resque-loner/legacy_helpers.rb +91 -0
- data/lib/resque-loner/unique_job.rb +23 -14
- data/lib/resque-loner/version.rb +1 -1
- data/resque-loner.gemspec +41 -32
- data/spec/loner_spec.rb +73 -51
- data/spec/spec_helper.rb +19 -3
- data/spec/support/redis_instance.rb +133 -0
- data/test/airbrake_test.rb +27 -0
- data/test/dump.rdb +0 -0
- data/test/job_hooks_test.rb +191 -52
- data/test/job_plugins_test.rb +33 -31
- data/test/plugin_test.rb +38 -26
- data/{spec/redis-test.conf → test/redis-test-cluster.conf} +4 -4
- data/test/resque-web_test.rb +23 -17
- data/test/resque_failure_redis_test.rb +23 -0
- data/test/resque_test.rb +56 -37
- data/test/test_helper.rb +58 -29
- data/test/worker_test.rb +311 -55
- metadata +157 -58
- data/init.rb +0 -1
- data/rails/init.rb +0 -1
- data/test/hoptoad_test.rb +0 -25
@@ -0,0 +1,91 @@
|
|
1
|
+
# This is an old helpers module pulled in from Resque 1.25.1
|
2
|
+
# which will be deprecated in future Resque versions. Bringing in
|
3
|
+
# this module allows us to get rid of the deprecation message
|
4
|
+
# (Resque::Helpers will be gone with no replacement in Resque 2.0.0.)
|
5
|
+
require 'multi_json'
|
6
|
+
|
7
|
+
# OkJson won't work because it doesn't serialize symbols
|
8
|
+
# in the same way yajl and json do.
|
9
|
+
if MultiJson.engine.to_s == 'MultiJson::Engines::OkJson'
|
10
|
+
fail 'Please install the yajl-ruby or json gem'
|
11
|
+
end
|
12
|
+
|
13
|
+
module Resque
|
14
|
+
module Plugins
|
15
|
+
module Loner
|
16
|
+
# Methods used by various classes in Resque.
|
17
|
+
module LegacyHelpers
|
18
|
+
class DecodeException < StandardError; end
|
19
|
+
|
20
|
+
# Direct access to the Redis instance.
|
21
|
+
def redis
|
22
|
+
Resque.redis
|
23
|
+
end
|
24
|
+
|
25
|
+
# Given a Ruby object, returns a string suitable for storage in a
|
26
|
+
# queue.
|
27
|
+
def encode(object)
|
28
|
+
::MultiJson.encode(object)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Given a string, returns a Ruby object.
|
32
|
+
def decode(object)
|
33
|
+
return unless object
|
34
|
+
|
35
|
+
begin
|
36
|
+
::MultiJson.decode(object)
|
37
|
+
rescue ::MultiJson::DecodeError => e
|
38
|
+
raise DecodeException, e.message, e.backtrace
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Given a word with dashes, returns a camel cased version of it.
|
43
|
+
#
|
44
|
+
# classify('job-name') # => 'JobName'
|
45
|
+
def classify(dashed_word)
|
46
|
+
dashed_word.split('-').each { |part| part[0] = part[0].chr.upcase }.join
|
47
|
+
end
|
48
|
+
|
49
|
+
# Tries to find a constant with the name specified in the argument string:
|
50
|
+
#
|
51
|
+
# constantize("Module") # => Module
|
52
|
+
# constantize("Test::Unit") # => Test::Unit
|
53
|
+
#
|
54
|
+
# The name is assumed to be the one of a top-level constant, no matter
|
55
|
+
# whether it starts with "::" or not. No lexical context is taken into
|
56
|
+
# account:
|
57
|
+
#
|
58
|
+
# C = 'outside'
|
59
|
+
# module M
|
60
|
+
# C = 'inside'
|
61
|
+
# C # => 'inside'
|
62
|
+
# constantize("C") # => 'outside', same as ::C
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# NameError is raised when the constant is unknown.
|
66
|
+
def constantize(camel_cased_word)
|
67
|
+
camel_cased_word = camel_cased_word.to_s
|
68
|
+
|
69
|
+
if camel_cased_word.include?('-')
|
70
|
+
camel_cased_word = classify(camel_cased_word)
|
71
|
+
end
|
72
|
+
|
73
|
+
names = camel_cased_word.split('::')
|
74
|
+
names.shift if names.empty? || names.first.empty?
|
75
|
+
|
76
|
+
constant = Object
|
77
|
+
names.each do |name|
|
78
|
+
args = Module.method(:const_get).arity != 1 ? [false] : []
|
79
|
+
|
80
|
+
if constant.const_defined?(name, *args)
|
81
|
+
constant = constant.const_get(name)
|
82
|
+
else
|
83
|
+
constant = constant.const_missing(name)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
constant
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'digest/md5'
|
2
|
+
require 'resque-loner/helpers'
|
2
3
|
|
3
4
|
#
|
4
5
|
# If you want your job to be unique, include this module in it. If you wish,
|
@@ -7,37 +8,34 @@ require 'digest/md5'
|
|
7
8
|
module Resque
|
8
9
|
module Plugins
|
9
10
|
module UniqueJob
|
10
|
-
|
11
11
|
def self.included(base)
|
12
|
-
base.extend
|
12
|
+
base.extend ClassMethods
|
13
13
|
base.class_eval do
|
14
|
-
base.send(:extend, Resque::
|
14
|
+
base.send(:extend, Resque::Plugins::Loner::LegacyHelpers)
|
15
15
|
end
|
16
16
|
end # self.included
|
17
17
|
|
18
18
|
module ClassMethods
|
19
|
-
|
20
|
-
|
21
19
|
#
|
22
20
|
# Payload is what Resque stored for this job along with the job's class name.
|
23
21
|
# On a Resque with no plugins installed, this is a hash containing :class and :args
|
24
22
|
#
|
25
23
|
def redis_key(payload)
|
26
24
|
payload = decode(encode(payload)) # This is the cycle the data goes when being enqueued/dequeued
|
27
|
-
job = payload[:class] || payload[
|
28
|
-
args = (payload[:args] || payload[
|
25
|
+
job = payload[:class] || payload['class']
|
26
|
+
args = (payload[:args] || payload['args'])
|
29
27
|
args.map! do |arg|
|
30
28
|
arg.is_a?(Hash) ? arg.sort : arg
|
31
29
|
end
|
32
30
|
|
33
|
-
digest = Digest::MD5.hexdigest
|
31
|
+
digest = Digest::MD5.hexdigest(encode(class: job, args: args))
|
34
32
|
digest
|
35
33
|
end
|
36
34
|
|
37
35
|
#
|
38
36
|
# The default ttl of a locking key is -1, i.e. forever. If for some reason you only
|
39
|
-
# want the lock to be in place after a certain amount of time, just set a ttl
|
40
|
-
# for your job. For example:
|
37
|
+
# want the lock to be in place after a certain amount of time, just set a ttl (in
|
38
|
+
# seconds) for your job. For example:
|
41
39
|
#
|
42
40
|
# class FooJob
|
43
41
|
# include Resque::Plugins::UniqueJob
|
@@ -49,9 +47,21 @@ module Resque
|
|
49
47
|
@loner_ttl || -1
|
50
48
|
end
|
51
49
|
|
50
|
+
#
|
51
|
+
# The default ttl of a persisting key is 0, i.e. immediately deleted.
|
52
|
+
# You can set loner_lock_after_execution_period if you want to block the execution
|
53
|
+
# of the job for a certain amount of time (in seconds). For example:
|
54
|
+
#
|
55
|
+
# class FooJob
|
56
|
+
# include Resque::Plugins::UniqueJob
|
57
|
+
# @loner_lock_after_execution_period = 40
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
def loner_lock_after_execution_period
|
62
|
+
@loner_lock_after_execution_period || 0
|
63
|
+
end
|
52
64
|
end # ClassMethods
|
53
|
-
|
54
|
-
|
55
65
|
end
|
56
66
|
end
|
57
67
|
end
|
@@ -60,13 +70,12 @@ module Resque
|
|
60
70
|
module Plugins
|
61
71
|
module Loner
|
62
72
|
class UniqueJob
|
63
|
-
|
64
73
|
include Resque::Plugins::UniqueJob
|
65
74
|
|
66
75
|
def self.inherited(host)
|
67
76
|
super(host)
|
68
77
|
return if @__unique_job_warned
|
69
|
-
warn
|
78
|
+
warn 'Inherit Resque::Plugins::Loner::UniqueJob is deprecated. Include Resque::Plugins::UniqueJob module instead.'
|
70
79
|
@__unique_job_warned = true
|
71
80
|
end
|
72
81
|
end
|
data/lib/resque-loner/version.rb
CHANGED
data/resque-loner.gemspec
CHANGED
@@ -5,46 +5,55 @@ $:.unshift lib unless $:.include?(lib)
|
|
5
5
|
require 'resque-loner/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
|
-
s.name
|
9
|
-
s.version
|
10
|
-
s.platform
|
11
|
-
s.authors
|
12
|
-
s.email
|
13
|
-
s.homepage
|
14
|
-
s.summary
|
15
|
-
s.has_rdoc
|
8
|
+
s.name = 'resque-loner'
|
9
|
+
s.version = Resque::Plugins::Loner::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ['Jannis Hermanns']
|
12
|
+
s.email = ['jannis@moviepilot.com']
|
13
|
+
s.homepage = 'http://github.com/jayniz/resque-loner'
|
14
|
+
s.summary = 'Adds unique jobs to resque'
|
15
|
+
s.has_rdoc = false
|
16
|
+
s.license = 'MIT'
|
16
17
|
|
17
18
|
s.rubyforge_project = 'resque-loner'
|
18
19
|
|
19
20
|
s.add_dependency 'resque', '~>1.0'
|
20
|
-
{
|
21
|
-
'rake' => '> 0.8.7',
|
22
|
-
'rack-test' => '~> 0.5.7',
|
23
|
-
'rspec' => '~> 2.5.0',
|
24
|
-
'mock_redis' => '~> 0.2.0',
|
25
|
-
'yajl-ruby' => '~> 0.8.2'
|
26
|
-
}.each do |lib, version|
|
27
|
-
s.add_development_dependency lib, version
|
28
|
-
end
|
29
21
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
22
|
+
%w(
|
23
|
+
airbrake
|
24
|
+
i18n
|
25
|
+
mocha
|
26
|
+
mock_redis
|
27
|
+
rack-test
|
28
|
+
rake
|
29
|
+
rspec
|
30
|
+
rubocop
|
31
|
+
simplecov
|
32
|
+
yajl-ruby
|
33
|
+
).each do |gemname|
|
34
|
+
s.add_development_dependency gemname
|
35
|
+
end
|
34
36
|
|
35
|
-
s.
|
36
|
-
|
37
|
+
s.executables = `git ls-files -z -- bin/*`.split("\0").map do
|
38
|
+
|f| File.basename(f)
|
39
|
+
end
|
40
|
+
s.files = `git ls-files -z`.split("\0")
|
41
|
+
s.test_files = `git ls-files -z -- {test,spec,features}/*`.split("\0")
|
42
|
+
s.require_paths = ['lib']
|
37
43
|
|
38
|
-
|
39
|
-
|
44
|
+
s.description = <<-EODESC.gsub(/^ {4}/, '')
|
45
|
+
Makes sure that for special jobs, there can be only one job with the same
|
46
|
+
workload in one queue.
|
40
47
|
|
41
|
-
|
48
|
+
Example:
|
49
|
+
class CacheSweeper
|
50
|
+
include Resque::Plugins::UniqueJob
|
42
51
|
|
43
|
-
|
52
|
+
@queue = :cache_sweeps
|
44
53
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
def self.perform(article_id)
|
55
|
+
# Cache Me If You Can...
|
56
|
+
end
|
57
|
+
end
|
58
|
+
EODESC
|
50
59
|
end
|
data/spec/loner_spec.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
3
|
#
|
5
4
|
# Resque-loner specific specs. I'm shooting right through the stack here and just
|
6
5
|
# test the outcomes, because the implementation will change soon and the tests run
|
@@ -11,10 +10,8 @@ class SomeJob
|
|
11
10
|
@queue = :some_queue
|
12
11
|
end
|
13
12
|
|
14
|
-
class SomeUniqueJob
|
15
|
-
|
13
|
+
class SomeUniqueJob
|
16
14
|
include Resque::Plugins::UniqueJob
|
17
|
-
|
18
15
|
@queue = :other_queue
|
19
16
|
def self.perform(foo); end
|
20
17
|
end
|
@@ -23,12 +20,11 @@ class FailingUniqueJob
|
|
23
20
|
include Resque::Plugins::UniqueJob
|
24
21
|
@queue = :other_queue
|
25
22
|
def self.perform(foo)
|
26
|
-
|
23
|
+
fail 'I beg to differ'
|
27
24
|
end
|
28
25
|
end
|
29
26
|
|
30
27
|
class DeprecatedUniqueJob < Resque::Plugins::Loner::UniqueJob
|
31
|
-
|
32
28
|
@queue = :other_queue
|
33
29
|
def self.perform(foo); end
|
34
30
|
end
|
@@ -37,11 +33,17 @@ class UniqueJobWithTtl
|
|
37
33
|
include Resque::Plugins::UniqueJob
|
38
34
|
@queue = :unique_with_ttl
|
39
35
|
@loner_ttl = 300
|
36
|
+
def self.perform(*args); end
|
37
|
+
end
|
40
38
|
|
39
|
+
class UniqueJobWithLockAfterExecution
|
40
|
+
include Resque::Plugins::UniqueJob
|
41
|
+
@queue = :unique_with_loner_lock_after_execution_period
|
42
|
+
@loner_lock_after_execution_period = 150
|
41
43
|
def self.perform(*args); end
|
42
44
|
end
|
43
45
|
|
44
|
-
describe
|
46
|
+
describe 'Resque' do
|
45
47
|
|
46
48
|
before(:each) do
|
47
49
|
Resque.redis.flushall
|
@@ -49,107 +51,107 @@ describe "Resque" do
|
|
49
51
|
Resque.size(:some_queue).should == 0
|
50
52
|
end
|
51
53
|
|
52
|
-
describe
|
53
|
-
it
|
54
|
-
Resque.enqueue SomeJob,
|
55
|
-
Resque.enqueue SomeJob,
|
54
|
+
describe 'Jobs' do
|
55
|
+
it 'can put multiple normal jobs on a queue' do
|
56
|
+
Resque.enqueue SomeJob, 'foo'
|
57
|
+
Resque.enqueue SomeJob, 'foo'
|
56
58
|
Resque.size(:some_queue).should == 2
|
57
59
|
end
|
58
60
|
|
59
|
-
it
|
60
|
-
Resque.enqueue SomeUniqueJob,
|
61
|
-
Resque.enqueue SomeUniqueJob,
|
61
|
+
it 'should allow only one of the same job to sit in a queue' do
|
62
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
63
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
62
64
|
Resque.size(:other_queue).should == 1
|
63
65
|
end
|
64
66
|
|
65
|
-
it
|
66
|
-
Resque.enqueue DeprecatedUniqueJob,
|
67
|
-
Resque.enqueue DeprecatedUniqueJob,
|
67
|
+
it 'should support deprecated Resque::Plugins::Loner::UniqueJob class' do
|
68
|
+
Resque.enqueue DeprecatedUniqueJob, 'foo'
|
69
|
+
Resque.enqueue DeprecatedUniqueJob, 'foo'
|
68
70
|
Resque.size(:other_queue).should == 1
|
69
71
|
end
|
70
72
|
|
71
|
-
it
|
72
|
-
Resque.enqueue SomeUniqueJob,
|
73
|
-
Resque.enqueue SomeUniqueJob,
|
73
|
+
it 'should allow the same jobs to be executed one after the other' do
|
74
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
75
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
74
76
|
Resque.size(:other_queue).should == 1
|
75
77
|
|
76
78
|
Resque.reserve(:other_queue)
|
77
79
|
Resque.size(:other_queue).should == 0
|
78
80
|
|
79
|
-
Resque.enqueue SomeUniqueJob,
|
80
|
-
Resque.enqueue SomeUniqueJob,
|
81
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
82
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
81
83
|
Resque.size(:other_queue).should == 1
|
82
84
|
end
|
83
85
|
|
84
|
-
it
|
85
|
-
Resque.enqueue SomeUniqueJob, :
|
86
|
-
Resque.enqueue SomeUniqueJob, :
|
86
|
+
it 'should be robust regarding hash attributes' do
|
87
|
+
Resque.enqueue SomeUniqueJob, bar: 1, foo: 2
|
88
|
+
Resque.enqueue SomeUniqueJob, foo: 2, bar: 1
|
87
89
|
Resque.size(:other_queue).should == 1
|
88
90
|
end
|
89
91
|
|
90
|
-
it
|
91
|
-
Resque.enqueue SomeUniqueJob, :
|
92
|
-
Resque.enqueue SomeUniqueJob, :bar => 1,
|
92
|
+
it 'should be robust regarding hash attributes (JSON does not distinguish between string and symbol)' do
|
93
|
+
Resque.enqueue SomeUniqueJob, bar: 1, foo: 1
|
94
|
+
Resque.enqueue SomeUniqueJob, :bar => 1, 'foo' => 1
|
93
95
|
Resque.size(:other_queue).should == 1
|
94
96
|
end
|
95
97
|
|
96
|
-
it
|
97
|
-
Resque.enqueue SomeUniqueJob,
|
98
|
-
Resque.enqueue SomeUniqueJob,
|
98
|
+
it 'should mark jobs as unqueued, when Job.destroy is killing them' do
|
99
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
100
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
99
101
|
Resque.size(:other_queue).should == 1
|
100
102
|
|
101
103
|
Resque::Job.destroy(:other_queue, SomeUniqueJob)
|
102
104
|
Resque.size(:other_queue).should == 0
|
103
105
|
|
104
|
-
Resque.enqueue SomeUniqueJob,
|
105
|
-
Resque.enqueue SomeUniqueJob,
|
106
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
107
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
106
108
|
Resque.size(:other_queue).should == 1
|
107
109
|
end
|
108
110
|
|
109
|
-
it
|
110
|
-
2.times { Resque.enqueue(
|
111
|
+
it 'should mark jobs as unqueued, when they raise an exception during #perform' do
|
112
|
+
2.times { Resque.enqueue(FailingUniqueJob, 'foo') }
|
111
113
|
Resque.size(:other_queue).should == 1
|
112
114
|
|
113
115
|
worker = Resque::Worker.new(:other_queue)
|
114
116
|
worker.work 0
|
115
117
|
Resque.size(:other_queue).should == 0
|
116
118
|
|
117
|
-
2.times { Resque.enqueue(
|
119
|
+
2.times { Resque.enqueue(FailingUniqueJob, 'foo') }
|
118
120
|
Resque.size(:other_queue).should == 1
|
119
121
|
end
|
120
122
|
|
121
|
-
it
|
122
|
-
Resque.enqueue SomeUniqueJob,
|
123
|
-
Resque.enqueued?(SomeUniqueJob,
|
124
|
-
Resque.enqueued?(SomeUniqueJob,
|
123
|
+
it 'should report if a job is queued or not' do
|
124
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
125
|
+
Resque.enqueued?(SomeUniqueJob, 'foo').should be_true
|
126
|
+
Resque.enqueued?(SomeUniqueJob, 'bar').should be_false
|
125
127
|
end
|
126
128
|
|
127
|
-
it
|
129
|
+
it 'should report if a job is in a special queue or not' do
|
128
130
|
default_queue = SomeUniqueJob.instance_variable_get(:@queue)
|
129
131
|
SomeUniqueJob.instance_variable_set(:@queue, :special_queue)
|
130
132
|
|
131
|
-
Resque.enqueue SomeUniqueJob,
|
132
|
-
Resque.enqueued_in?(
|
133
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
134
|
+
Resque.enqueued_in?(:special_queue, SomeUniqueJob, 'foo').should be_true
|
133
135
|
|
134
136
|
SomeUniqueJob.instance_variable_set(:@queue, default_queue)
|
135
137
|
|
136
|
-
Resque.enqueued?(
|
138
|
+
Resque.enqueued?(SomeUniqueJob, 'foo').should be_false
|
137
139
|
end
|
138
140
|
|
139
|
-
it
|
141
|
+
it 'should not be able to report if a non-unique job was enqueued' do
|
140
142
|
Resque.enqueued?(SomeJob).should be_nil
|
141
143
|
end
|
142
144
|
|
143
|
-
it
|
144
|
-
Resque.enqueue SomeUniqueJob,
|
145
|
-
Resque.enqueue FailingUniqueJob,
|
145
|
+
it 'should cleanup all loners when a queue is destroyed' do
|
146
|
+
Resque.enqueue SomeUniqueJob, 'foo'
|
147
|
+
Resque.enqueue FailingUniqueJob, 'foo'
|
146
148
|
|
147
149
|
Resque.remove_queue(:other_queue)
|
148
150
|
|
149
|
-
Resque.enqueue(SomeUniqueJob,
|
151
|
+
Resque.enqueue(SomeUniqueJob, 'foo')
|
150
152
|
Resque.size(:other_queue).should == 1
|
151
153
|
end
|
152
|
-
|
154
|
+
|
153
155
|
it 'should not raise an error when deleting an already empty queue' do
|
154
156
|
expect { Resque.remove_queue(:other_queue) }.to_not raise_error
|
155
157
|
end
|
@@ -157,9 +159,29 @@ describe "Resque" do
|
|
157
159
|
it 'should honor loner_ttl in the redis key' do
|
158
160
|
Resque.enqueue UniqueJobWithTtl
|
159
161
|
Resque.enqueued?(UniqueJobWithTtl).should be_true
|
160
|
-
k=Resque.redis.keys
|
162
|
+
k = Resque.redis.keys 'loners:queue:unique_with_ttl:job:*'
|
161
163
|
k.length.should == 1
|
162
164
|
Resque.redis.ttl(k[0]).should be_within(2).of(UniqueJobWithTtl.loner_ttl)
|
163
165
|
end
|
166
|
+
|
167
|
+
it 'should not allow the same job to be enqueued after execution if loner_lock_after_execution_period is set' do
|
168
|
+
Resque.enqueue UniqueJobWithLockAfterExecution, 'foo'
|
169
|
+
Resque.enqueue UniqueJobWithLockAfterExecution, 'foo'
|
170
|
+
Resque.size(:unique_with_loner_lock_after_execution_period).should == 1
|
171
|
+
|
172
|
+
Resque.reserve(:unique_with_loner_lock_after_execution_period)
|
173
|
+
Resque.size(:unique_with_loner_lock_after_execution_period).should == 0
|
174
|
+
|
175
|
+
Resque.enqueue UniqueJobWithLockAfterExecution, 'foo'
|
176
|
+
Resque.size(:unique_with_loner_lock_after_execution_period).should == 0
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'should honor loner_lock_after_execution_period in the redis key' do
|
180
|
+
Resque.enqueue UniqueJobWithLockAfterExecution
|
181
|
+
Resque.reserve(:unique_with_loner_lock_after_execution_period)
|
182
|
+
k = Resque.redis.keys 'loners:queue:unique_with_loner_lock_after_execution_period:job:*'
|
183
|
+
k.length.should == 1
|
184
|
+
Resque.redis.ttl(k[0]).should be_within(2).of(UniqueJobWithLockAfterExecution.loner_lock_after_execution_period)
|
185
|
+
end
|
164
186
|
end
|
165
187
|
end
|