Skip to content

Commit a0a12de

Browse files
committed
send ACTIVATE/PAUSED events to BUS API on milestones pause/resume (with unit tests)
1 parent 74d5a0d commit a0a12de

File tree

7 files changed

+147
-18
lines changed

7 files changed

+147
-18
lines changed

src/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export const EVENT = {
7474
MILESTONE_ADDED: 'milestone.added',
7575
MILESTONE_UPDATED: 'milestone.updated',
7676
MILESTONE_REMOVED: 'milestone.removed',
77+
MILESTONE_PAUSED: 'milestone.paused',
78+
MILESTONE_RESUMED: 'milestone.resumed',
7779

7880
PROJECT_MEMBER_INVITE_CREATED: 'project.member.invite.created',
7981
PROJECT_MEMBER_INVITE_UPDATED: 'project.member.invite.updated',

src/events/busApi.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,8 @@ module.exports = (app, logger) => {
529529
event = BUS_API_EVENT.MILESTONE_TRANSITION_COMPLETED;
530530
} else if (updated.status === MILESTONE_STATUS.ACTIVE) {
531531
event = BUS_API_EVENT.MILESTONE_TRANSITION_ACTIVE;
532+
} else if (updated.status === MILESTONE_STATUS.PAUSED) {
533+
event = BUS_API_EVENT.MILESTONE_TRANSITION_PAUSED;
532534
}
533535

534536
if (event) {
@@ -592,12 +594,24 @@ module.exports = (app, logger) => {
592594
.catch(err => null); // eslint-disable-line no-unused-vars
593595
});
594596

595-
/**
597+
/**
596598
* MILESTONE_UPDATED.
597599
*/
598-
// eslint-disable-next-line no-unused-vars
599-
app.on(EVENT.ROUTING_KEY.MILESTONE_UPDATED, ({ req, original, updated, cascadedUpdates }) => {
600-
logger.debug(`receive MILESTONE_UPDATED event for milestone ${original.id}`);
600+
601+
/**
602+
* Handlers for updated milestones which sends events to Kafka
603+
*
604+
* @param {String} eventName event name which causes calling this method
605+
* @param {Object} params params
606+
* @param {Object} params.req request object
607+
* @param {Object} params.original original milestone object
608+
* @param {Object} params.updated updated milestone object
609+
* @param {Object} params.cascadedUpdates milestones updated cascaded
610+
*
611+
* @return {undefined}
612+
*/
613+
function handleMilestoneUpdated(eventName, { req, original, updated, cascadedUpdates }) {
614+
logger.debug(`receive ${eventName} event for milestone ${original.id}`);
601615

602616
const projectId = _.parseInt(req.params.projectId);
603617
const timeline = _.omit(req.timeline.toJSON(), 'deletedAt', 'deletedBy');
@@ -640,7 +654,11 @@ module.exports = (app, logger) => {
640654
}
641655
});
642656
}).catch(err => null); // eslint-disable-line no-unused-vars
643-
});
657+
}
658+
659+
app.on(EVENT.ROUTING_KEY.MILESTONE_UPDATED, handleMilestoneUpdated.bind(null, EVENT.ROUTING_KEY.MILESTONE_UPDATED));
660+
app.on(EVENT.ROUTING_KEY.MILESTONE_PAUSED, handleMilestoneUpdated.bind(null, EVENT.ROUTING_KEY.MILESTONE_PAUSED));
661+
app.on(EVENT.ROUTING_KEY.MILESTONE_RESUMED, handleMilestoneUpdated.bind(null, EVENT.ROUTING_KEY.MILESTONE_RESUMED));
644662

