From 5dab189815f2447a8d29d071539ee7906102fd5f Mon Sep 17 00:00:00 2001 From: zadam Date: Tue, 3 May 2022 00:30:09 +0200 Subject: [PATCH] recovery for tree cycle errors, #2831 --- src/services/consistency_checks.js | 57 +++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 267c9fec3..dbf4b4478 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -56,41 +56,66 @@ class ConsistencyChecks { childToParents[childNoteId].push(parentNoteId); } + /** @returns {boolean} true if cycle was found and we should try again */ const checkTreeCycle = (noteId, path) => { if (noteId === 'root') { - return; - } - - if (!childToParents[noteId] || childToParents[noteId].length === 0) { - logError(`No parents found for note ${noteId}`); - - this.unrecoveredConsistencyErrors = true; - return; + return false; } for (const parentNoteId of childToParents[noteId]) { if (path.includes(parentNoteId)) { - logError(`Tree cycle detected at parent-child relationship: ${parentNoteId} - ${noteId}, whole path: ${path}`); + if (this.autoFix) { + const branch = becca.getBranchFromChildAndParent(noteId, parentNoteId); + branch.markAsDeleted('cycle-autofix'); + logFix(`Branch '${branch.branchId}' between child '${noteId}' and parent '${parentNoteId}' has been deleted since it was causing a tree cycle.`); - this.unrecoveredConsistencyErrors = true; + return true; + } + else { + logError(`Tree cycle detected at parent-child relationship: ${parentNoteId} - ${noteId}, whole path: ${path}`); + + this.unrecoveredConsistencyErrors = true; + } } else { const newPath = path.slice(); newPath.push(noteId); - checkTreeCycle(parentNoteId, newPath); + const retryNeeded = checkTreeCycle(parentNoteId, newPath); + + if (retryNeeded) { + return true; + } } } + + return false; }; const noteIds = Object.keys(childToParents); for (const noteId of noteIds) { - checkTreeCycle(noteId, []); + const retryNeeded = checkTreeCycle(noteId, []); + + if (retryNeeded) { + return true; + } } - if (childToParents['root'].length !== 1 || childToParents['root'][0] !== 'none') { - logError('Incorrect root parent: ' + JSON.stringify(childToParents['root'])); - this.unrecoveredConsistencyErrors = true; + return false; + } + + checkAndRepairTreeCycles() { + let treeFixed = false; + + while (this.checkTreeCycles()) { + // fixing cycle means deleting branches, we might need to create a new branch to recover the note + this.findExistencyIssues(); + + treeFixed = true; + } + + if (treeFixed) { + this.reloadNeeded = true; } } @@ -646,7 +671,7 @@ class ConsistencyChecks { if (!this.unrecoveredConsistencyErrors) { // we run this only if basic checks passed since this assumes basic data consistency - this.checkTreeCycles(); + this.checkAndRepairTreeCycles(); } if (this.reloadNeeded) {