I'm building an app where I need to have three scoreboards which I'm implementing with sorted sets and lists. The app is running on node.js using the node_redis (https://github.com/mranney/node_redis) module for the redis client.
The first scoreboard is a 'latest scores' which I'm using a list and LPUSH for. The second is an all time high score which I'm using a sorted list for with the ZADD command.
I'm having trouble implementing a 'high scores this week'. I was thinking that I should use another sorted list using ZADD with an EXPIRE set for one week. That all works fine, but after the list has expired for the first time, it'll continue to add to a new list forever.
Is there a redis command to have an expire to auto renew? (I've been searching for an answer for a couple of hours now but the answer appears to be no). I'm coming to the conclusion that I'll need to do this programmatically. During a function call that uses the set, I could check to see if the TTL is -1 and reset it there and then. Is this best practice? Am I missing a clever trick somewhere? Do I need to be concerned about the extra database requests?
--EDIT--
I've had a reply to this question on twitter https://twitter.com/redsmin/status/302177241167691777
The suggested solution (if I understand correctly) is to use the EXPIREAT command along with each ZADD
expireat myscoreboard {{timestamp of the end of the week}}
zadd myscoreboard 1 "one"
This "feels" right to me but I'm new to redis so would appreciate some discussion on this technique or any other ways of solving the problem.
It depends on how you define "one week". There are several ways to use it, for example:
The simplest to implement are 2 & 3. You specify a set which includes in it's keyname the date/time to start on, using an expire of one week. You then simply determine on the client side which day you want and grab the data.
For example zadd scoreboard:weekly:03:March:2013 1 "bob"
Then the following week your keyname would be zadd scoreboard:weekly:10:March:2013 1 "bob"
When you first create the key you set the expires, and that is all. No need to re-set it every time. Pseudocode follows:
if (ttl scoreboard:weekly:03:March:2013) == 0: expire scoreboard:weekly:03:March:2013 604800
This way you only set the expiration once, get auto-expiration, and can easily pull the weekly scoreboard.
You could implement a rolling week using the same method but you would need to go to a daily key name and calculate what keys to get, then merge them. You could do this using zunionstore.