2017-11-09 20:52:47 -05:00
|
|
|
const sql = require('./sql');
|
2021-02-11 22:50:32 +01:00
|
|
|
const log = require('./log');
|
2021-06-29 22:15:57 +02:00
|
|
|
const entityChangesService = require('./entity_changes');
|
2019-01-03 23:27:10 +01:00
|
|
|
const eventService = require('./events');
|
2021-06-29 22:15:57 +02:00
|
|
|
const entityConstructor = require("../becca/entity_constructor");
|
2017-11-09 20:52:47 -05:00
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
function updateEntity(remoteEC, remoteEntityRow, instanceId) {
|
|
|
|
if (!remoteEntityRow && remoteEC.entityName === 'options') {
|
|
|
|
return; // can be undefined for options with isSynced=false
|
2020-03-08 21:59:19 +01:00
|
|
|
}
|
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
const updated = remoteEC.entityName === 'note_reordering'
|
|
|
|
? updateNoteReordering(remoteEC, remoteEntityRow, instanceId)
|
|
|
|
: updateNormalEntity(remoteEC, remoteEntityRow, instanceId);
|
2019-01-03 23:27:10 +01:00
|
|
|
|
2021-07-22 20:19:44 +02:00
|
|
|
if (updated) {
|
2023-07-29 21:59:20 +02:00
|
|
|
if (remoteEntityRow?.isDeleted) {
|
2021-05-01 11:38:20 +02:00
|
|
|
eventService.emit(eventService.ENTITY_DELETE_SYNCED, {
|
2023-07-29 21:59:20 +02:00
|
|
|
entityName: remoteEC.entityName,
|
|
|
|
entityId: remoteEC.entityId
|
2021-05-01 11:38:20 +02:00
|
|
|
});
|
|
|
|
}
|
2023-07-29 21:59:20 +02:00
|
|
|
else if (!remoteEC.isErased) {
|
2021-05-01 11:38:20 +02:00
|
|
|
eventService.emit(eventService.ENTITY_CHANGE_SYNCED, {
|
2023-07-29 21:59:20 +02:00
|
|
|
entityName: remoteEC.entityName,
|
|
|
|
entityRow: remoteEntityRow
|
2021-05-01 11:38:20 +02:00
|
|
|
});
|
|
|
|
}
|
2019-01-03 23:27:10 +01:00
|
|
|
}
|
2018-04-07 22:25:28 -04:00
|
|
|
}
|
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
function updateNormalEntity(remoteEC, remoteEntityRow, instanceId) {
|
|
|
|
const localEC = sql.getRow(`SELECT * FROM entity_changes WHERE entityName = ? AND entityId = ?`, [remoteEC.entityName, remoteEC.entityId]);
|
2020-12-14 13:58:02 +01:00
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
if (!localEC?.isErased && remoteEC.isErased) {
|
|
|
|
eraseEntity(remoteEC, instanceId);
|
2020-12-14 13:58:02 +01:00
|
|
|
|
|
|
|
return true;
|
2023-07-29 21:59:20 +02:00
|
|
|
} else if (localEC?.isErased && !remoteEC.isErased) {
|
|
|
|
// on this side, we can't unerase the entity, so force the entity to be erased on the other side.
|
2023-07-29 23:25:02 +02:00
|
|
|
entityChangesService.putEntityChangeForOtherInstances(localEC);
|
2023-07-29 21:59:20 +02:00
|
|
|
|
2023-08-31 00:14:35 +02:00
|
|
|
return false;
|
|
|
|
} else if (localEC?.isErased && remoteEC.isErased) {
|
2023-07-29 21:59:20 +02:00
|
|
|
return false;
|
2020-12-14 13:58:02 +01:00
|
|
|
}
|
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
if (!localEC
|
|
|
|
|| localEC.utcDateChanged < remoteEC.utcDateChanged
|
|
|
|
|| (localEC.utcDateChanged === remoteEC.utcDateChanged && localEC.hash !== remoteEC.hash) // sync error, we should still update
|
2020-12-14 13:15:32 +01:00
|
|
|
) {
|
2023-07-29 21:59:20 +02:00
|
|
|
if (remoteEC.entityName === 'blobs' && remoteEntityRow.content !== null) {
|
2023-07-27 23:22:08 +02:00
|
|
|
// we always use a Buffer object which is different from normal saving - there we use a simple string type for
|
|
|
|
// "string notes". The problem is that in general, it's not possible to detect whether a blob content
|
|
|
|
// is string note or note (syncs can arrive out of order)
|
2023-07-29 21:59:20 +02:00
|
|
|
remoteEntityRow.content = Buffer.from(remoteEntityRow.content, 'base64');
|
2023-07-27 23:22:08 +02:00
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
if (remoteEntityRow.content.byteLength === 0) {
|
2023-07-27 23:22:08 +02:00
|
|
|
// there seems to be a bug which causes empty buffer to be stored as NULL which is then picked up as inconsistency
|
2023-07-29 21:59:20 +02:00
|
|
|
// (possibly not a problem anymore with the newer better-sqlite3)
|
2023-07-27 23:22:08 +02:00
|
|
|
remoteEntityRow.content = "";
|
|
|
|
}
|
2017-11-28 17:04:47 -05:00
|
|
|
}
|
2019-11-01 20:00:56 +01:00
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
sql.replace(remoteEC.entityName, remoteEntityRow);
|
2019-11-01 20:00:56 +01:00
|
|
|
|
2023-07-29 23:25:02 +02:00
|
|
|
entityChangesService.putEntityChangeWithInstanceId(remoteEC, instanceId);
|
2019-11-01 20:00:56 +01:00
|
|
|
|
2020-04-04 14:57:19 +02:00
|
|
|
return true;
|
2023-07-29 21:59:20 +02:00
|
|
|
} else if (localEC.hash !== remoteEC.hash && localEC.utcDateChanged > remoteEC.utcDateChanged) {
|
|
|
|
// the change on our side is newer than on the other side, so the other side should update
|
2023-07-29 23:25:02 +02:00
|
|
|
entityChangesService.putEntityChangeForOtherInstances(localEC);
|
2023-07-29 21:59:20 +02:00
|
|
|
|
|
|
|
return false;
|
2020-04-04 14:57:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2019-11-01 20:00:56 +01:00
|
|
|
}
|
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
function updateNoteReordering(remoteEC, remoteEntityRow, instanceId) {
|
|
|
|
for (const key in remoteEntityRow) {
|
|
|
|
sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", [remoteEntityRow[key], key]);
|
|
|
|
}
|
2017-11-09 20:52:47 -05:00
|
|
|
|
2023-07-29 23:25:02 +02:00
|
|
|
entityChangesService.putEntityChangeWithInstanceId(remoteEC, instanceId);
|
2020-04-04 14:57:19 +02:00
|
|
|
|
|
|
|
return true;
|
2017-11-09 20:52:47 -05:00
|
|
|
}
|
|
|
|
|
2022-01-09 21:25:15 +01:00
|
|
|
function eraseEntity(entityChange, instanceId) {
|
2021-11-12 21:19:23 +01:00
|
|
|
const {entityName, entityId} = entityChange;
|
|
|
|
|
2023-01-22 23:36:05 +01:00
|
|
|
const entityNames = [
|
|
|
|
"notes",
|
|
|
|
"branches",
|
|
|
|
"attributes",
|
2023-06-04 23:01:40 +02:00
|
|
|
"revisions",
|
2023-03-16 12:17:55 +01:00
|
|
|
"attachments",
|
2023-07-29 21:59:20 +02:00
|
|
|
"blobs"
|
2023-01-22 23:36:05 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
if (!entityNames.includes(entityName)) {
|
2023-07-29 21:59:20 +02:00
|
|
|
log.error(`Cannot erase entity '${entityName}', id '${entityId}'.`);
|
2021-11-12 21:19:23 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
const primaryKeyName = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName;
|
2021-11-12 21:19:23 +01:00
|
|
|
|
2023-07-29 21:59:20 +02:00
|
|
|
sql.execute(`DELETE FROM ${entityName} WHERE ${primaryKeyName} = ?`, [entityId]);
|
2021-11-12 21:19:23 +01:00
|
|
|
|
2023-07-29 23:25:02 +02:00
|
|
|
entityChangesService.putEntityChangeWithInstanceId(entityChange, instanceId);
|
2021-11-12 21:19:23 +01:00
|
|
|
}
|
|
|
|
|
2017-11-09 20:52:47 -05:00
|
|
|
module.exports = {
|
2018-04-07 22:32:46 -04:00
|
|
|
updateEntity
|
2020-06-20 12:31:38 +02:00
|
|
|
};
|