From 7695b606c6145904295e8dbc10eb45f5f44b7c9f Mon Sep 17 00:00:00 2001 From: Zaid Abdulla Date: Sat, 9 Nov 2013 00:16:06 +0300 Subject: [PATCH] Use locking to avoid possible unnecessary fetching and caching of presets and objects --- db.coffee | 72 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/db.coffee b/db.coffee index 6a6b334..ee7b0ad 100644 --- a/db.coffee +++ b/db.coffee @@ -51,6 +51,53 @@ getTask = (taskId, callback) -> ) +getCached = (name, valueCallback, valueExpiry, callback) -> + redisClient.get(name, (err, res) -> + return callback(err) if err + return callback(null, JSON.parse(res)) if res? + + lockAcquired = () -> + valueCallback((err, value) -> + return callback(err, value) if err + redisClient.setex(name, valueExpiry, JSON.stringify(value), (err) -> + return callback(err, value) if err + redisClient.del("lock.#{name}", (err) -> + callback(err, value) + ) + ) + ) + + redisClient.setnx("lock.#{name}", Date.now() + 30000, (err, res) -> + return callback(err) if err + if res == 1 + lockAcquired() + else + setTimeout(() -> + redisClient.get("lock.#{name}", (err, timestamp) -> + return callback(err) if err + now = Date.now() + if not timestamp? + getCached(name, valueCallback, valueExpiry, callback) + else if timestamp > now + setTimeout(() -> + getCached(name, valueCallback, valueExpiry, callback) + , 1000) + else + redisClient.getset("lock.#{name}", now + 30000, (err, timestamp) -> + return callback(err) if err + if timestamp > now + setTimeout(() -> + getCached(name, valueCallback, valueExpiry, callback) + , 1000) + else + lockAcquired() + ) + ) + , 1000) + ) + ) + + getPresets = (callback) -> redisClient.mget('presets', 'objects', (err, res) -> presets = JSON.parse(res[0]) @@ -60,22 +107,27 @@ getPresets = (callback) -> return if not presets - presetsCollection.find().toArray((err, p) -> + getCached('presets', (callback) -> + presetsCollection.find().toArray((err, res) -> + callback(err, res) + ) + , config.PRESETS_CACHE_DURATION, (err, res) -> throw err if err - presets = p - - redisClient.setex('presets', config.PRESETS_CACHE_DURATION, JSON.stringify(presets)) + presets = res callback(presets, objects) if objects ) if not objects - objectsCollection.find().toArray((err, o) -> + getCached('objects', (callback) -> + objectsCollection.find().toArray((err, res) -> + return callback(err) if err + objs = {} + objs[r._id] = r for r in res + callback(null, objs) + ) + , config.PRESETS_CACHE_DURATION, (err, res) -> throw err if err - objects = {} - for i in o - objects[i._id] = i - - redisClient.setex('objects', config.PRESETS_CACHE_DURATION, JSON.stringify(objects)) + objects = res callback(presets, objects) if presets ) )