diff --git a/lib/redis/semaphore.rb b/lib/redis/semaphore.rb index 06e04b3..e340ea0 100644 --- a/lib/redis/semaphore.rb +++ b/lib/redis/semaphore.rb @@ -15,6 +15,7 @@ class Semaphore # Redis::Semaphore.new(:my_semaphore, :path => "bla") def initialize(name, opts = {}) @name = name + @expiration = opts.delete(:expiration) @resource_count = opts.delete(:resources) || 1 @stale_client_timeout = opts.delete(:stale_client_timeout) @redis = opts.delete(:redis) || Redis.new(opts) @@ -30,6 +31,7 @@ def exists_or_create! elsif token != API_VERSION raise "Semaphore exists but running as wrong version (version #{token} vs #{API_VERSION})." else + set_expiration true end end @@ -80,7 +82,7 @@ def locked?(token = nil) @tokens.each do |token| return true if locked?(token) end - + false end end @@ -150,10 +152,17 @@ def create! @resource_count.times do |index| @redis.rpush(available_key, index) end - # Persist key @redis.del(exists_key) @redis.set(exists_key, API_VERSION) + set_expiration + end + end + + def set_expiration + if @expiration + @redis.expire(available_key, @expiration) + @redis.expire(exists_key, @expiration) end end diff --git a/spec/semaphore_spec.rb b/spec/semaphore_spec.rb index 213cc4d..db61788 100644 --- a/spec/semaphore_spec.rb +++ b/spec/semaphore_spec.rb @@ -114,6 +114,20 @@ end end + describe "semaphore with expiration" do + let(:semaphore) { Redis::Semaphore.new(:my_semaphore, :redis => @redis, :expiration => 2) } + let(:multisem) { Redis::Semaphore.new(:my_semaphore_2, :resources => 2, :redis => @redis, :expiration => 2) } + + it_behaves_like "a semaphore" + + it "expires keys" do + original_key_size = @redis.keys.count + semaphore.exists_or_create! + sleep 3.0 + expect(@redis.keys.count).to eq(original_key_size) + end + end + describe "semaphore without staleness checking" do let(:semaphore) { Redis::Semaphore.new(:my_semaphore, :redis => @redis) } let(:multisem) { Redis::Semaphore.new(:my_semaphore_2, :resources => 2, :redis => @redis) }