Skip to content

Commit

Permalink
When an aspect’s tags change, send “delete” and “add” realtime events…
Browse files Browse the repository at this point in the history
… (instead of “update”)

so that perspectives which filter by aspect tag will get the right sample events.
  • Loading branch information
iamigo committed Dec 21, 2016
1 parent 3d106f4 commit 3b9466f
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 3 deletions.
62 changes: 59 additions & 3 deletions db/model/aspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ const assoc = {};
const timeoutLength = 10;
const timeoutRegex = /^[0-9]{1,9}[SMHDsmhd]$/;
const valueLabelLength = 10;
const sampleEventNames = {
add: 'refocus.internal.realtime.sample.add',
upd: 'refocus.internal.realtime.sample.update',
del: 'refocus.internal.realtime.sample.remove',
};

module.exports = function aspect(seq, dataTypes) {
const Aspect = seq.define('Aspect', {
Expand Down Expand Up @@ -172,6 +177,10 @@ module.exports = function aspect(seq, dataTypes) {

/**
* Recalculate sample status if any of the status ranges changed.
* If aspect tags changed, send a "delete" realtime event for all the
* samples for this aspect. (The afterUpdate hook will subsequently send
* an "add" event.) This way, perspectives which filter by aspect tags
* will get the right samples.
*
* @param {Aspect} inst - The instance being updated
* @returns {Promise}
Expand All @@ -194,12 +203,38 @@ module.exports = function aspect(seq, dataTypes) {
.catch((err) => reject(err))
);
}

if (inst.changed('tags')) {
return new seq.Promise((resolve, reject) => {
inst.getSamples()
.each((samp) => {
return common.sampleAspectAndSubjectArePublished(seq, samp)
.then((published) => {
if (published) {
return common.augmentSampleWithSubjectAspectInfo(seq, samp)
.then((s) => {
common.publishChange(s, sampleEventNames.del);
});
}

return seq.Promise.resolve(true);
});
})
.then(() => resolve(inst))
.catch(reject);
});
} // tags changed

return seq.Promise.resolve(true);
}, // hooks.beforeUpdate

/**
* If isPublished is being updated from true to false or name of
* the aspect is changed, delete any samples
* which are associated with the aspect.
* If isPublished is being updated from true to false or the name of the
* aspect is changed, delete any samples associated with the aspect.
* If aspect tags changed, send an "add" realtime event for all the
* samples for this aspect. (The beforeUpdate hook will already have
* sent a "delete" event.) This way, perspectives which filter by aspect
* tags will get the right samples.
*
* @param {Aspect} inst - The updated instance
* @returns {Promise}
Expand All @@ -217,6 +252,27 @@ module.exports = function aspect(seq, dataTypes) {
);
}

if (inst.changed('tags')) {
return new seq.Promise((resolve, reject) => {
inst.getSamples()
.each((samp) => {
return common.sampleAspectAndSubjectArePublished(seq, samp)
.then((published) => {
if (published) {
return common.augmentSampleWithSubjectAspectInfo(seq, samp)
.then((s) => {
common.publishChange(s, sampleEventNames.add);
});
}

return seq.Promise.resolve(true);
});
})
.then(() => resolve(inst))
.catch(reject);
});
} // tags changed

return seq.Promise.resolve();
}, // hooks.afterUpdate

Expand Down
75 changes: 75 additions & 0 deletions tests/db/model/aspect/tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2016, 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/db/model/aspect/tagsAndLinks.js
*/
'use strict';

const expect = require('chai').expect;
const tu = require('../../../testUtils');
const u = require('./utils');
const Aspect = tu.db.Aspect;
const Subject = tu.db.Subject;
const Sample = tu.db.Sample;

describe.only('db: aspect: tags: update', () => {
beforeEach((done) => {
Aspect.create({
isPublished: true,
name: `${tu.namePrefix}A`,
timeout: '1s',
valueType: 'NUMERIC',
criticalRange: [0, 0],
warningRange: [1, 1],
infoRange: [2, 2],
okRange: [3, 3],
tags: ['T1'],
})
.then(() => Aspect.create({
isPublished: true,
name: `${tu.namePrefix}B`,
timeout: '2m',
valueType: 'NUMERIC',
criticalRange: [0, 0],
warningRange: [1, 1],
infoRange: [2, 2],
okRange: [3, 3],
tags: ['T2'],
}))
.then(() => Subject.create({
isPublished: true,
name: `${tu.namePrefix}Subject`,
}))
.then(() => Sample.bulkUpsertByName([
{ name: `${tu.namePrefix}Subject|${tu.namePrefix}A`, value: 1 },
{ name: `${tu.namePrefix}Subject|${tu.namePrefix}B`, value: 2 },
]))
.then(() => done())
.catch(done);
});

afterEach(u.forceDelete);

it('update an aspect tag, samples have it next time they are loaded',
(done) => {
Aspect.findOne({ name: `${tu.namePrefix}A` })
.then((o) => {
o.tags = ['T3'];
return o.save();
})
.then(() => Sample.findOne({
name: `${tu.namePrefix}Subject|${tu.namePrefix}A`,
}))
.then((s) => {
expect(s.dataValues.aspect.tags).to.have.members(['T3']);
done();
})
.catch(done);
});
});

0 comments on commit 3b9466f

Please sign in to comment.