Skip to content

Get Timeline from DB #390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions src/routes/timelines/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,47 @@ const schema = {
params: {
timelineId: Joi.number().integer().positive().required(),
},
query: {
db: Joi.boolean().optional(),
},
};

// Load the milestones
const loadMilestones = timeline =>
timeline.getMilestones()
.then((milestones) => {
const loadedTimeline = _.omit(timeline.toJSON(), ['deletedAt', 'deletedBy']);
loadedTimeline.milestones =
_.map(milestones, milestone => _.omit(milestone.toJSON(), ['deletedAt', 'deletedBy']));

return Promise.resolve(loadedTimeline);
});

module.exports = [
validate(schema),
// Validate and get projectId from the timelineId param, and set to request params for
// checking by the permissions middleware
validateTimeline.validateTimelineIdParam,
permissions('timeline.view'),
(req, res, next) => {
eClient.get({ index: ES_TIMELINE_INDEX,
// when user query with db, bypass the elasticsearch
// and get the data directly from database
if (req.query.db) {
req.log.debug('bypass ES, gets timeline directly from database');
return loadMilestones(req.timeline).then(timeline => res.json(timeline));
}
return eClient.get({ index: ES_TIMELINE_INDEX,
type: ES_TIMELINE_TYPE,
id: req.params.timelineId,
})
.then((doc) => {
req.log.debug('timeline found in ES');
res.json(doc._source); // eslint-disable-line no-underscore-dangle
return res.json(doc._source); // eslint-disable-line no-underscore-dangle
})
.catch((err) => {
if (err.status === 404) {
req.log.debug('No timeline found in ES');
// Load the milestones
return req.timeline.getMilestones()
.then((milestones) => {
const timeline = _.omit(req.timeline.toJSON(), ['deletedAt', 'deletedBy']);
timeline.milestones =
_.map(milestones, milestone => _.omit(milestone.toJSON(), ['deletedAt', 'deletedBy']));

// Write to response
return res.json(timeline);
});
return loadMilestones(req.timeline).then(timeline => res.json(timeline));
}
return next(err);
});
Expand Down
152 changes: 117 additions & 35 deletions src/routes/timelines/get.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,51 @@
*/
import chai from 'chai';
import request from 'supertest';
import config from 'config';
import _ from 'lodash';

import models from '../../models';
import server from '../../app';
import testUtil from '../../tests/util';

const should = chai.should();

const ES_TIMELINE_INDEX = config.get('elasticsearchConfig.timelineIndexName');
const ES_TIMELINE_TYPE = config.get('elasticsearchConfig.timelineDocType');

const timelines = [
{
name: 'name 1',
description: 'description 1',
startDate: '2018-05-11T00:00:00.000Z',
endDate: '2018-05-12T00:00:00.000Z',
reference: 'project',
referenceId: 1,
createdBy: 1,
updatedBy: 1,
},
{
name: 'name 2',
description: 'description 2',
startDate: '2018-05-12T00:00:00.000Z',
endDate: '2018-05-13T00:00:00.000Z',
reference: 'phase',
referenceId: 1,
createdBy: 1,
updatedBy: 1,
},
{
name: 'name 3',
description: 'description 3',
startDate: '2018-05-13T00:00:00.000Z',
endDate: '2018-05-14T00:00:00.000Z',
reference: 'phase',
referenceId: 1,
createdBy: 1,
updatedBy: 1,
deletedAt: '2018-05-14T00:00:00.000Z',
},
];
const milestones = [
{
id: 1,
Expand Down Expand Up @@ -143,41 +181,37 @@ describe('GET timeline', () => {
]))
.then(() =>
// Create timelines
models.Timeline.bulkCreate([
{
name: 'name 1',
description: 'description 1',
startDate: '2018-05-11T00:00:00.000Z',
endDate: '2018-05-12T00:00:00.000Z',
reference: 'project',
referenceId: 1,
createdBy: 1,
updatedBy: 1,
},
{
name: 'name 2',
description: 'description 2',
startDate: '2018-05-12T00:00:00.000Z',
endDate: '2018-05-13T00:00:00.000Z',
reference: 'phase',
referenceId: 1,
createdBy: 1,
updatedBy: 1,
},
{
name: 'name 3',
description: 'description 3',
startDate: '2018-05-13T00:00:00.000Z',
endDate: '2018-05-14T00:00:00.000Z',
reference: 'phase',
referenceId: 1,
createdBy: 1,
updatedBy: 1,
deletedAt: '2018-05-14T00:00:00.000Z',
},
]))
.then(() => models.Milestone.bulkCreate(milestones))
.then(() => done());
// Create timelines
models.Timeline.bulkCreate(timelines, { returning: true })
.then(createdTimelines => (
// create milestones after timelines
models.Milestone.bulkCreate(milestones))
.then(createdMilestones => [createdTimelines, createdMilestones]),
),
).then(([createdTimelines, createdMilestones]) =>
// Index to ES
Promise.all(_.map(createdTimelines, async (createdTimeline) => {
const timelineJson = _.omit(createdTimeline.toJSON(), 'deletedAt', 'deletedBy');
timelineJson.projectId = createdTimeline.id !== 3 ? 1 : 2;
if (timelineJson.id === 1) {
timelineJson.milestones = _.map(
createdMilestones,
cm => _.omit(cm.toJSON(), 'deletedAt', 'deletedBy'),
);
} else if (timelineJson.id === 2) {
timelineJson.description = 'from ES';
}

await server.services.es.index({
index: ES_TIMELINE_INDEX,
type: ES_TIMELINE_TYPE,
id: timelineJson.id,
body: timelineJson,
});
}))
.then(() => {
done();
}));
});
});
});
Expand Down Expand Up @@ -316,5 +350,53 @@ describe('GET timeline', () => {
})
.expect(200, done);
});

it('should return data from ES when db param is not set', (done) => {
request(server)
.get('/v5/timelines/2')
.set({
Authorization: `Bearer ${testUtil.jwts.admin}`,
})
.expect(200)
.end((err, res) => {
const resJson = res.body;
resJson.id.should.be.eql(2);
resJson.name.should.be.eql('name 2');
resJson.description.should.be.eql('from ES');

resJson.startDate.should.be.eql('2018-05-12T00:00:00.000Z');
resJson.endDate.should.be.eql('2018-05-13T00:00:00.000Z');
resJson.reference.should.be.eql('phase');
resJson.referenceId.should.be.eql(1);

resJson.createdBy.should.be.eql(1);
should.exist(resJson.createdAt);
resJson.updatedBy.should.be.eql(1);
should.exist(resJson.updatedAt);
should.not.exist(resJson.deletedBy);
should.not.exist(resJson.deletedAt);

should.not.exist(resJson.milestones);

done();
});
});

it('should return data from DB without calling ES when db param is set', (done) => {
request(server)
.get('/v5/timelines/2?db=true')
.set({
Authorization: `Bearer ${testUtil.jwts.admin}`,
})
.expect(200)
.end((err, res) => {
const resJson = res.body;
resJson.id.should.be.eql(2);
resJson.name.should.be.eql('name 2');
resJson.description.should.be.eql('description 2');

done();
});
});
});
});