From df0411197b5a34a2c311d4d840f48e7df38ffc31 Mon Sep 17 00:00:00 2001 From: zadam Date: Fri, 12 Nov 2021 21:19:23 +0100 Subject: [PATCH] fixed syncing of erased notes, closes #2316 --- src/public/app/services/server.js | 5 +++++ src/services/consistency_checks.js | 2 +- src/services/notes.js | 16 ++++++++++++---- src/services/sync.js | 4 ++-- src/services/sync_update.js | 19 ++++++++++++++++++- 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/public/app/services/server.js b/src/public/app/services/server.js index 1a209fef8..295936d12 100644 --- a/src/public/app/services/server.js +++ b/src/public/app/services/server.js @@ -160,6 +160,11 @@ if (utils.isElectron()) { arg.body = JSON.parse(arg.body); } + if (!(arg.requestId in reqResolves)) { + // this can happen when reload happens between firing up the request and receiving the response + throw new Error(`Unknown requestId="${arg.requestId}"`); + } + reqResolves[arg.requestId]({ body: arg.body, headers: arg.headers diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 966796dc7..8f15f8188 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -705,7 +705,7 @@ sqlInit.dbReady.then(() => { setInterval(cls.wrap(runPeriodicChecks), 60 * 60 * 1000); // kickoff checks soon after startup (to not block the initial load) - setTimeout(cls.wrap(runPeriodicChecks), 10 * 1000); + setTimeout(cls.wrap(runPeriodicChecks), 4 * 1000); }); module.exports = { diff --git a/src/services/notes.js b/src/services/notes.js index d9008e270..2b889793b 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -679,10 +679,10 @@ function eraseNotes(noteIdsToErase) { } sql.executeMany(`DELETE FROM notes WHERE noteId IN (???)`, noteIdsToErase); - sql.executeMany(`UPDATE entity_changes SET isErased = 1 WHERE entityName = 'notes' AND entityId IN (???)`, noteIdsToErase); + setEntityChangesAsErased(sql.getManyRows(`SELECT * FROM entity_changes WHERE entityName = 'notes' AND entityId IN (???)`, noteIdsToErase)); sql.executeMany(`DELETE FROM note_contents WHERE noteId IN (???)`, noteIdsToErase); - sql.executeMany(`UPDATE entity_changes SET isErased = 1 WHERE entityName = 'note_contents' AND entityId IN (???)`, noteIdsToErase); + setEntityChangesAsErased(sql.getManyRows(`SELECT * FROM entity_changes WHERE entityName = 'note_contents' AND entityId IN (???)`, noteIdsToErase)); // we also need to erase all "dependent" entities of the erased notes const branchIdsToErase = sql.getManyRows(`SELECT branchId FROM branches WHERE noteId IN (???)`, noteIdsToErase) @@ -703,6 +703,14 @@ function eraseNotes(noteIdsToErase) { log.info(`Erased notes: ${JSON.stringify(noteIdsToErase)}`); } +function setEntityChangesAsErased(entityChanges) { + for (const ec of entityChanges) { + ec.isErased = true; + + entityChangesService.addEntityChange(ec); + } +} + function eraseBranches(branchIdsToErase) { if (branchIdsToErase.length === 0) { return; @@ -710,7 +718,7 @@ function eraseBranches(branchIdsToErase) { sql.executeMany(`DELETE FROM branches WHERE branchId IN (???)`, branchIdsToErase); - sql.executeMany(`UPDATE entity_changes SET isErased = 1 WHERE entityName = 'branches' AND entityId IN (???)`, branchIdsToErase); + setEntityChangesAsErased(sql.getManyRows(`SELECT * FROM entity_changes WHERE entityName = 'branches' AND entityId IN (???)`, branchIdsToErase)); } function eraseAttributes(attributeIdsToErase) { @@ -720,7 +728,7 @@ function eraseAttributes(attributeIdsToErase) { sql.executeMany(`DELETE FROM attributes WHERE attributeId IN (???)`, attributeIdsToErase); - sql.executeMany(`UPDATE entity_changes SET isErased = 1 WHERE entityName = 'attributes' AND entityId IN (???)`, attributeIdsToErase); + setEntityChangesAsErased(sql.getManyRows(`SELECT * FROM entity_changes WHERE entityName = 'attributes' AND entityId IN (???)`, attributeIdsToErase)); } function eraseDeletedEntities(eraseEntitiesAfterTimeInSeconds = null) { diff --git a/src/services/sync.js b/src/services/sync.js index 793fb2ecf..cd14cc2c0 100644 --- a/src/services/sync.js +++ b/src/services/sync.js @@ -395,8 +395,8 @@ function getOutstandingPullCount() { require("../becca/becca_loader").beccaLoaded.then(() => { setInterval(cls.wrap(sync), 60000); - // kickoff initial sync immediately - setTimeout(cls.wrap(sync), 2000); + // kickoff initial sync immediately, but should happen after initial consistency checks + setTimeout(cls.wrap(sync), 5000); // called just so ws.setLastSyncedPush() is called getLastSyncedPush(); diff --git a/src/services/sync_update.js b/src/services/sync_update.js index 908a7927c..7abc737b9 100644 --- a/src/services/sync_update.js +++ b/src/services/sync_update.js @@ -9,7 +9,7 @@ function updateEntity(entityChange, entityRow) { if (!entityRow) { if (entityChange.isSynced) { if (entityChange.isErased) { - entityChangesService.addEntityChange(entityChange, true); + eraseEntity(entityChange); } else { log.info(`Encountered synced non-erased entity change without entity: ${JSON.stringify(entityChange)}`); @@ -105,6 +105,23 @@ function handleContent(content) { return content; } +function eraseEntity(entityChange) { + const {entityName, entityId} = entityChange; + + if (!["notes", "note_contents", "branches", "attributes", "note_revisions", "note_revision_contents"].includes(entityName)) { + log.error(`Cannot erase entity ${entityName}, id ${entityId}`); + return; + } + + const keyName = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName; + + sql.execute(`DELETE FROM ${entityName} WHERE ${keyName} = ?`, [entityId]); + + eventService.emit(eventService.ENTITY_DELETE_SYNCED, { entityName, entityId }); + + entityChangesService.addEntityChange(entityChange, true); +} + module.exports = { updateEntity };