Skip to content

Commit

Permalink
dlete sample complete
Browse files Browse the repository at this point in the history
  • Loading branch information
pallavi2209 committed Mar 11, 2017
1 parent 2279b86 commit 01fa404
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 5 deletions.
13 changes: 12 additions & 1 deletion api/v1/controllers/samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,18 @@ module.exports = {
* @param {Function} next - The next middleware function in the stack
*/
deleteSample(req, res, next) {
doDelete(req, res, next, helper);
if (featureToggles.isFeatureEnabled(constants.featureName)) {
const resultObj = { reqStartTime: new Date() }; // for logging
const sampleName = req.swagger.params.key.value.toLowerCase();
redisModelSample.deleteSample(sampleName, resultObj, req.method)
.then((response) => {
u.logAPI(req, resultObj, response); // audit log
res.status(httpStatus.OK).json(response);
})
.catch((err) => u.handleError(next, err, helper.modelName));
} else {
doDelete(req, res, next, helper);
}
},

/**
Expand Down
57 changes: 57 additions & 0 deletions cache/models/samples.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const defaults = require('../../config').api.defaults;
const redisErrors = require('../redisErrors');
const sampleUtils = require('../../db/helpers/sampleUtils');
const dbConstants = require('../../db/constants');
const redisOps = require('../redisOps');
const aspectType = redisOps.aspectType;
const sampleType = redisOps.sampleType;
const subjectType = redisOps.subjectType;
const sampFields = {
MSG_BODY: 'messageBody',
MSG_CODE: 'messageCode',
Expand All @@ -43,6 +47,7 @@ const sampleFieldsArr = Object.keys(sampFields).map(
const ZERO = 0;
const ONE = 1;
const TWO = 2;
const THREE = 3;
const MINUS_ONE = -1;

/**
Expand Down Expand Up @@ -437,6 +442,58 @@ function upsertOneSample(sampleQueryBodyObj, method) {

module.exports = {

/**
* Delete sample. Get sample. If found, get aspect, delete sample entry from
* sample index, delete aspect from subject set and delete sample hash. If
* sample not found, thro Not found error.
* @param {String} sampleName - Sample name
* @param {Object} logObject - Log object
* @param {String} method - Type of request method
* @returns {Promise} - Resolves to a sample object
*/
deleteSample(sampleName, logObject, method) {
const subjAspArr = sampleName.toLowerCase().split('|');

if (subjAspArr.length < TWO) {
const err = new redisErrors.ValidationError({
explanation: 'Incorrect sample name.',
});
return Promise.resolve(err);
}

const subjAbsPath = subjAspArr[ZERO];
const aspName = subjAspArr[ONE];
const cmds = [];
let sampObjToReturn;

return redisOps.getHashPromise(sampleType, sampleName)
.then((sampleObj) => {
if (!sampleObj) {
throw new redisErrors.ResourceNotFoundError({
explanation: 'Sample not found.',
});
}

sampObjToReturn = sampleObj;
})
.then(() => {
cmds.push(redisOps.getHashCmd(aspectType, aspName));
cmds.push(redisOps.delKeyFromIndexCmd(sampleType, sampleName));
cmds.push(redisOps.delAspFromSubjSetCmd(subjAbsPath, aspName));
cmds.push(redisOps.delHashCmd(sampleType, sampleName));

return redisOps.executeBatchCmds(cmds);
})
.then((response) => {
logObject.dbTime = new Date() - logObject.reqStartTime; // log db time
const asp = response[ZERO];

// attach aspect and links to sample
const resSampAsp = cleanAddAspectToSample(sampObjToReturn, asp, method);
return resSampAsp;
});
},

/**
* Retrieves the sample from redis and sends it back in the response. Get
* sample and corresponsing aspect from redis and then apply field list
Expand Down
106 changes: 102 additions & 4 deletions cache/redisOps.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ function addKey(type, name) {

/**
* Deletes an entry from the master list of indices identified by "type" and
* and the corresponding set identified by "name". Use this to delete a single
* and the corresponding hash identified by "name". Use this to delete a single
* key from the subjectStore, aspectStore or SampleStore.
* @param {String} type - The type of the master list on which the
* set operations are to be performed
* @param {String} name - Name of the key to be added
* @param {String} name - Name of the key to be deleted
* @returns {Promise} - which resolves to the values returned by the redis
* batch command
*/
Expand All @@ -80,7 +80,7 @@ function deleteKey(type, name) {
// remove the entry from the master index of type
cmds.push(['srem', indexName, key]);

// delete the set
// delete the hash
cmds.push(['del', key]);
return redisClient.batch(cmds).execAsync()
.then((ret) => Promise.resolve(ret))
Expand Down Expand Up @@ -132,7 +132,7 @@ function deleteKeys(type, objectName, name) {
// remove the entry from the master list of index
cmds.push(['srem', indexName, Array.from(keyArr)]);

// delete the set too
// delete the hash too
cmds.push(['del', Array.from(keyArr)]);
return redisClient.batch(cmds).execAsync();
})
Expand Down Expand Up @@ -241,6 +241,104 @@ function renameKeys(type, objectName, oldName, newName) {
} // renameKeys

module.exports = {

/**
* Command to delete key from master index
* @param {String} type - Object type
* @param {String} name - Object name
* @returns {Array} - Command array
*/
delKeyFromIndexCmd(type, name) {
const indexName = redisStore.constants.indexKey[type];
const nameKey = redisStore.toKey(type, name);
return ['srem', indexName, nameKey];
},

/**
* Command to check if key exists in master index
* @param {String} type - Object type
* @param {String} name - Object name
* @returns {Array} - Command array
*/
keyExistsInIndexCmd(type, name) {
const indexName = redisStore.constants.indexKey[type];
const nameKey = redisStore.toKey(type, name);
return ['sismember', indexName, nameKey];
},

/**
* Command to delete aspect from subject set
* @param {String} subjAbsPath - Subject absolute path
* @param {String} aspName - Aspect name
* @returns {Array} - Command array
*/
delAspFromSubjSetCmd(subjAbsPath, aspName) {
return [
'srem',
redisStore.toKey(subjectType, subjAbsPath),
aspName.toLowerCase(),
];
},

/**
* Command to check if aspect exists in subject set
* @param {String} subjAbsPath - Subject absolute path
* @param {String} aspName - Aspect name
* @returns {Array} - Command array
*/
aspExistsInSubjSetCmd(subjAbsPath, aspName) {
return [
'sismember',
redisStore.toKey(subjectType, subjAbsPath),
aspName.toLowerCase(),
];
},

/**
* Command to delete hash
* @param {String} type - Object type
* @param {String} name - Object name
* @returns {Array} - Command array
*/
delHashCmd(type, name) {
return [
'del',
redisStore.toKey(type, name),
];
},

/**
* Command to get complete hash.
* @param {String} type - Object type
* @param {String} name - Object name
* @returns {Array} - Command array
*/
getHashCmd(type, name) {
return [
'hgetall',
redisStore.toKey(type, name),
];
},

/**
* Promise to get complete hash
* @param {String} type - Object type
* @param {String} name - Object name
* @returns {Promise} - Resolves to object
*/
getHashPromise(type, name) {
return redisClient.hgetallAsync(redisStore.toKey(type, name));
},

/**
* Execute command asynchronously
* @param {Array} cmds - array of commands
* @returns {Promise} - Resolves to commands responses
*/
executeBatchCmds(cmds) {
return redisClient.batch(cmds).execAsync();
},

renameKey,

renameKeys,
Expand Down
103 changes: 103 additions & 0 deletions tests/cache/models/samples/delete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* 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/cache/models/samples/delete.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 path = '/v1/samples';
const rtu = require('../redisTestUtil');
const redisOps = require('../../../../cache/redisOps');
const objectType = require('../../../../cache/sampleStore')
.constants.objectType;
const expect = require('chai').expect;
const ZERO = 0;

describe(`api: DELETE ${path}`, () => {
const sampleName = '___Subject1.___Subject2|___Aspect1';
let token;

before((done) => {
tu.toggleOverride('enableRedisSampleStore', true);
tu.createToken()
.then((returnedToken) => {
token = returnedToken;
done();
})
.catch((err) => done(err));
});

beforeEach(rtu.populateRedis);
afterEach(rtu.forceDelete);
after(() => tu.toggleOverride('enableRedisSampleStore', false));

it('basic delete', (done) => {
api.delete(`${path}/${sampleName}`)
.set('Authorization', token)
.expect(constants.httpStatus.OK)
.expect((res) => {
if (tu.gotExpectedLength(res.body, ZERO)) {
throw new Error('expecting sample');
}
})
.end((err /* , res */) => {
if (err) {
done(err);
}

const subjAspArr = sampleName.toLowerCase().split('|');

const cmds = [];
cmds.push(redisOps.getHashCmd(objectType.sample, sampleName));
cmds.push(redisOps.keyExistsInIndexCmd(objectType.sample, sampleName));
cmds.push(redisOps.aspExistsInSubjSetCmd(subjAspArr[0], subjAspArr[1]));

redisOps.executeBatchCmds(cmds)
.then((response) => {
expect(response[0]).to.be.equal(null);
expect(response[1]).to.be.equal(0);
expect(response[2]).to.be.equal(0);
});
done();
});
});

it('does not return id', (done) => {
api.delete(`${path}/${sampleName}`)
.set('Authorization', token)
.expect(constants.httpStatus.OK)
.end((err, res) => {
if (err) {
done(err);
}

expect(res.body.name).to.equal(sampleName);
done();
});
});

it('is case in-sensitive', (done) => {
api.delete(`${path}/${sampleName.toLowerCase()}`)
.set('Authorization', token)
.expect(constants.httpStatus.OK)
.end((err, res) => {
if (err) {
done(err);
}

expect(res.body.name).to.equal(sampleName);
done();
});
});
});

0 comments on commit 01fa404

Please sign in to comment.