Permalink
Browse files

Provide a way to configure ttl on keys used for locking

  • Loading branch information...
1 parent 7b46a0a commit cb6412beeacbabc19f314ffbed188cba5ae89efe @unclebilly unclebilly committed Dec 12, 2011
Showing with 48 additions and 1 deletion.
  1. +13 −1 lib/resque-loner/helpers.rb
  2. +17 −0 lib/resque-loner/unique_job.rb
  3. +18 −0 spec/loner_spec.rb
View
14 lib/resque-loner/helpers.rb
@@ -11,7 +11,11 @@ def self.loner_queued?(queue, item)
def self.mark_loner_as_queued(queue, item)
return unless item_is_a_unique_job?(item)
- redis.set(unique_job_queue_key(queue, item), 1)
+ key = unique_job_queue_key(queue, item)
+ redis.set(key, 1)
+ unless(ttl=item_ttl(item)) == -1 # no need to incur overhead for default value
+ redis.expire(key, ttl)
+ end
end
def self.mark_loner_as_unqueued(queue, job)
@@ -34,6 +38,14 @@ def self.item_is_a_unique_job?(item)
end # so resque-loner should not start throwing up when that happens.
end
+ def self.item_ttl(item)
+ begin
+ constantize(item[:class] || item["class"]).loner_ttl
+ rescue
+ -1
+ end
+ end
+
def self.job_destroy(queue, klass, *args)
klass = klass.to_s
redis_queue = "queue:#{queue}"
View
17 lib/resque-loner/unique_job.rb
@@ -33,6 +33,23 @@ def redis_key(payload)
digest = Digest::MD5.hexdigest encode(:class => job, :args => args)
digest
end
+
+ #
+ # The default ttl of a locking key is -1, i.e. forever. If for some reason you only
+ # want the lock to be in place after a certain amount of time, override this method
+ # in your job. For example:
+ #
+ # class FooJob
+ # include Resque::Plugins::UniqueJob
+ # def self.loner_ttl
+ # 40
+ # end
+ # end
+ #
+ def loner_ttl
+ -1
+ end
+
end # ClassMethods
View
18 spec/loner_spec.rb
@@ -33,6 +33,17 @@ class DeprecatedUniqueJob < Resque::Plugins::Loner::UniqueJob
def self.perform(foo); end
end
+class UniqueJobWithTtl
+ include Resque::Plugins::UniqueJob
+ @queue = :unique_with_ttl
+
+ def self.loner_ttl
+ 300
+ end
+
+ def self.perform(*args); end
+end
+
describe "Resque" do
before(:each) do
@@ -146,5 +157,12 @@ def self.perform(foo); end
expect { Resque.remove_queue(:other_queue) }.to_not raise_error
end
+ it 'should honor loner_ttl in the redis key' do
+ Resque.enqueue UniqueJobWithTtl
+ Resque.enqueued?(UniqueJobWithTtl).should be_true
+ k=Resque.redis.keys "loners:queue:unique_with_ttl:job:*"
+ k.length.should == 1
+ Resque.redis.ttl(k[0]).should be_within(2).of(UniqueJobWithTtl.loner_ttl)
+ end
end
end

0 comments on commit cb6412b

Please sign in to comment.