always autofix note_contents.content = NULL sync issue after note erasion

This commit is contained in:
zadam 2020-02-19 19:51:36 +01:00
parent 4ce4ac9584
commit ad7a55d305
4 changed files with 36 additions and 27 deletions

3
.idea/dataSources.xml generated
View File

@ -6,9 +6,6 @@
<synchronize>true</synchronize> <synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver> <jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/../trilium-data/document.db</jdbc-url> <jdbc-url>jdbc:sqlite:$PROJECT_DIR$/../trilium-data/document.db</jdbc-url>
<driver-properties>
<property name="enable_load_extension" value="true" />
</driver-properties>
</data-source> </data-source>
</component> </component>
</project> </project>

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "trilium", "name": "trilium",
"version": "0.40.2", "version": "0.40.3",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -323,14 +323,25 @@ class ConsistencyChecks {
WHERE isErased = 1 WHERE isErased = 1
AND content IS NOT NULL`, AND content IS NOT NULL`,
async ({noteId}) => { async ({noteId}) => {
if (this.autoFix) {
await sql.execute(`UPDATE note_contents SET content = NULL WHERE noteId = ?`, [noteId]);
logFix(`Note ${noteId} content has been set to null since the note is erased`); // we always fix this issue because there does not seem to be a good way to prevent it.
} // Scenario in which this can happen:
else { // 1. user on instance A deletes the note (sync for notes is created, but not for note_contents) and is later erased
logError(`Note ${noteId} content is not null even though the note is erased`); // 2. instance B gets synced from instance A, note is updated because of sync row for notes,
} // but note_contents is not because erasion does not create sync rows
// 3. therefore note.isErased = true, but note_contents.content remains not updated and not erased.
//
// Considered solutions:
// - don't sync erased notes - this might prevent syncing also of the isDeleted flag and note would continue
// to exist on the other instance
// - create sync rows for erased event - this would be a problem for undeletion since erasion might happen
// on one instance after undelete and thus would win even though there's no user action behind it
//
// So instead we just fix such cases afterwards here.
await sql.execute(`UPDATE note_contents SET content = NULL WHERE noteId = ?`, [noteId]);
logFix(`Note ${noteId} content has been set to null since the note is erased`);
}); });
await this.findAndFixIssues(` await this.findAndFixIssues(`
@ -547,23 +558,23 @@ class ConsistencyChecks {
}); });
await this.findAndFixIssues(` await this.findAndFixIssues(`
SELECT SELECT
id, entityId id, entityId
FROM FROM
sync sync
LEFT JOIN ${entityName} ON entityId = ${key} LEFT JOIN ${entityName} ON entityId = ${key}
WHERE WHERE
sync.entityName = '${entityName}' sync.entityName = '${entityName}'
AND ${key} IS NULL`, AND ${key} IS NULL`,
async ({id, entityId}) => { async ({id, entityId}) => {
if (this.autoFix) { if (this.autoFix) {
await sql.execute("DELETE FROM sync WHERE entityName = ? AND entityId = ?", [entityName, entityId]); await sql.execute("DELETE FROM sync WHERE entityName = ? AND entityId = ?", [entityName, entityId]);
logFix(`Deleted extra sync record id=${id}, entityName=${entityName}, entityId=${entityId}`); logFix(`Deleted extra sync record id=${id}, entityName=${entityName}, entityId=${entityId}`);
} else { } else {
logError(`Unrecognized sync record id=${id}, entityName=${entityName}, entityId=${entityId}`); logError(`Unrecognized sync record id=${id}, entityName=${entityName}, entityId=${entityId}`);
} }
}); });
} }
async findSyncRowsIssues() { async findSyncRowsIssues() {

View File

@ -599,6 +599,7 @@ async function eraseDeletedNotes() {
UPDATE notes UPDATE notes
SET title = '[deleted]', SET title = '[deleted]',
contentLength = 0, contentLength = 0,
isProtected = 0,
isErased = 1 isErased = 1
WHERE noteId IN (???)`, noteIdsToErase); WHERE noteId IN (???)`, noteIdsToErase);