645663
/**
646664
* MILESTONE_REMOVED.

src/routes/milestones/status.pause.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Joi from 'joi';
44
import { middleware as tcMiddleware } from 'tc-core-library-js';
55
import util from '../../util';
66
import validateTimeline from '../../middlewares/validateTimeline';
7-
import { MILESTONE_STATUS, BUS_API_EVENT } from '../../constants';
7+
import { MILESTONE_STATUS, EVENT } from '../../constants';
88
import models from '../../models';
99

1010
const permissions = tcMiddleware.permissions;
@@ -74,12 +74,12 @@ module.exports = [
7474
.then(() => {
7575
// Send event to bus
7676
req.log.debug('Sending event to RabbitMQ bus for milestone %d', updated.id);
77-
req.app.services.pubsub.publish(BUS_API_EVENT.MILESTONE_TRANSITION_PAUSED,
77+
req.app.services.pubsub.publish(EVENT.ROUTING_KEY.MILESTONE_PAUSED,
7878
{ original, updated },
7979
{ correlationId: req.id },
8080
);
8181

82-
req.app.emit(BUS_API_EVENT.MILESTONE_TRANSITION_PAUSED,
82+
req.app.emit(EVENT.ROUTING_KEY.MILESTONE_PAUSED,
8383
{ req, original, updated });
8484

8585
res.json(util.wrapResponse(req.id));

src/routes/milestones/status.pause.spec.js

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
import chai from 'chai';
66
import _ from 'lodash';
77
import request from 'supertest';
8+
import sinon from 'sinon';
89
import models from '../../models';
910
import server from '../../app';
1011
import testUtil from '../../tests/util';
12+
import busApi from '../../services/busApi';
13+
import { BUS_API_EVENT } from '../../constants';
1114

1215
chai.should();
1316

14-
describe('Status Pause Milestone', () => {
17+
describe('PAUSE Milestone', () => {
1518
beforeEach((done) => {
1619
testUtil.clearDb()
1720
.then(() => {
@@ -254,6 +257,7 @@ describe('Status Pause Milestone', () => {
254257
});
255258

256259
after(testUtil.clearDb);
260+
257261
describe('PATCH /timelines/{timelineId}/milestones/{milestoneId}/status/pause', () => {
258262
const body = {
259263
param: {
@@ -368,8 +372,7 @@ describe('Status Pause Milestone', () => {
368372
});
369373
});
370374

371-
it('should have one status history created with multiple sequencial status paused messages', function fn(done) {
372-
this.timeout(10000);
375+
it('should have one status history created with multiple sequential status paused messages', (done) => {
373376
request(server)
374377
.patch('/v4/timelines/1/milestones/1/status/pause')
375378
.set({
@@ -390,5 +393,57 @@ describe('Status Pause Milestone', () => {
390393
});
391394
});
392395
});
396+
397+
describe('Bus api', () => {
398+
let createEventSpy;
399+
const sandbox = sinon.sandbox.create();
400+
401+
before((done) => {
402+
// Wait for 500ms in order to wait for createEvent calls from previous tests to complete
403+
testUtil.wait(done);
404+
});
405+
406+
beforeEach(() => {
407+
createEventSpy = sandbox.spy(busApi, 'createEvent');
408+
});
409+
410+
afterEach(() => {
411+
sandbox.restore();
412+
});
413+
414+
it('should send messages MILESTONE_UPDATED and MILESTONE_TRANSITION_PAUSED', (done) => {
415+
request(server)
416+
.patch('/v4/timelines/1/milestones/1/status/pause')
417+
.set({
418+
Authorization: `Bearer ${testUtil.jwts.admin}`,
419+
})
420+
.send(body)
421+
.expect(200)
422+
.end((err) => {
423+
if (err) {
424+
done(err);
425+
} else {
426+
testUtil.wait(() => {
427+
createEventSpy.calledTwice.should.be.true;
428+
createEventSpy.firstCall.calledWith(BUS_API_EVENT.MILESTONE_UPDATED, sinon.match({
429+
projectId: 1,
430+
projectName: 'test1',
431+
projectUrl: 'https://local.topcoder-dev.com/projects/1',
432+
userId: 40051333,
433+
initiatorUserId: 40051333,
434+
})).should.be.true;
435+
createEventSpy.secondCall.calledWith(BUS_API_EVENT.MILESTONE_TRANSITION_PAUSED, sinon.match({
436+
projectId: 1,
437+
projectName: 'test1',
438+
projectUrl: 'https://local.topcoder-dev.com/projects/1',
439+
userId: 40051333,
440+
initiatorUserId: 40051333,
441+
})).should.be.true;
442+
done();
443+
});
444+
}
445+
});
446+
});
447+
});
393448
});
394449
});

src/routes/milestones/status.resume.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Joi from 'joi';
44
import { middleware as tcMiddleware } from 'tc-core-library-js';
55
import util from '../../util';
66
import validateTimeline from '../../middlewares/validateTimeline';
7-
import { MILESTONE_STATUS, BUS_API_EVENT } from '../../constants';
7+
import { MILESTONE_STATUS, EVENT } from '../../constants';
88
import models from '../../models';
99

1010
const permissions = tcMiddleware.permissions;
@@ -85,12 +85,12 @@ module.exports = [
8585
.then(() => {
8686
// Send event to bus
8787
req.log.debug('Sending event to RabbitMQ bus for milestone %d', updated.id);
88-
req.app.services.pubsub.publish(BUS_API_EVENT.MILESTONE_TRANSITION_ACTIVE,
88+
req.app.services.pubsub.publish(EVENT.ROUTING_KEY.MILESTONE_RESUMED,
8989
{ original, updated },
9090
{ correlationId: req.id },
9191
);
9292

93-
req.app.emit(BUS_API_EVENT.MILESTONE_TRANSITION_ACTIVE,
93+
req.app.emit(EVENT.ROUTING_KEY.MILESTONE_RESUMED,
9494
{ req, original, updated });
9595

9696
res.json(util.wrapResponse(req.id));

src/routes/milestones/status.resume.spec.js

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
*/
55
import chai from 'chai';
66
import request from 'supertest';
7+
import sinon from 'sinon';
78
import models from '../../models';
89
import server from '../../app';
910
import testUtil from '../../tests/util';
11+
import busApi from '../../services/busApi';
12+
import { BUS_API_EVENT } from '../../constants';
1013

