Reputation: 787
I have a set of of ~60 sorted sets each containing a ~200 members which I am trying to process. Previously I built a Redis (Lua) serverside script but the big(O) time values of the request bog down under load.
I am now trying to offload the processing to Ruby/Sinatra and refreshing the results on every request proving to be inefficient. Given the code below, is there an way to cache the "scores" results in Sinatra so I don't have to pull from Redis on every request?
global = redis.smembers("id_list")
i=0
scores = redis.pipelined do
global.each do |key|
redis.zrange("user:#{global[i]}",0,100,:with_scores => true)
i+=1
end
end
Upvotes: 1
Views: 783
Reputation: 1506
Sinatra has a global scope where objects will persist between requests. If you have a scorekeeper class defined which maintains an instance variable for your score, then you can have a lookup method for the score which holds the value. For example:
class Scorekeeper
def initialize
@scores = nil
end
def scores
@scores ||= get_scores
end
def get_scores
global = redis.smembers("id_list")
i=0
scores = redis.pipelined do
global.each do |key|
redis.zrange("user:#{global[i]}",0,100,:with_scores => true)
i+=1
end
end
scores
end
end
Now your Sinatra app just needs to instantiate a scorekeeper outside of any resource declaration:
require 'sinatra'
keeper = Scorekeeper.new
get '/scores' do
keeper.scores
end
This way on the first request, the scores property will get populated, on all further requests, it will use the cached value.
Upvotes: 3