diff --git a/api/v1/helpers/verbs/doFind.js b/api/v1/helpers/verbs/doFind.js index 74714865ff..1afd626b52 100644 --- a/api/v1/helpers/verbs/doFind.js +++ b/api/v1/helpers/verbs/doFind.js @@ -16,7 +16,7 @@ const fu = require('./findUtils'); const COUNT_HEADER_NAME = require('../../constants').COUNT_HEADER_NAME; const httpStatus = require('../../constants').httpStatus; const redisCache = require('../../../../cache/redisCache').client; -const SECS_IN_MIN = 60; +const cacheExpiry = require('../../../../config').CACHE_EXPIRY_IN_SECS; /** * Finds all matching records but only returns a subset of the results for @@ -134,7 +134,7 @@ function doFindResponse(reqResNext, props, opts, cacheKey) { // cache the object by cacheKey. Store the key-value pair in cache // with an expiry of 1 minute (60s) const strObj = JSON.stringify(retval); - redisCache.setex(cacheKey, SECS_IN_MIN, strObj); + redisCache.setex(cacheKey, cacheExpiry, strObj); } }) .catch((err) => u.handleError(reqResNext.next, err, props.modelName)); diff --git a/api/v1/helpers/verbs/doGet.js b/api/v1/helpers/verbs/doGet.js index 1579080bab..f1f37ad551 100644 --- a/api/v1/helpers/verbs/doGet.js +++ b/api/v1/helpers/verbs/doGet.js @@ -14,8 +14,7 @@ const u = require('./utils'); const httpStatus = require('../../constants').httpStatus; const redisCache = require('../../../../cache/redisCache').client; - -const SECS_IN_MIN = 60; +const cacheExpiry = require('../../../../config').CACHE_EXPIRY_IN_SECS; /** * Retrieves a record and sends it back in the json response with status code @@ -41,6 +40,8 @@ function doGet(req, res, next, props) { cacheKey += reqParams.fields.value; } + console.log(cacheKey); + redisCache.get(cacheKey, (cacheErr, reply) => { if (cacheErr || !reply) { // if err or no reply, get from db and set redis cache @@ -51,7 +52,7 @@ function doGet(req, res, next, props) { // cache the object by cacheKey. Store the key-value pair in cache // with an expiry of 1 minute (60s) const strObj = JSON.stringify(o); - redisCache.setex(cacheKey, SECS_IN_MIN, strObj); + redisCache.setex(cacheKey, cacheExpiry, strObj); }) .catch((err) => u.handleError(next, err, props.modelName)); } else { diff --git a/config.js b/config.js index d10a1bae6c..d1813e7f7b 100644 --- a/config.js +++ b/config.js @@ -41,6 +41,8 @@ const auditSubjects = pe.AUDIT_SUBJECTS || 'NONE'; const auditSamples = pe.AUDIT_SAMPLES || 'NONE'; const auditAspects = pe.AUDIT_ASPECTS || 'NONE'; +const CACHE_EXPIRY_IN_SECS = 60; + module.exports = { api: { @@ -162,4 +164,5 @@ module.exports = { auditSubjects, auditSamples, auditAspects, + CACHE_EXPIRY_IN_SECS, }; diff --git a/package.json b/package.json index 4caf0e3be7..3e9212daa0 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,10 @@ "test-api": "mocha -R dot --recursive tests/api", "test-disablehttp": "DISABLE_HTTP=true mocha -R dot --recursive tests/disableHttp", "test-enforced": "USE_ACCESS_TOKEN=true mocha -R dot --recursive tests/enforceToken", + "test-cache-persp": "ENABLE_CACHE_PERSPECTIVE=true mocha -R dot --recursive tests/enableCache", "test-db": "npm run checkdb && mocha -R dot --recursive tests/db", "test-view": "NODE_ENV=build mocha -R dot --recursive --compilers js:babel-core/register --require ./tests/view/setup.js tests/view", - "test": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R dot --recursive tests/api tests/clock tests/config tests/db tests/jobQueue tests/realtime tests/tokenNotReq && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage && npm run test-view && npm run test-disablehttp && npm run test-enforced", + "test": "istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R dot --recursive tests/api tests/clock tests/config tests/db tests/jobQueue tests/realtime tests/tokenNotReq && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage && npm run test-view && npm run test-disablehttp && npm run test-enforced && npm run test-cache-persp", "undo-migratedb": "node db/migrateUndo.js", "view": "NODE_ENV=production gulp browserifyViews && npm start" }, diff --git a/tests/enableCache/perspectives.js b/tests/enableCache/perspectives.js new file mode 100644 index 0000000000..087623ad56 --- /dev/null +++ b/tests/enableCache/perspectives.js @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2017, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or + * https://opensource.org/licenses/BSD-3-Clause + */ + +/** + * tests/enableCache/perspectives.js + */ +'use strict'; // eslint-disable-line strict + +const supertest = require('supertest'); +const api = supertest(require('../../index').app); +const constants = require('../../api/v1/constants'); +const tu = require('../testUtils'); +const u = require('./utils'); +const path = '/v1/perspectives'; +const expect = require('chai').expect; +const redisCache = require('../../cache/redisCache').client; +const ZERO = 0; +const ONE = 1; + +describe(`api: GET ${path}`, () => { + let lensId; + let token; + let perspectiveId; + // let perspectiveName; + + before((done) => { + redisCache.flushdb(); + tu.createToken() + .then((returnedToken) => { + token = returnedToken; + done(); + }) + .catch(done); + }); + + before((done) => { + u.doSetup() + .then((createdLens) => tu.db.Perspective.create({ + name: `${tu.namePrefix}testPersp`, + lensId: createdLens.id, + rootSubject: 'myMainSubject', + aspectFilter: ['temperature', 'humidity'], + aspectTagFilter: ['temp', 'hum'], + subjectTagFilter: ['ea', 'na'], + statusFilter: ['Critical', '-OK'], + })) + .then((createdPersp) => { + lensId = createdPersp.lensId; + perspectiveId = createdPersp.id; + // perspectiveName = createdPersp.name; + done(); + }) + .catch(done); + }); + + after(u.forceDelete); + after(tu.forceDeleteUser); + + it('basic get', (done) => { + api.get(path) + .set('Authorization', token) + .expect(constants.httpStatus.OK) + .end((err, res) => { + if (err) { + done(err); + } + + expect(res.body).to.have.length(ONE); + expect(res.body[ZERO].name).to.be.equal('___testPersp'); + expect(res.body).to.have.deep.property('[0].lensId', lensId); + + done(); + }); + }); + + it('basic get, response present in cache', (done) => { + redisCache.get('{\"where\":{}}', (cacheErr, reply) => { + if (reply) { + const jsonReply = JSON.parse(reply); + expect(jsonReply).to.have.length(ONE); + expect(jsonReply[ZERO].name).to.be.equal('___testPersp'); + expect(jsonReply).to.have.deep.property('[0].lensId', lensId); + + done(); + } else { + throw new Error('Expected response value in cache'); + } + }); + }); + + it('get with limit and sort', (done) => { + api.get(path + '?limit=10&sort=name') + .set('Authorization', token) + .expect(constants.httpStatus.OK) + .end((err, res) => { + if (err) { + done(err); + } + + expect(res.body).to.have.length(ONE); + expect(res.body[ZERO].name).to.be.equal('___testPersp'); + expect(res.body).to.have.deep.property('[0].lensId', lensId); + + done(); + }); + }); + + it('get with limit and sort, response present in cache', (done) => { + redisCache.get('{"order":["name"],"limit":10,"where":{}}', + (cacheErr, reply) => { + if (reply) { + const jsonReply = JSON.parse(reply); + expect(jsonReply).to.have.length(ONE); + expect(jsonReply[ZERO].name).to.be.equal('___testPersp'); + expect(jsonReply).to.have.deep.property('[0].lensId', lensId); + + done(); + } else { + throw new Error('Expected response value in cache'); + } + }); + }); + + it('basic get by id', (done) => { + api.get(`${path}/${perspectiveId}`) + .set('Authorization', token) + .expect(constants.httpStatus.OK) + .end((err, res) => { + if (err) { + done(err); + } + + expect(res.body.name).to.equal(`${tu.namePrefix}testPersp`); + expect(res.body.rootSubject).to.equal('myMainSubject'); + expect(res.body.lensId).to.equal(lensId); + + done(); + }); + }); + + it('basic get by id, response present in cache', (done) => { + redisCache.get(perspectiveId, + (cacheErr, reply) => { + if (reply) { + const jsonReply = JSON.parse(reply); + expect(jsonReply.name).to.equal(`${tu.namePrefix}testPersp`); + expect(jsonReply.rootSubject).to.equal('myMainSubject'); + expect(jsonReply.lensId).to.equal(lensId); + + done(); + } else { + throw new Error('Expected response value in cache'); + } + }); + }); +}); diff --git a/tests/enableCache/utils.js b/tests/enableCache/utils.js new file mode 100644 index 0000000000..8e8fe181ce --- /dev/null +++ b/tests/enableCache/utils.js @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2017, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or + * https://opensource.org/licenses/BSD-3-Clause + */ + +/** + * tests/enableCache/utils.js + */ +'use strict'; // eslint-disable-line strict + +const tu = require('../testUtils'); +const path = require('path'); +const fs = require('fs'); + +const testStartTime = new Date(); + +module.exports = { + doSetup() { + return new tu.db.Sequelize.Promise((resolve, reject) => { + const willSendthis = fs.readFileSync( + path.join(__dirname, + '../api/v1/apiTestsUtils/lens.zip') + ); + const lens = { + name: `${tu.namePrefix}testLensName`, + sourceName: 'testSourceLensName', + description: 'test Description', + sourceDescription: 'test Source Description', + isPublished: true, + library: willSendthis, + }; + tu.db.Lens.create(lens) + .then(resolve) + .catch(reject); + }); + }, + + forceDelete(done) { + tu.forceDelete(tu.db.Perspective, testStartTime) + .then(() => tu.forceDelete(tu.db.Lens, testStartTime)) + .then(() => done()) + .catch(done); + }, +};