1114
chai.should();
1215

13-
describe('Status resume Milestone', () => {
16+
describe('RESUME Milestone', () => {
1417
beforeEach((done) => {
1518
testUtil.clearDb()
1619
.then(() => {
@@ -379,8 +382,7 @@ describe('Status resume Milestone', () => {
379382
});
380383
});
381384

382-
it('should have one status history created with multiple sequencial status resumed messages', function fn(done) {
383-
this.timeout(10000);
385+
it('should have one status history created with multiple sequential status resumed messages', (done) => {
384386
request(server)
385387
.patch('/v4/timelines/1/milestones/1/status/resume')
386388
.set({
@@ -401,5 +403,57 @@ describe('Status resume Milestone', () => {
401403
});
402404
});
403405
});
406+
407+
describe('Bus api', () => {
408+
let createEventSpy;
409+
const sandbox = sinon.sandbox.create();
410+
411+
before((done) => {
412+
// Wait for 500ms in order to wait for createEvent calls from previous tests to complete
413+
testUtil.wait(done);
414+
});
415+
416+
beforeEach(() => {
417+
createEventSpy = sandbox.spy(busApi, 'createEvent');
418+
});
419+
420+
afterEach(() => {
421+
sandbox.restore();
422+
});
423+
424+
it('should send messages MILESTONE_UPDATED and MILESTONE_TRANSITION_RESUMED', (done) => {
425+
request(server)
426+
.patch('/v4/timelines/1/milestones/1/status/resume')
427+
.set({
428+
Authorization: `Bearer ${testUtil.jwts.admin}`,
429+
})
430+
.send(body)
431+
.expect(200)
432+
.end((err) => {
433+
if (err) {
434+
done(err);
435+
} else {
436+
testUtil.wait(() => {
437+
createEventSpy.calledTwice.should.be.true;
438+
createEventSpy.firstCall.calledWith(BUS_API_EVENT.MILESTONE_UPDATED, sinon.match({
439+
projectId: 1,
440+
projectName: 'test1',
441+
projectUrl: 'https://local.topcoder-dev.com/projects/1',
442+
userId: 40051333,
443+
initiatorUserId: 40051333,
444+
})).should.be.true;
445+
createEventSpy.secondCall.calledWith(BUS_API_EVENT.MILESTONE_TRANSITION_ACTIVE, sinon.match({
446+
projectId: 1,
447+
projectName: 'test1',
448+
projectUrl: 'https://local.topcoder-dev.com/projects/1',
449+
userId: 40051333,
450+
initiatorUserId: 40051333,
451+
})).should.be.true;
452+
done();
453+
});
454+
}
455+
});
456+
});
457+
});
404458
});
405459
});

src/routes/milestones/update.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ describe('UPDATE Milestone', () => {
166166
name: 'Milestone 2',
167167
duration: 3,
168168
startDate: '2018-05-14T00:00:00.000Z',
169-
status: 'draft',
169+
status: 'reviewed',
170170
type: 'type2',
171171
order: 2,
172172
plannedText: 'plannedText 2',

0 commit comments

Comments
 (0)