Skip to content

Instantly share code, notes, and snippets.

@latompa
Last active December 10, 2015 21:48
Show Gist options
  • Save latompa/4497555 to your computer and use it in GitHub Desktop.
Save latompa/4497555 to your computer and use it in GitHub Desktop.
Individual set member expiry, inspired by https://github.com/antirez/redis/issues/135
require 'redis'
#
# The drawback with this approach is old members are deleted as you add new, creates a bit of overhead.
# The whole set expires, using normal redis expiration, if you don't add anything until the last member was added
#
class ExpiringSortedSet
attr_reader :key
def initialize(args)
@key = args[:key]
@redis = args[:redis]
@expiry = args[:expiry]
end
def add(v)
created_at = Time.now.to_i
expire_old_set_members(created_at)
expire_key
@redis.zadd @key, created_at+@expiry, v
end
def members
@redis.zrangebyscore @key, Time.now.to_i, "+inf"
end
private
def expire_key
@redis.expire @key,@expiry
end
def expire_old_set_members(since)
@redis.zremrangebyscore @key, "-inf", since-1
end
end
p "running timed test"
# make a set with key test:1, set members should expire within 5 seconds
s = ExpiringSortedSet.new(:key => "test:1",
:redis => (redis=Redis.new(:host => "localhost")),
:expiry => 5)
redis.del s.key
s.add(1)
sleep 3
puts s.members, "^ should be 1"
s.add(2)
puts s.members, "^ should be 1, 2"
sleep 3 # 1 expires here
puts s.members, "^ should be 2"
s.add(3)
puts s.members, "^ should be 2, 3"
# if set isn't accessed in the next 5 seconds, the whole key expires
sleep 6
puts s.members, "^ should be empty"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment