Skip to content
This repository was archived by the owner on Jul 31, 2020. It is now read-only.
Merged
46 changes: 35 additions & 11 deletions client/recordUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,25 +250,49 @@ const mergeRecord = (record1, record2) => {

/**
* Within an array of [record, object], merge items whose records have the
* same objectId.
* same objectId and same actions.
* Requirements:
* 1) should not combine CREATE when object is not null:
* [[CREATE, object], [UPDATE, object]] => [[CREATE, object], [UPDATE, object]]
* [[CREATE, null], [UPDATE, null]] => [[CREATE(2), null]]
* [[CREATE, null], [UPDATE, object]] => ??? seems impossible => [[CREATE(2), object]]
* 2) should not combine any DELETE
* 3) all of UPDATE should be combined to single update
* @param {Array} recordsAndObjects Same format as input to resolveRecords().
* @returns {Array}
*/
const mergeRecords = (recordsAndObjects) => {
const objectIdMap = {} // map of objectId to [record, object]
var mergedResult = []
recordsAndObjects.forEach((recordAndObject) => {
const record = recordAndObject[0]
const object = recordAndObject[1]
const existingObject = recordAndObject[1]
const id = JSON.stringify(record.objectId)
if (objectIdMap[id]) {
const mergedRecord = mergeRecord(objectIdMap[id][0], record)
objectIdMap[id] = [mergedRecord, object]
} else {
objectIdMap[id] = recordAndObject

if (!mergedResult.length ||
(record.action === proto.actions.CREATE && existingObject) ||
record.action === proto.actions.DELETE) {
mergedResult.push(recordAndObject)
return
}
})
// webkit does not support Object.values
return Object.keys(objectIdMap).map((key) => objectIdMap[key])

// We reach this point in 2 cases
// 1. record.action is UPDATE => should merge with UPDATE or [CREATE, null]
// 2. record.action is CREATE and existingObject is null => should merge with UPDATE or [CREATE, null]

// Go through mergedResult from last to first
for (var j = mergedResult.length - 1; j >= 0; --j) {
if (JSON.stringify(mergedResult[j][0].objectId) === id &&
// Should not merge with CREATE or DELETE, only UPDATE
(mergedResult[j][0].action === proto.actions.UPDATE ||
(mergedResult[j][0].action === proto.actions.CREATE && !mergedResult[j][1]))) {
mergedResult[j][0] = mergeRecord(mergedResult[j][0], record)
return
}
}
mergedResult.push(recordAndObject)
}) // recordsAndObjects.forEach

return mergedResult
}

/**
Expand Down
6 changes: 6 additions & 0 deletions lib/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ message SecretboxRecord {
bytes nonceRandom = 3;
}

message MetaInfo {
optional string key = 1;
optional string value = 2;
}

message SyncRecord {
enum Action {
CREATE = 0;
Expand All @@ -49,6 +54,7 @@ message SyncRecord {
repeated string fields = 6;
bool hideInToolbar = 7;
string order = 8;
repeated MetaInfo metaInfo= 9;
}
message SiteSetting {
string hostPattern = 1;
Expand Down
Loading