Skip to content
This repository has been archived by the owner on Oct 25, 2021. It is now read-only.

Commit

Permalink
send details of deprecated properties in events
Browse files Browse the repository at this point in the history
  • Loading branch information
wheresrhys committed Dec 4, 2019
1 parent d730b51 commit 52b8437
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 102 deletions.
3 changes: 3 additions & 0 deletions api/__tests__/v2/merge.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ describe('merge', () => {

const testMergeRequest = (payload, ...expectations) => {
expectations[0] = expectations[0] || 200;
if (expectations[1] && expectations[1].children) {
expectations[1].deprecatedChildren = expectations[1].children;
}
return sandbox
.request(app)
.post(
Expand Down
4 changes: 3 additions & 1 deletion api/__tests__/v2/node-patch.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ describe('v2 - node PATCH', () => {
if (data) {
req = req.send(data);
}

if (expectations[1] && expectations[1].children) {
expectations[1].deprecatedChildren = expectations[1].children;
}
return req.expect(...expectations);
};

Expand Down
8 changes: 6 additions & 2 deletions api/__tests__/v2/node-post.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@ describe('v2 - node POST', () => {
beforeAll(async () => {
app = await createApp();
});
const testPostRequest = (url, data, ...expectations) =>
sandbox
const testPostRequest = (url, data, ...expectations) => {
if (expectations[1] && expectations[1].children) {
expectations[1].deprecatedChildren = expectations[1].children;
}
return sandbox
.request(app)
.post(url)
.namespacedAuth()
.send(data)
.expect(...expectations);
};

it('responds with 500 if neo4j query fails', async () => {
stubDbUnavailable(sandbox);
Expand Down
8 changes: 8 additions & 0 deletions example-schema/types/MainType.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ properties:
label: Children label
direction: outgoing
hasMany: true
deprecatedChildren:
relationship: HAS_CHILD
type: ChildType
description: Children description.
label: Children label
direction: outgoing
hasMany: true
deprecationReason: Replaced by children
parents:
relationship: IS_PARENT_OF
type: ParentType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ describe('docstore events', () => {
Promise.resolve({
VersionId: 'lalalala',
Body:
'{"someDocument": "some document2", "anotherDocument": "another document"}',
'{"someDocument": "some document", "anotherDocument": "another document"}',
}),
}));

Expand Down Expand Up @@ -336,7 +336,7 @@ describe('docstore events', () => {
promise: () =>
Promise.resolve({
VersionId: 'lalalala',
Body: '{"someDocument": "some document2"}',
Body: '{"someDocument": "some document"}',
}),
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ describe('Rest events module integration', () => {
expect(emitSpy).toHaveBeenCalledTimes(2);
expectCreateEvent(mainType, mainCode, [
'children',

'code',
'deprecatedChildren',
'someString',
]);
expectUpdateEvent(childType, childCode, ['isChildOf']);
Expand All @@ -122,6 +124,7 @@ describe('Rest events module integration', () => {
expectCreateEvent(mainType, mainCode, [
'children',
'code',
'deprecatedChildren',
'someString',
]);
expectCreateEvent(childType, childCode, ['code', 'isChildOf']);
Expand Down Expand Up @@ -168,7 +171,11 @@ describe('Rest events module integration', () => {

expect(status).toBe(200);
expect(emitSpy).toHaveBeenCalledTimes(2);
expectUpdateEvent(mainType, mainCode, ['children', 'someString']);
expectUpdateEvent(mainType, mainCode, [
'children',
'deprecatedChildren',
'someString',
]);
expectUpdateEvent(childType, childCode, ['isChildOf']);
});

Expand All @@ -186,7 +193,11 @@ describe('Rest events module integration', () => {

expect(status).toBe(200);
expect(emitSpy).toHaveBeenCalledTimes(2);
expectUpdateEvent(mainType, mainCode, ['children', 'someString']);
expectUpdateEvent(mainType, mainCode, [
'children',
'deprecatedChildren',
'someString',
]);
expectCreateEvent(childType, childCode, ['code', 'isChildOf']);
});
it('should send extra UPDATE events when disconnecting from related nodes', async () => {
Expand All @@ -208,7 +219,11 @@ describe('Rest events module integration', () => {

expect(status).toBe(200);
expect(emitSpy).toHaveBeenCalledTimes(2);
expectUpdateEvent(mainType, mainCode, ['children', 'someString']);
expectUpdateEvent(mainType, mainCode, [
'children',
'deprecatedChildren',
'someString',
]);
expectUpdateEvent(childType, childCode, ['isChildOf']);
});
});
Expand Down Expand Up @@ -277,7 +292,10 @@ describe('Rest events module integration', () => {
console.log(JSON.stringify(emitSpy.mock.calls, null, 2));
expect(emitSpy).toHaveBeenCalledTimes(3);
expectDeleteEvent(mainType, absorbedCode);
expectUpdateEvent(mainType, mainCode, ['children']);
expectUpdateEvent(mainType, mainCode, [
'children',
'deprecatedChildren',
]);
expectUpdateEvent(childType, childCode, ['isChildOf']);
});

Expand Down
25 changes: 14 additions & 11 deletions packages/tc-api-rest-handlers/lib/events/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const groupBy = require('lodash.groupby');

const schema = require('@financial-times/tc-schema-sdk');
const EventEmitter = require('events');
const {
makeAddedRelationshipEvents,
Expand All @@ -17,12 +17,16 @@ const combineSimilarEvents = events => {
({ action, code, type }) => `${action}:${code}:${type}`,
);
return Object.values(groupedEvents).map(groupedEvent => {
const updatedPropertiesList = groupedEvent.map(
const updatedPropertiesList = groupedEvent.flatMap(
event => event.updatedProperties,
);
const updatedProperties = unique([].concat(...updatedPropertiesList))
.filter(name => name && name.charAt(0) !== '_')
.sort();
const updatedProperties = unique(
unique(updatedPropertiesList)
.filter(name => name && name.charAt(0) !== '_')
.flatMap(propName =>
schema.findPropertyNames(groupedEvent[0].type, propName),
),
).sort();
// Merge to first event object
return Object.assign(groupedEvent[0], {
...(groupedEvent[0].action === 'DELETE'
Expand Down Expand Up @@ -90,12 +94,11 @@ const broadcast = changeSummaries => {
if (!Array.isArray(changeSummaries)) {
changeSummaries = [changeSummaries];
}
combineSimilarEvents([].concat(...changeSummaries.map(makeEvents))).forEach(
event =>
module.exports.emitter.emit(event.action, {
time: Math.floor(Date.now() / 1000),
...event,
}),
combineSimilarEvents(changeSummaries.flatMap(makeEvents)).forEach(event =>
module.exports.emitter.emit(event.action, {
time: Math.floor(Date.now() / 1000),
...event,
}),
);
};

Expand Down
47 changes: 9 additions & 38 deletions packages/tc-api-rest-handlers/lib/events/related-events.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,5 @@
const schema = require('@financial-times/tc-schema-sdk');

const invertDirection = direction =>
direction === 'incoming' ? 'outgoing' : 'incoming';

const findPropertyName = ({
sourceType,
destinationType,
relationship,
direction,
}) => {
const { properties: sourceProperties } = schema.getType(sourceType);
const [propName] = Object.entries(sourceProperties).find(
([, definition]) =>
definition.type === destinationType &&
definition.relationship === relationship &&
definition.direction === direction,
);
return propName;
};

const findInversePropertyName = (rootType, propName) => {
const { type, relationship, direction } = schema.getType(
rootType,
).properties[propName];

return findPropertyName({
sourceType: type,
direction: invertDirection(direction),
relationship,
destinationType: rootType,
});
};

const generateRelatedEvents = ({
rootType,
getEventType,
Expand Down Expand Up @@ -87,10 +55,13 @@ const makeAddedRelationshipEvents = (
getEventType: (type, code) =>
isCreated(type, code) ? 'CREATE' : 'UPDATE',
getUpdatedProperties: ({ rootType, propName, type, code }) => {
const updatedProperty = findInversePropertyName(rootType, propName);
const updatedProperties = schema.findInversePropertyNames(
rootType,
propName,
);
return isCreated(type, code)
? ['code', updatedProperty].sort()
: [updatedProperty];
? updatedProperties.concat(['code']).sort()
: updatedProperties;
},
relationships: addedRelationships,
});
Expand All @@ -100,9 +71,9 @@ const makeRemovedRelationshipEvents = (nodeType, removedRelationships = {}) =>
generateRelatedEvents({
rootType: nodeType,
getEventType: () => 'UPDATE',
getUpdatedProperties: ({ rootType, propName }) => [
findInversePropertyName(rootType, propName),
],
getUpdatedProperties: ({ rootType, propName }) =>
schema.findInversePropertyNames(rootType, propName),

relationships: removedRelationships,
});

Expand Down
5 changes: 1 addition & 4 deletions packages/tc-api-rest-handlers/lib/neo4j-model.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
const { getType } = require('@financial-times/tc-schema-sdk');
const { getType, invertDirection } = require('@financial-times/tc-schema-sdk');
const {
executeQuery,
executeQueriesWithTransaction,
} = require('@financial-times/tc-api-db-manager');
const { convertNeo4jToJson } = require('./neo4j-type-conversion');

const invertDirection = direction =>
direction === 'incoming' ? 'outgoing' : 'incoming';

const getDirection = (record, node) =>
record.get('relationship').start === node.identity
? 'outgoing'
Expand Down
38 changes: 0 additions & 38 deletions packages/tc-api-rest-handlers/lib/relationships/properties.js

This file was deleted.

6 changes: 4 additions & 2 deletions packages/tc-api-rest-handlers/lib/relationships/write.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
const httpErrors = require('http-errors');
const { stripIndents } = require('common-tags');
const { getType } = require('@financial-times/tc-schema-sdk');
const {
getType,
findInversePropertyNames,
} = require('@financial-times/tc-schema-sdk');
const { metaPropertiesForCreate } = require('../metadata-helpers');
const { findInversePropertyNames } = require('./properties');

const relationshipFragment = (
type,
Expand Down
55 changes: 55 additions & 0 deletions packages/tc-schema-sdk/lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const invertDirection = direction =>
direction === 'incoming' ? 'outgoing' : 'incoming';

const findPropertyNamesFromPropertyDef = function({
rootType,
direction,
relationship,
destinationType,
}) {
return Object.entries(this.getType(rootType).properties)
.filter(
([, def]) =>
def.type === destinationType &&
def.relationship === relationship &&
def.direction === direction,
)
.map(([propName]) => propName)
.sort();
};

const findInversePropertyNames = function(rootType, propName) {
const { type, relationship, direction } = this.getType(rootType).properties[
propName
];
return this.findPropertyNamesFromPropertyDef({
rootType: type,
direction: invertDirection(direction),
relationship,
destinationType: rootType,
});
};

const findPropertyNames = function(rootType, propName) {
const { type, relationship, direction } = this.getType(rootType).properties[
propName
];

if (!relationship) {
return [propName];
}

return this.findPropertyNamesFromPropertyDef({
rootType,
direction,
relationship,
destinationType: type,
});
};

module.exports = {
invertDirection,
findPropertyNames,
findInversePropertyNames,
findPropertyNamesFromPropertyDef,
};
5 changes: 5 additions & 0 deletions packages/tc-schema-sdk/sdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const stringValidator = require('./data-accessors/string-validator');
const enums = require('./data-accessors/enums');
const types = require('./data-accessors/types');
const { SchemaUpdater } = require('./lib/updater');
const utils = require('./lib/utils');

class SDK {
constructor(options = {}) {
Expand All @@ -25,6 +26,10 @@ class SDK {
this.ready = this.ready.bind(this);
this.onChange = this.onChange.bind(this);

Object.entries(utils).forEach(([name, method]) => {
this[name] = method.bind(this);
});

if (options.init !== false) {
this.init(options);
}
Expand Down

0 comments on commit 52b8437

Please sign in to comment.