Permalink
Browse files

solving #33 - cached version of request used

  • Loading branch information...
Diego Lafuente
Diego Lafuente committed May 2, 2015
1 parent 28c38df commit e6169e61974a0304eec22fbcb95655d85f5fdece
Showing with 187 additions and 58 deletions.
  1. +14 −3 lib/cache.js
  2. +149 −0 lib/cached-request.js
  3. +11 −7 lib/factors/versions.js
  4. +12 −47 lib/packages.js
  5. +1 −1 test.js
View
@@ -62,6 +62,14 @@ exports.clear = function ()
cache = {};
};
/*
* Clears the interval (only for test purposes)
*/
exports.clearInterval = function ()
{
clearInterval(interval);
};
/*
* Clears the expired registries
*/
@@ -77,8 +85,8 @@ function clearExpired()
}
}
// TODO!!: set timeout with a period (repetitive) and assign it to a variable
//setTimeout(clearExpired, defaultExpiration * 1000);
// Set periodic task to clear cache
var interval = setInterval(clearExpired, defaultExpiration * 1000);
/************************************************
**************** UNIT TESTS ********************
@@ -136,7 +144,10 @@ exports.test = function(callback)
testGetInvalidKey,
testClearExpired,
testValidCycleCache
], 10000, callback);
], 10000, function(error, result) {
exports.clearInterval();
return callback(error, result);
});
};
// run tests if invoked directly
View
@@ -0,0 +1,149 @@
'use strict';
/**
* Wrapper over the request library featuring a cache.
* (C) 2015 Diego Lafuente.
*/
// requires
var requestLib = require('request');
var cache = require('./cache.js');
var testing = require('testing');
/**
* Wraps request.get including the cache option
* @param url[required]: the url to call
* @param shouldCache[optional]: boolean indicating if the request should be cached. Defaults to false.
* @param callback[required]: a function(error, response, body) to be called when finished
*/
exports.get = function(url, shouldCache, callback) {
if (typeof shouldCache === 'function') {
callback = shouldCache;
shouldCache = false;
}
// check cache if needed
if (shouldCache) {
var cachedResponse = cache.get(url);
if (cachedResponse) {
return callback (null, null, cachedResponse.value);
}
}
requestLib.get(url, function(error, response, body) {
// cache response if everything ok and cache is true
if (shouldCache && !error && response.statusCode === 200) {
cache.set(url, body);
}
return callback (error, response, body);
});
};
/************************************************
**************** UNIT TESTS ********************
************************************************/
function testShouldCacheOmitted(callback) {
var testUrl = 'testUrl';
//stubs
var restoreRequestLibGet = requestLib.get;
requestLib.get = function(url, internalCallback) {
testing.assertEquals(url, testUrl, 'wrong url passed to request.get', callback);
return internalCallback(null, 'testResponse', 'testBody');
};
var restoreCache = cache;
cache = {
get: function() {
testing.assert(false, 'cache.get should not be called');
},
set: function() {
testing.assert(false, 'cache.set should not be called');
}
};
exports.get(testUrl, function (error, response, body) {
testing.check(error, callback);
testing.assertEquals(response, 'testResponse', 'wrong response', callback);
testing.assertEquals(body, 'testBody', 'wrong response', callback);
// restore
cache = restoreCache;
requestLib.get = restoreRequestLibGet;
testing.success(callback);
});
}
function testShouldCacheFalse(callback) {
var testUrl = 'testUrl';
//stubs
var restoreRequestLibGet = requestLib.get;
requestLib.get = function(url, internalCallback) {
testing.assertEquals(url, testUrl, 'wrong url passed to request.get', callback);
return internalCallback(null, 'testResponse', 'testBody');
};
var restoreCache = cache;
cache = {
get: function() {
testing.assert(false, 'cache.get should not be called');
},
set: function() {
testing.assert(false, 'cache.set should not be called');
}
};
exports.get(testUrl, false, function (error, response, body) {
testing.check(error, callback);
testing.assertEquals(response, 'testResponse', 'wrong response', callback);
testing.assertEquals(body, 'testBody', 'wrong response', callback);
// restore
cache = restoreCache;
requestLib.get = restoreRequestLibGet;
testing.success(callback);
});
}
function testShouldCacheTrue(callback) {
var testUrl = 'testUrl';
//stubs
var restoreRequestLibGet = requestLib.get;
requestLib.get = function(url, internalCallback) {
testing.assertEquals(url, testUrl, 'wrong url passed to request.get', callback);
return internalCallback(null, {statusCode: 200}, 'testBody');
};
var restoreCache = cache;
cache = {
get: function(key) {
testing.assertEquals(key, testUrl, 'wrong url passed to cache.get', callback);
},
set: function(key, value) {
testing.assertEquals(key, testUrl, 'wrong url passed to cache.set', callback);
testing.assertEquals(value, 'testBody', 'wrong url passed to cache.set', callback);
}
};
exports.get(testUrl, true, function (error, response, body) {
testing.check(error, callback);
testing.assertEquals(body, 'testBody', 'wrong response', callback);
// restore
cache = restoreCache;
requestLib.get = restoreRequestLibGet;
testing.success(callback);
});
}
/**
* Run all tests.
*/
exports.test = function(callback)
{
testing.run([
testShouldCacheOmitted,
testShouldCacheFalse,
testShouldCacheTrue
], function (error, result) {
cache.clearInterval();
return callback (error, result);
});
};
// run tests if invoked directly
if (__filename == process.argv[1])
{
exports.test(testing.show);
}
View
@@ -9,7 +9,8 @@
require('prototypes');
var Log = require('log');
var config = require('../../config.js');
var request = require('request');
var cache = require('../cache.js');
var request = require('../cached-request.js');
var testing = require('testing');
// globals
@@ -38,7 +39,7 @@ exports.estimate = function(entry, callback)
};
var registryUrl = 'http://registry.npmjs.org/' + name;
log.debug('Estimating versions with URL: %s', registryUrl);
request.get(registryUrl, function(error, response, body)
request.get(registryUrl, true, function(error, response, body)
{
if (error)
{
@@ -81,7 +82,7 @@ function testEstimateInvalidPackageName(callback)
name: 'invalid'
};
// stub request.get
request.get = function(url, internalCallback) {
request.get = function(url, shouldCache, internalCallback) {
return internalCallback('error');
};
exports.estimate(entry, function (error, estimation) {
@@ -97,7 +98,7 @@ function testEstimateInvalidJsonReturnedByRegistry(callback)
name: 'valid'
};
// stub request.get
request.get = function(url, internalCallback) {
request.get = function(url, shouldCache, internalCallback) {
return internalCallback(null, null, 'invalid_json');
};
exports.estimate(entry, function (error, estimation) {
@@ -113,7 +114,7 @@ function testEstimateValidEntryNoVersions(callback)
name: 'valid'
};
// stub request.get
request.get = function(url, internalCallback) {
request.get = function(url, shouldCache, internalCallback) {
var response = {};
return internalCallback(null, null, JSON.stringify(response));
};
@@ -130,7 +131,7 @@ function testEstimateValidEntry(callback)
name: 'valid'
};
// stub request.get
request.get = function(url, internalCallback) {
request.get = function(url, shouldCache, internalCallback) {
var response = {versions: {version1: {},version2: {}}};
return internalCallback(null, null, JSON.stringify(response));
};
@@ -152,7 +153,10 @@ exports.test = function(callback)
testEstimateInvalidJsonReturnedByRegistry,
testEstimateValidEntryNoVersions,
testEstimateValidEntry
], callback);
], function (error, result) {
cache.clearInterval();
return callback(error, result);
});
};
// run tests if invoked directly
View
@@ -5,7 +5,7 @@ var Log = require('log');
var testing = require('testing');
var db = require('./db.js');
var cache = require('./cache.js');
var requestLib = require('request');
var requestLib = require('./cached-request.js');
var config = require('../config.js');
// globals
@@ -277,18 +277,8 @@ exports.findInNpmRegistry = function (name, callback)
return callback('name is null or empty');
}
var registryUrl = 'http://registry.npmjs.org/' + name;
// check cache
var cachedResponse = cache.get(registryUrl);
if (cachedResponse) {
var result = {
name: cachedResponse.name,
repository: cachedResponse.repository,
description: cachedResponse.description
};
return callback(null, result);
}
// not cached, perform request
requestLib.get(registryUrl, function(error, getResponse, body)
// perform request
requestLib.get(registryUrl, true, function(error, getResponse, body)
{
if (error)
{
@@ -313,8 +303,6 @@ exports.findInNpmRegistry = function (name, callback)
repository: registryResponse.repository,
description: registryResponse.description
};
//cache response
cache.set(registryUrl, registryResponse);
return callback(null, result);
});
};
@@ -341,7 +329,7 @@ function testFindInNpmRegistryErrorResponse(callback)
{
//stub requestLib.get
var restoreRequestLibGet = requestLib.get;
requestLib.get = function (url, internalCallback) {
requestLib.get = function (url, shouldCache, internalCallback) {
internalCallback({check:true});
};
exports.findInNpmRegistry('test', function (error, result) {
@@ -356,9 +344,9 @@ function testFindInNpmRegistryErrorResponse(callback)
function testFindInNpmRegistryEmptyResponse(callback)
{
//stub cache.get
//stub requestLib.get
var restoreRequestLibGet = requestLib.get;
requestLib.get = function (url, internalCallback) {
requestLib.get = function (url, shouldCache, internalCallback) {
internalCallback(null, null, '');
};
exports.findInNpmRegistry('test', function (error, result) {
@@ -374,7 +362,7 @@ function testFindInNpmRegistryErrorInvalidJsonResponse(callback)
{
//stub requestLib.get
var restoreRequestLibGet = requestLib.get;
requestLib.get = function (url, internalCallback) {
requestLib.get = function (url, shouldCache, internalCallback) {
internalCallback(null, null, 'invalid_json');
};
exports.findInNpmRegistry('test', function (error, result) {
@@ -386,43 +374,18 @@ function testFindInNpmRegistryErrorInvalidJsonResponse(callback)
});
}
function testFindInNpmRegistryCachedResponse(callback)
{
//stub requestLib.get
var restoreCacheGet = cache.get;
cache.get = function () {
return {name:'testName',repository:'testRepository',description:'testDescription'};
};
exports.findInNpmRegistry('test', function (error, result) {
testing.check(error, callback);
testing.assertEquals(result.name, 'testName', 'wrong name in response for valid request', callback);
testing.assertEquals(result.repository, 'testRepository', 'wrong repository in response for valid request', callback);
testing.assertEquals(result.description, 'testDescription', 'wrong description in response for valid request', callback);
//restore cache.get
cache.get = restoreCacheGet;
testing.success(callback);
});
}
function testFindInNpmRegistryValidResponse(callback)
{
//stub requestLib.get
var restoreRequestLibGet = requestLib.get;
requestLib.get = function (url, internalCallback) {
requestLib.get = function (url, shouldCache, internalCallback) {
internalCallback(null, null, '{"name":"testName","repository":"testRepository","description":"testDescription"}');
};
exports.findInNpmRegistry('test', function (error, result) {
testing.check(error, callback);
testing.assertEquals(result.name, 'testName', 'wrong name in response for valid request', callback);
testing.assertEquals(result.repository, 'testRepository', 'wrong repository in response for valid request', callback);
testing.assertEquals(result.description, 'testDescription', 'wrong description in response for valid request', callback);
// check that the response was cached
var cachedResponse = cache.get('http://registry.npmjs.org/test');
testing.assertEquals(cachedResponse.name, 'testName', 'wrong name in cached response', callback);
testing.assertEquals(cachedResponse.repository, 'testRepository', 'wrong repository in cached response', callback);
testing.assertEquals(cachedResponse.description, 'testDescription', 'wrong description in cached response', callback);
// clear cache
cache.clear();
//restore requestLib.get
requestLib.get = restoreRequestLibGet;
testing.success(callback);
@@ -603,10 +566,12 @@ exports.test = function(callback) {
testFindInNpmRegistryErrorResponse,
testFindInNpmRegistryEmptyResponse,
testFindInNpmRegistryErrorInvalidJsonResponse,
testFindInNpmRegistryCachedResponse,
testFindInNpmRegistryValidResponse,
testClose
], callback);
], function (error, result) {
cache.clearInterval();
return callback(error, result);
});
};
// start tests if invoked directly
View
@@ -20,7 +20,7 @@ exports.test = function(callback)
{
log.debug('Running tests');
var tests = {};
var libs = ['estimation', 'db', 'badges', 'packages', 'update', 'cache'];
var libs = ['estimation', 'db', 'badges', 'packages', 'update', 'cache', 'cached-request'];
var factors = ['issues', 'versions', 'downloads'];
libs.forEach(function(lib)
{

0 comments on commit e6169e6

Please sign in to comment.