Skip to content

Commit

Permalink
counter and stubby lock
Browse files Browse the repository at this point in the history
  • Loading branch information
Jay Adkisson committed Jun 20, 2010
1 parent fc93b67 commit 5a05e03
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/rudis/structure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ def watch(tries=0)
end
end

require_local 'structures/counter'
require_local 'structures/list'
require_local 'structures/lock'
require_local 'structures/hash'
require_local 'structures/set'
require_local 'structures/string'
Expand Down
27 changes: 27 additions & 0 deletions lib/rudis/structures/counter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
class Rudis
class Counter < Structure
def incr
redis.incr(key)
end

def decr
redis.decr(key)
end

def incrby(i)
redis.incrby(key, i.to_i)
end

def decrby(i)
redis.decrby(key, i.to_i)
end

def to_i
redis.get(key).to_i
end

def zero?
to_i.zero?
end
end
end
59 changes: 59 additions & 0 deletions lib/rudis/structures/lock.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
class Rudis
class Lock < Structure
class LockFailed < Exception; end

def acquire(options={})
options.rmerge!(
:tries => 1,
:sleep => 1
)

return set(options) unless block_given?

1.upto options[:tries] do
if set(options)
return begin
yield
ensure
clear
end
end
sleep options[:sleep]
end

# oops, we couldn't get the lock
raise LockFailed, <<-msg.squish
Unable to acquire lock after #{options[:tries]} time(s)
msg
return false
end

def set(options={})
options.rmerge!(
:timeout => 30
)
if redis.setnx(key, timestamp(options[:timeout]))
return true
else
# check the timestamp
old = redis.getset(key, timestamp(options[:timeout]))
if old < timestamp
# expired lock, we're good
return true
else
# lock is not expired, put it back
redis.set(key, old)
return false
end
end
end

alias clear del

private
def timestamp(timeout=0)
Time.now.to_i + timeout
end

end
end
17 changes: 17 additions & 0 deletions spec/counter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
describe Rudis::Counter do
before :each do
Rudis::Counter.redis.flushdb
@c = Rudis::Counter.new('my_counter')
end

it "counts!" do
@c.to_i.should == 0
@c.should be_zero
@c.incr.should == 1
@c.incr.should == 2
@c.decr.should == 1
@c.incrby(4).should == 5
@c.decrby(2).should == 3
@c.incrby(-1).should == 2
end
end

0 comments on commit 5a05e03

Please sign in to comment.