Skip to content

Commit 1a2f306

Browse files
committed
Moved merging to api
1 parent 81dcb5f commit 1a2f306

5 files changed

Lines changed: 180 additions & 10 deletions

File tree

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
"devDependencies": {
2222
"@shelf/jest-mongodb": "^1.2.2",
2323
"@types/jest": "^26.0.8",
24+
"@types/lodash.clonedeep": "^4.5.9",
25+
"@types/lodash.mergewith": "^4.6.9",
2426
"eslint": "^6.7.2",
2527
"eslint-config-codex": "1.2.4",
2628
"eslint-plugin-import": "^2.19.1",
@@ -38,6 +40,7 @@
3840
"@graphql-tools/utils": "^8.9.0",
3941
"@hawk.so/nodejs": "^3.1.1",
4042
"@hawk.so/types": "^0.1.31",
43+
"@n1ru4l/json-patch-plus": "^0.2.0",
4144
"@types/amqp-connection-manager": "^2.0.4",
4245
"@types/bson": "^4.0.5",
4346
"@types/debug": "^4.1.5",
@@ -70,6 +73,8 @@
7073
"graphql-upload": "^13",
7174
"jsonwebtoken": "^8.5.1",
7275
"lodash": "^4.17.15",
76+
"lodash.clonedeep": "^4.5.0",
77+
"lodash.mergewith": "^4.6.2",
7378
"migrate-mongo": "^7.0.1",
7479
"mime-types": "^2.1.25",
7580
"mongodb": "^3.7.3",

src/models/eventsFactory.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { getMidnightWithTimezoneOffset, getUTCMidnight } from '../utils/dates';
2+
import { composeFullRepetitionEvent } from '../utils/merge';
23
import { groupBy } from '../utils/grouper';
34
import safe from 'safe-regex';
45

@@ -422,6 +423,19 @@ class EventsFactory extends Factory {
422423
.skip(skip)
423424
.toArray();
424425

426+
console.log('repetitions', repetitions);
427+
428+
console.log('eventOriginal', eventOriginal);
429+
430+
431+
repetitions.forEach(repetition => {
432+
repetition.payload = composeFullRepetitionEvent(eventOriginal, repetition).payload;
433+
console.log(repetition);
434+
if ('delta' in repetition) {
435+
delete repetition.delta;
436+
}
437+
});
438+
425439
const isLastPortion = repetitions.length < limit && skip === 0;
426440

427441
/**
@@ -455,10 +469,30 @@ class EventsFactory extends Factory {
455469
* @todo move to Repetitions(?) model
456470
*/
457471
async getEventRepetition(repetitionId) {
458-
return this.getCollection(this.TYPES.REPETITIONS)
472+
const repetition = await this.getCollection(this.TYPES.REPETITIONS)
459473
.findOne({
460474
_id: ObjectID(repetitionId),
461475
});
476+
477+
if (!repetition) {
478+
return null;
479+
}
480+
481+
const event = await this.findOneByQuery({
482+
groupHash: repetition.groupHash,
483+
});
484+
485+
if (!event) {
486+
return null;
487+
}
488+
489+
repetition.payload = composeFullRepetitionEvent(event, repetition).payload;
490+
491+
if ('delta' in repetition) {
492+
delete repetition.delta;
493+
}
494+
495+
return repetition;
462496
}
463497

464498
/**
@@ -469,10 +503,6 @@ class EventsFactory extends Factory {
469503
async getEventLastRepetition(eventId) {
470504
const repetitions = await this.getEventRepetitions(eventId, 1);
471505

472-
if (repetitions.length === 0) {
473-
return null;
474-
}
475-
476506
return repetitions.shift();
477507
}
478508

src/typeDefs/event.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,6 @@ type Repetition {
255255
"""
256256
payload: RepetitionPayload
257257
258-
"""
259-
Delta of the event's payload, stringified JSON
260-
"""
261-
delta: String
262-
263258
"""
264259
Event timestamp
265260
"""

src/utils/merge.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import mergeWith from 'lodash.mergewith';
2+
import cloneDeep from 'lodash.clonedeep';
3+
import { patch } from '@n1ru4l/json-patch-plus';
4+
5+
type HawkEvent = {
6+
payload: {
7+
[key: string]: any
8+
}
9+
}
10+
11+
type HawkEventRepetition = {
12+
payload: {
13+
[key: string]: any
14+
}
15+
delta: string;
16+
}
17+
18+
/**
19+
* One of the features of the events is that their repetition is the difference
20+
* between the original, which greatly optimizes storage. So we need to restore
21+
* the original repetition payload using the very first event and its difference
22+
* between its repetition
23+
*
24+
* @param originalEvent - the very first event we received
25+
* @param repetition - the difference with its repetition, for the repetition we want to display
26+
* @returns fully assembled payload of the current repetition
27+
*/
28+
export function repetitionAssembler(originalEvent: Object, repetition: { [key: string]: any }): any {
29+
const customizer = (originalParam: any, repetitionParam: any): any => {
30+
if (repetitionParam === null) {
31+
return originalParam;
32+
}
33+
34+
35+
if (typeof repetitionParam === 'object' && typeof originalParam === 'object') {
36+
/**
37+
* If original event has null but repetition has some value, we need to return repetition value
38+
*/
39+
if (originalParam === null) {
40+
return repetitionParam;
41+
/**
42+
* Otherwise, we need to recursively merge original and repetition values
43+
*/
44+
} else {
45+
return repetitionAssembler(originalParam, repetitionParam);
46+
}
47+
}
48+
49+
return repetitionParam;
50+
};
51+
52+
return mergeWith(cloneDeep(originalEvent), cloneDeep(repetition), customizer);
53+
}
54+
55+
56+
/**
57+
* Helps to merge original event and repetition due to delta format,
58+
* in case of old delta format, we need to patch the payload
59+
* in case of new delta format, we need to assemble the payload
60+
*
61+
* @param originalEvent {HawkEvent} - The original event
62+
* @param repetition {HawkEventRepetition} - The repetition to process
63+
* @returns {HawkEvent} Updated event with processed repetition payload
64+
*/
65+
export function composeFullRepetitionEvent(originalEvent: HawkEvent, repetition: HawkEventRepetition | undefined): HawkEvent {
66+
67+
console.log('originalEvent', originalEvent);
68+
console.log('repetition', repetition);
69+
70+
/**
71+
* Make a deep copy of the original event, because we need to avoid mutating the original event
72+
*/
73+
const event = cloneDeep(originalEvent);
74+
75+
if (!repetition) {
76+
return event;
77+
}
78+
79+
/**
80+
* New delta format (repetition.delta is not null)
81+
*/
82+
if (repetition.delta) {
83+
event.payload = patch({
84+
left: event.payload,
85+
delta: JSON.parse(repetition.delta)
86+
});
87+
88+
return event;
89+
}
90+
91+
/**
92+
* New delta format (repetition.payload is null) and repetition.delta is null (there is no delta between original and repetition)
93+
*/
94+
if (!repetition.payload) {
95+
return event;
96+
}
97+
98+
/**
99+
* Old delta format (repetition.payload is not null)
100+
* @todo remove after July 5 2025
101+
*/
102+
event.payload = repetitionAssembler(event.payload, repetition.payload);
103+
104+
return event;
105+
}
106+

yarn.lock

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,11 @@
720720
semver "^7.3.5"
721721
tar "^6.1.11"
722722

723+
"@n1ru4l/json-patch-plus@^0.2.0":
724+
version "0.2.0"
725+
resolved "https://registry.yarnpkg.com/@n1ru4l/json-patch-plus/-/json-patch-plus-0.2.0.tgz#b8fa09fd980c3460dfdc109a7c4cc5590157aa6b"
726+
integrity sha512-pLkJy83/rVfDTyQgDSC8GeXAHEdXNHGNJrB1b7wAyGQu0iv7tpMXntKVSqj0+XKNVQbco40SZffNfVALzIt0SQ==
727+
723728
"@phc/format@^1.0.0":
724729
version "1.0.0"
725730
resolved "https://registry.yarnpkg.com/@phc/format/-/format-1.0.0.tgz#b5627003b3216dc4362125b13f48a4daa76680e4"
@@ -1077,6 +1082,25 @@
10771082
"@types/koa-compose" "*"
10781083
"@types/node" "*"
10791084

1085+
"@types/lodash.clonedeep@^4.5.9":
1086+
version "4.5.9"
1087+
resolved "https://registry.yarnpkg.com/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.9.tgz#ea48276c7cc18d080e00bb56cf965bcceb3f0fc1"
1088+
integrity sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==
1089+
dependencies:
1090+
"@types/lodash" "*"
1091+
1092+
"@types/lodash.mergewith@^4.6.9":
1093+
version "4.6.9"
1094+
resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.9.tgz#7093028a36de3cae4495d03b9d92c351cab1f8bf"
1095+
integrity sha512-fgkoCAOF47K7sxrQ7Mlud2TH023itugZs2bUg8h/KzT+BnZNrR2jAOmaokbLunHNnobXVWOezAeNn/lZqwxkcw==
1096+
dependencies:
1097+
"@types/lodash" "*"
1098+
1099+
"@types/lodash@*":
1100+
version "4.17.20"
1101+
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.20.tgz#1ca77361d7363432d29f5e55950d9ec1e1c6ea93"
1102+
integrity sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==
1103+
10801104
"@types/long@^4.0.0":
10811105
version "4.0.2"
10821106
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
@@ -4616,6 +4640,11 @@ lockfile@^1.0.4:
46164640
dependencies:
46174641
signal-exit "^3.0.2"
46184642

4643+
lodash.clonedeep@^4.5.0:
4644+
version "4.5.0"
4645+
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
4646+
integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
4647+
46194648
lodash.includes@^4.3.0:
46204649
version "4.3.0"
46214650
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
@@ -4646,6 +4675,11 @@ lodash.isstring@^4.0.1:
46464675
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
46474676
integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
46484677

4678+
lodash.mergewith@^4.6.2:
4679+
version "4.6.2"
4680+
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
4681+
integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
4682+
46494683
lodash.once@^4.0.0:
46504684
version "4.1.1"
46514685
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"

0 commit comments

Comments
 (0)