consistency checks fixes

This commit is contained in:
zadam 2020-07-01 22:42:59 +02:00
parent f0b608ddec
commit 78a2c1753e
4 changed files with 43 additions and 39 deletions

View File

@ -117,7 +117,6 @@ class Note extends Entity {
return JSON.parse(content); return JSON.parse(content);
} }
/** @returns {Promise} */
setContent(content) { setContent(content) {
if (content === null || content === undefined) { if (content === null || content === undefined) {
throw new Error(`Cannot set null content to note ${this.noteId}`); throw new Error(`Cannot set null content to note ${this.noteId}`);

View File

@ -100,7 +100,6 @@ class NoteRevision extends Entity {
} }
} }
/** @returns {Promise} */
setContent(content) { setContent(content) {
// force updating note itself so that utcDateModified is represented correctly even for the content // force updating note itself so that utcDateModified is represented correctly even for the content
this.forcedChange = true; this.forcedChange = true;

View File

@ -24,7 +24,7 @@ class ConsistencyChecks {
for (const res of results) { for (const res of results) {
try { try {
fixerCb(res); sql.transactional(() => fixerCb(res));
if (this.autoFix) { if (this.autoFix) {
this.fixedIssues = true; this.fixedIssues = true;
@ -94,7 +94,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT branchId, branches.noteId SELECT branchId, branches.noteId
FROM branches FROM branches
LEFT JOIN notes USING (noteId) LEFT JOIN notes USING (noteId)
WHERE branches.isDeleted = 0 WHERE branches.isDeleted = 0
AND notes.noteId IS NULL`, AND notes.noteId IS NULL`,
({branchId, noteId}) => { ({branchId, noteId}) => {
@ -112,7 +112,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT branchId, branches.noteId AS parentNoteId SELECT branchId, branches.noteId AS parentNoteId
FROM branches FROM branches
LEFT JOIN notes ON notes.noteId = branches.parentNoteId LEFT JOIN notes ON notes.noteId = branches.parentNoteId
WHERE branches.isDeleted = 0 WHERE branches.isDeleted = 0
AND branches.branchId != 'root' AND branches.branchId != 'root'
AND notes.noteId IS NULL`, AND notes.noteId IS NULL`,
@ -131,7 +131,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT attributeId, attributes.noteId SELECT attributeId, attributes.noteId
FROM attributes FROM attributes
LEFT JOIN notes USING (noteId) LEFT JOIN notes USING (noteId)
WHERE attributes.isDeleted = 0 WHERE attributes.isDeleted = 0
AND notes.noteId IS NULL`, AND notes.noteId IS NULL`,
({attributeId, noteId}) => { ({attributeId, noteId}) => {
@ -149,7 +149,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT attributeId, attributes.value AS noteId SELECT attributeId, attributes.value AS noteId
FROM attributes FROM attributes
LEFT JOIN notes ON notes.noteId = attributes.value LEFT JOIN notes ON notes.noteId = attributes.value
WHERE attributes.isDeleted = 0 WHERE attributes.isDeleted = 0
AND attributes.type = 'relation' AND attributes.type = 'relation'
AND notes.noteId IS NULL`, AND notes.noteId IS NULL`,
@ -176,7 +176,7 @@ class ConsistencyChecks {
SELECT branchId, SELECT branchId,
noteId noteId
FROM branches FROM branches
JOIN notes USING (noteId) JOIN notes USING (noteId)
WHERE notes.isDeleted = 1 WHERE notes.isDeleted = 1
AND branches.isDeleted = 0`, AND branches.isDeleted = 0`,
({branchId, noteId}) => { ({branchId, noteId}) => {
@ -195,7 +195,7 @@ class ConsistencyChecks {
SELECT branchId, SELECT branchId,
parentNoteId parentNoteId
FROM branches FROM branches
JOIN notes AS parentNote ON parentNote.noteId = branches.parentNoteId JOIN notes AS parentNote ON parentNote.noteId = branches.parentNoteId
WHERE parentNote.isDeleted = 1 WHERE parentNote.isDeleted = 1
AND branches.isDeleted = 0 AND branches.isDeleted = 0
`, ({branchId, parentNoteId}) => { `, ({branchId, parentNoteId}) => {
@ -213,7 +213,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT DISTINCT notes.noteId SELECT DISTINCT notes.noteId
FROM notes FROM notes
LEFT JOIN branches ON notes.noteId = branches.noteId AND branches.isDeleted = 0 LEFT JOIN branches ON notes.noteId = branches.noteId AND branches.isDeleted = 0
WHERE notes.isDeleted = 0 WHERE notes.isDeleted = 0
AND branches.branchId IS NULL AND branches.branchId IS NULL
`, ({noteId}) => { `, ({noteId}) => {
@ -285,7 +285,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT notes.noteId SELECT notes.noteId
FROM notes FROM notes
LEFT JOIN note_contents USING (noteId) LEFT JOIN note_contents USING (noteId)
WHERE note_contents.noteId IS NULL`, WHERE note_contents.noteId IS NULL`,
({noteId}) => { ({noteId}) => {
if (this.autoFix) { if (this.autoFix) {
@ -316,7 +316,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT noteId SELECT noteId
FROM notes FROM notes
JOIN note_contents USING (noteId) JOIN note_contents USING (noteId)
WHERE isDeleted = 0 WHERE isDeleted = 0
AND isProtected = 0 AND isProtected = 0
AND content IS NULL`, AND content IS NULL`,
@ -335,7 +335,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT noteId SELECT noteId
FROM notes FROM notes
JOIN note_contents USING (noteId) JOIN note_contents USING (noteId)
WHERE isErased = 1 WHERE isErased = 1
AND content IS NOT NULL`, AND content IS NOT NULL`,
({noteId}) => { ({noteId}) => {
@ -363,7 +363,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT noteId, noteRevisionId SELECT noteId, noteRevisionId
FROM notes FROM notes
JOIN note_revisions USING (noteId) JOIN note_revisions USING (noteId)
WHERE notes.isErased = 1 WHERE notes.isErased = 1
AND note_revisions.isErased = 0`, AND note_revisions.isErased = 0`,
({noteId, noteRevisionId}) => { ({noteId, noteRevisionId}) => {
@ -382,7 +382,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT note_revisions.noteRevisionId SELECT note_revisions.noteRevisionId
FROM note_revisions FROM note_revisions
LEFT JOIN note_revision_contents USING (noteRevisionId) LEFT JOIN note_revision_contents USING (noteRevisionId)
WHERE note_revision_contents.noteRevisionId IS NULL WHERE note_revision_contents.noteRevisionId IS NULL
AND note_revisions.isProtected = 0`, AND note_revisions.isProtected = 0`,
({noteRevisionId}) => { ({noteRevisionId}) => {
@ -401,7 +401,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT noteRevisionId SELECT noteRevisionId
FROM note_revisions FROM note_revisions
JOIN note_revision_contents USING (noteRevisionId) JOIN note_revision_contents USING (noteRevisionId)
WHERE isErased = 0 WHERE isErased = 0
AND content IS NULL`, AND content IS NULL`,
({noteRevisionId}) => { ({noteRevisionId}) => {
@ -454,7 +454,7 @@ class ConsistencyChecks {
this.findAndFixIssues(` this.findAndFixIssues(`
SELECT parentNoteId SELECT parentNoteId
FROM branches FROM branches
JOIN notes ON notes.noteId = branches.parentNoteId JOIN notes ON notes.noteId = branches.parentNoteId
WHERE notes.isDeleted = 0 WHERE notes.isDeleted = 0
AND notes.type == 'search' AND notes.type == 'search'
AND branches.isDeleted = 0`, AND branches.isDeleted = 0`,
@ -519,7 +519,7 @@ class ConsistencyChecks {
SELECT attributeId, SELECT attributeId,
attributes.noteId attributes.noteId
FROM attributes FROM attributes
JOIN notes ON attributes.noteId = notes.noteId JOIN notes ON attributes.noteId = notes.noteId
WHERE attributes.isDeleted = 0 WHERE attributes.isDeleted = 0
AND notes.isDeleted = 1`, AND notes.isDeleted = 1`,
({attributeId, noteId}) => { ({attributeId, noteId}) => {
@ -538,7 +538,7 @@ class ConsistencyChecks {
SELECT attributeId, SELECT attributeId,
attributes.value AS targetNoteId attributes.value AS targetNoteId
FROM attributes FROM attributes
JOIN notes ON attributes.value = notes.noteId JOIN notes ON attributes.value = notes.noteId
WHERE attributes.type = 'relation' WHERE attributes.type = 'relation'
AND attributes.isDeleted = 0 AND attributes.isDeleted = 0
AND notes.isDeleted = 1`, AND notes.isDeleted = 1`,
@ -605,7 +605,7 @@ class ConsistencyChecks {
this.runSyncRowChecks("options", "name"); this.runSyncRowChecks("options", "name");
} }
runAllChecks() { runAllChecksAndFixers() {
this.unrecoveredConsistencyErrors = false; this.unrecoveredConsistencyErrors = false;
this.fixedIssues = false; this.fixedIssues = false;
@ -639,34 +639,39 @@ class ConsistencyChecks {
} }
runDbDiagnostics() { runDbDiagnostics() {
this.showEntityStat("Notes", `SELECT isDeleted, count(1) this.showEntityStat("Notes",
FROM notes `SELECT isDeleted, count(1)
GROUP BY isDeleted`); FROM notes
this.showEntityStat("Note revisions", `SELECT isErased, count(1) GROUP BY isDeleted`);
FROM note_revisions this.showEntityStat("Note revisions",
GROUP BY isErased`); `SELECT isErased, count(1)
this.showEntityStat("Branches", `SELECT isDeleted, count(1) FROM note_revisions
FROM branches GROUP BY isErased`);
GROUP BY isDeleted`); this.showEntityStat("Branches",
this.showEntityStat("Attributes", `SELECT isDeleted, count(1) `SELECT isDeleted, count(1)
FROM attributes FROM branches
GROUP BY isDeleted`); GROUP BY isDeleted`);
this.showEntityStat("API tokens", `SELECT isDeleted, count(1) this.showEntityStat("Attributes",
FROM api_tokens `SELECT isDeleted, count(1)
GROUP BY isDeleted`); FROM attributes
GROUP BY isDeleted`);
this.showEntityStat("API tokens",
`SELECT isDeleted, count(1)
FROM api_tokens
GROUP BY isDeleted`);
} }
async runChecks() { async runChecks() {
let elapsedTimeMs; let elapsedTimeMs;
await syncMutexService.doExclusively(() => { await syncMutexService.doExclusively(() => {
const startTime = new Date(); const startTimeMs = Date.now();
this.runDbDiagnostics(); this.runDbDiagnostics();
this.runAllChecks(); this.runAllChecksAndFixers();
elapsedTimeMs = Date.now() - startTime.getTime(); elapsedTimeMs = Date.now() - startTimeMs;
}); });
if (this.unrecoveredConsistencyErrors) { if (this.unrecoveredConsistencyErrors) {

View File

@ -158,7 +158,8 @@ function getContentDisposition(filename) {
const STRING_MIME_TYPES = ["application/x-javascript", "image/svg+xml"]; const STRING_MIME_TYPES = ["application/x-javascript", "image/svg+xml"];
function isStringNote(type, mime) { function isStringNote(type, mime) {
return ["text", "code", "relation-map", "search"].includes(type) // render and book are string note in the sense that they are expected to contain empty string
return ["text", "code", "relation-map", "search", "render", "book"].includes(type)
|| mime.startsWith('text/') || mime.startsWith('text/')
|| STRING_MIME_TYPES.includes(mime); || STRING_MIME_TYPES.includes(mime);
} }