mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
server-ts: Port consistency_checks
This commit is contained in:
parent
ed47c23e23
commit
aa233b8adb
10
src/app.js
10
src/app.js
@ -26,10 +26,10 @@ app.use(helmet({
|
|||||||
crossOriginEmbedderPolicy: false
|
crossOriginEmbedderPolicy: false
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.use(express.text({limit: '500mb'}));
|
app.use(express.text({ limit: '500mb' }));
|
||||||
app.use(express.json({limit: '500mb'}));
|
app.use(express.json({ limit: '500mb' }));
|
||||||
app.use(express.raw({limit: '500mb'}));
|
app.use(express.raw({ limit: '500mb' }));
|
||||||
app.use(express.urlencoded({extended: false}));
|
app.use(express.urlencoded({ extended: false }));
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(express.static(path.join(__dirname, 'public/root')));
|
app.use(express.static(path.join(__dirname, 'public/root')));
|
||||||
app.use(`/manifest.webmanifest`, express.static(path.join(__dirname, 'public/manifest.webmanifest')));
|
app.use(`/manifest.webmanifest`, express.static(path.join(__dirname, 'public/manifest.webmanifest')));
|
||||||
@ -49,7 +49,7 @@ require('./services/sync');
|
|||||||
require('./services/backup');
|
require('./services/backup');
|
||||||
|
|
||||||
// trigger consistency checks timer
|
// trigger consistency checks timer
|
||||||
require('./services/consistency_checks.js');
|
require('./services/consistency_checks');
|
||||||
|
|
||||||
require('./services/scheduler.js');
|
require('./services/scheduler.js');
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ const sql = require('../../services/sql');
|
|||||||
const log = require('../../services/log');
|
const log = require('../../services/log');
|
||||||
const backupService = require('../../services/backup');
|
const backupService = require('../../services/backup');
|
||||||
const anonymizationService = require('../../services/anonymization');
|
const anonymizationService = require('../../services/anonymization');
|
||||||
const consistencyChecksService = require('../../services/consistency_checks.js');
|
const consistencyChecksService = require('../../services/consistency_checks');
|
||||||
|
|
||||||
function getExistingBackups() {
|
function getExistingBackups() {
|
||||||
return backupService.getExistingBackups();
|
return backupService.getExistingBackups();
|
||||||
|
@ -132,7 +132,7 @@ function getChanged(req) {
|
|||||||
const partialRequests = {};
|
const partialRequests = {};
|
||||||
|
|
||||||
function update(req) {
|
function update(req) {
|
||||||
let {body} = req;
|
let { body } = req;
|
||||||
|
|
||||||
const pageCount = parseInt(req.get('pageCount'));
|
const pageCount = parseInt(req.get('pageCount'));
|
||||||
const pageIndex = parseInt(req.get('pageIndex'));
|
const pageIndex = parseInt(req.get('pageIndex'));
|
||||||
@ -164,7 +164,7 @@ function update(req) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const {entities, instanceId} = body;
|
const { entities, instanceId } = body;
|
||||||
|
|
||||||
sql.transactional(() => syncUpdateService.updateEntities(entities, instanceId));
|
sql.transactional(() => syncUpdateService.updateEntities(entities, instanceId));
|
||||||
}
|
}
|
||||||
@ -193,7 +193,7 @@ function queueSector(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkEntityChanges() {
|
function checkEntityChanges() {
|
||||||
require('../../services/consistency_checks.js').runEntityChangesChecks();
|
require('../../services/consistency_checks').runEntityChangesChecks();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -1,33 +1,42 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const sql = require('./sql');
|
import sql = require('./sql');
|
||||||
const sqlInit = require('./sql_init');
|
import sqlInit = require('./sql_init');
|
||||||
const log = require('./log');
|
import log = require('./log');
|
||||||
const ws = require('./ws');
|
import ws = require('./ws');
|
||||||
const syncMutexService = require('./sync_mutex');
|
import syncMutexService = require('./sync_mutex');
|
||||||
const cls = require('./cls');
|
import cls = require('./cls');
|
||||||
const entityChangesService = require('./entity_changes');
|
import entityChangesService = require('./entity_changes');
|
||||||
const optionsService = require('./options');
|
import optionsService = require('./options');
|
||||||
const BBranch = require('../becca/entities/bbranch');
|
import BBranch = require('../becca/entities/bbranch');
|
||||||
const revisionService = require('./revisions');
|
import revisionService = require('./revisions');
|
||||||
const becca = require('../becca/becca');
|
import becca = require('../becca/becca');
|
||||||
const utils = require('../services/utils');
|
import utils = require('../services/utils');
|
||||||
const eraseService = require('../services/erase');
|
import eraseService = require('../services/erase');
|
||||||
const {sanitizeAttributeName} = require('./sanitize_attribute_name');
|
import sanitizeAttributeName = require('./sanitize_attribute_name');
|
||||||
const noteTypes = require('../services/note_types').getNoteTypeNames();
|
import noteTypesService = require('../services/note_types');
|
||||||
|
import { BranchRow, NoteRow } from '../becca/entities/rows';
|
||||||
|
import { EntityChange, EntityRow } from './entity_changes_interface';
|
||||||
|
const noteTypes = noteTypesService.getNoteTypeNames();
|
||||||
|
|
||||||
class ConsistencyChecks {
|
class ConsistencyChecks {
|
||||||
|
|
||||||
|
private autoFix: boolean;
|
||||||
|
private unrecoveredConsistencyErrors: boolean;
|
||||||
|
private fixedIssues: boolean;
|
||||||
|
private reloadNeeded: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param autoFix - automatically fix all encountered problems. False is only for debugging during development (fail fast)
|
* @param autoFix - automatically fix all encountered problems. False is only for debugging during development (fail fast)
|
||||||
*/
|
*/
|
||||||
constructor(autoFix) {
|
constructor(autoFix: boolean) {
|
||||||
this.autoFix = autoFix;
|
this.autoFix = autoFix;
|
||||||
this.unrecoveredConsistencyErrors = false;
|
this.unrecoveredConsistencyErrors = false;
|
||||||
this.fixedIssues = false;
|
this.fixedIssues = false;
|
||||||
this.reloadNeeded = false;
|
this.reloadNeeded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
findAndFixIssues(query, fixerCb) {
|
findAndFixIssues(query: string, fixerCb: (res: any) => void) {
|
||||||
const results = sql.getRows(query);
|
const results = sql.getRows(query);
|
||||||
|
|
||||||
for (const res of results) {
|
for (const res of results) {
|
||||||
@ -39,7 +48,7 @@ class ConsistencyChecks {
|
|||||||
} else {
|
} else {
|
||||||
this.unrecoveredConsistencyErrors = true;
|
this.unrecoveredConsistencyErrors = true;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
logError(`Fixer failed with ${e.message} ${e.stack}`);
|
logError(`Fixer failed with ${e.message} ${e.stack}`);
|
||||||
this.unrecoveredConsistencyErrors = true;
|
this.unrecoveredConsistencyErrors = true;
|
||||||
}
|
}
|
||||||
@ -49,8 +58,8 @@ class ConsistencyChecks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkTreeCycles() {
|
checkTreeCycles() {
|
||||||
const childToParents = {};
|
const childToParents: Record<string, string[]> = {};
|
||||||
const rows = sql.getRows("SELECT noteId, parentNoteId FROM branches WHERE isDeleted = 0");
|
const rows = sql.getRows<BranchRow>("SELECT noteId, parentNoteId FROM branches WHERE isDeleted = 0");
|
||||||
|
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
const childNoteId = row.noteId;
|
const childNoteId = row.noteId;
|
||||||
@ -61,7 +70,7 @@ class ConsistencyChecks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {boolean} true if cycle was found and we should try again */
|
/** @returns {boolean} true if cycle was found and we should try again */
|
||||||
const checkTreeCycle = (noteId, path) => {
|
const checkTreeCycle = (noteId: string, path: string[]) => {
|
||||||
if (noteId === 'root') {
|
if (noteId === 'root') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -70,8 +79,10 @@ class ConsistencyChecks {
|
|||||||
if (path.includes(parentNoteId)) {
|
if (path.includes(parentNoteId)) {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const branch = becca.getBranchFromChildAndParent(noteId, parentNoteId);
|
const branch = becca.getBranchFromChildAndParent(noteId, parentNoteId);
|
||||||
branch.markAsDeleted('cycle-autofix');
|
if (branch) {
|
||||||
logFix(`Branch '${branch.branchId}' between child '${noteId}' and parent '${parentNoteId}' has been deleted since it was causing a tree cycle.`);
|
branch.markAsDeleted('cycle-autofix');
|
||||||
|
logFix(`Branch '${branch.branchId}' between child '${noteId}' and parent '${parentNoteId}' has been deleted since it was causing a tree cycle.`);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -133,6 +144,9 @@ class ConsistencyChecks {
|
|||||||
({branchId, noteId}) => {
|
({branchId, noteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const branch = becca.getBranch(branchId);
|
const branch = becca.getBranch(branchId);
|
||||||
|
if (!branch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
branch.markAsDeleted();
|
branch.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -154,12 +168,21 @@ class ConsistencyChecks {
|
|||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
// Delete the old branch and recreate it with root as parent.
|
// Delete the old branch and recreate it with root as parent.
|
||||||
const oldBranch = becca.getBranch(branchId);
|
const oldBranch = becca.getBranch(branchId);
|
||||||
|
if (!oldBranch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const noteId = oldBranch.noteId;
|
const noteId = oldBranch.noteId;
|
||||||
oldBranch.markAsDeleted("missing-parent");
|
oldBranch.markAsDeleted("missing-parent");
|
||||||
|
|
||||||
let message = `Branch '${branchId}' was missing parent note '${parentNoteId}', so it was deleted. `;
|
let message = `Branch '${branchId}' was missing parent note '${parentNoteId}', so it was deleted. `;
|
||||||
|
|
||||||
if (becca.getNote(noteId).getParentBranches().length === 0) {
|
const note = becca.getNote(noteId);
|
||||||
|
if (!note) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (note.getParentBranches().length === 0) {
|
||||||
const newBranch = new BBranch({
|
const newBranch = new BBranch({
|
||||||
parentNoteId: 'root',
|
parentNoteId: 'root',
|
||||||
noteId: noteId,
|
noteId: noteId,
|
||||||
@ -188,6 +211,9 @@ class ConsistencyChecks {
|
|||||||
({attributeId, noteId}) => {
|
({attributeId, noteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const attribute = becca.getAttribute(attributeId);
|
const attribute = becca.getAttribute(attributeId);
|
||||||
|
if (!attribute) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
attribute.markAsDeleted();
|
attribute.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -208,6 +234,9 @@ class ConsistencyChecks {
|
|||||||
({attributeId, noteId}) => {
|
({attributeId, noteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const attribute = becca.getAttribute(attributeId);
|
const attribute = becca.getAttribute(attributeId);
|
||||||
|
if (!attribute) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
attribute.markAsDeleted();
|
attribute.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -230,6 +259,9 @@ class ConsistencyChecks {
|
|||||||
({attachmentId, ownerId}) => {
|
({attachmentId, ownerId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const attachment = becca.getAttachment(attachmentId);
|
const attachment = becca.getAttachment(attachmentId);
|
||||||
|
if (!attachment) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
attachment.markAsDeleted();
|
attachment.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = false;
|
this.reloadNeeded = false;
|
||||||
@ -258,6 +290,7 @@ class ConsistencyChecks {
|
|||||||
({branchId, noteId}) => {
|
({branchId, noteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const branch = becca.getBranch(branchId);
|
const branch = becca.getBranch(branchId);
|
||||||
|
if (!branch) return;
|
||||||
branch.markAsDeleted();
|
branch.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -278,6 +311,9 @@ class ConsistencyChecks {
|
|||||||
`, ({branchId, parentNoteId}) => {
|
`, ({branchId, parentNoteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const branch = becca.getBranch(branchId);
|
const branch = becca.getBranch(branchId);
|
||||||
|
if (!branch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
branch.markAsDeleted();
|
branch.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -321,7 +357,7 @@ class ConsistencyChecks {
|
|||||||
HAVING COUNT(1) > 1`,
|
HAVING COUNT(1) > 1`,
|
||||||
({noteId, parentNoteId}) => {
|
({noteId, parentNoteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const branchIds = sql.getColumn(
|
const branchIds = sql.getColumn<string>(
|
||||||
`SELECT branchId
|
`SELECT branchId
|
||||||
FROM branches
|
FROM branches
|
||||||
WHERE noteId = ?
|
WHERE noteId = ?
|
||||||
@ -333,9 +369,17 @@ class ConsistencyChecks {
|
|||||||
|
|
||||||
// it's not necessarily "original" branch, it's just the only one which will survive
|
// it's not necessarily "original" branch, it's just the only one which will survive
|
||||||
const origBranch = branches[0];
|
const origBranch = branches[0];
|
||||||
|
if (!origBranch) {
|
||||||
|
logError(`Unable to find original branch.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// delete all but the first branch
|
// delete all but the first branch
|
||||||
for (const branch of branches.slice(1)) {
|
for (const branch of branches.slice(1)) {
|
||||||
|
if (!branch) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
branch.markAsDeleted();
|
branch.markAsDeleted();
|
||||||
|
|
||||||
logFix(`Removing branch '${branch.branchId}' since it's a parent-child duplicate of branch '${origBranch.branchId}'`);
|
logFix(`Removing branch '${branch.branchId}' since it's a parent-child duplicate of branch '${origBranch.branchId}'`);
|
||||||
@ -357,6 +401,7 @@ class ConsistencyChecks {
|
|||||||
({attachmentId, noteId}) => {
|
({attachmentId, noteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const attachment = becca.getAttachment(attachmentId);
|
const attachment = becca.getAttachment(attachmentId);
|
||||||
|
if (!attachment) return;
|
||||||
attachment.markAsDeleted();
|
attachment.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = false;
|
this.reloadNeeded = false;
|
||||||
@ -379,6 +424,7 @@ class ConsistencyChecks {
|
|||||||
({noteId, type}) => {
|
({noteId, type}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const note = becca.getNote(noteId);
|
const note = becca.getNote(noteId);
|
||||||
|
if (!note) return;
|
||||||
note.type = 'file'; // file is a safe option to recover notes if the type is not known
|
note.type = 'file'; // file is a safe option to recover notes if the type is not known
|
||||||
note.save();
|
note.save();
|
||||||
|
|
||||||
@ -404,6 +450,10 @@ class ConsistencyChecks {
|
|||||||
const fakeDate = "2000-01-01 00:00:00Z";
|
const fakeDate = "2000-01-01 00:00:00Z";
|
||||||
|
|
||||||
const blankContent = getBlankContent(isProtected, type, mime);
|
const blankContent = getBlankContent(isProtected, type, mime);
|
||||||
|
if (!blankContent) {
|
||||||
|
logError(`Unable to recover note ${noteId} since it's content could not be retrieved (might be protected note).`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const blobId = utils.hashedBlobId(blankContent);
|
const blobId = utils.hashedBlobId(blankContent);
|
||||||
const blobAlreadyExists = !!sql.getValue("SELECT 1 FROM blobs WHERE blobId = ?", [blobId]);
|
const blobAlreadyExists = !!sql.getValue("SELECT 1 FROM blobs WHERE blobId = ?", [blobId]);
|
||||||
|
|
||||||
@ -452,7 +502,11 @@ class ConsistencyChecks {
|
|||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const note = becca.getNote(noteId);
|
const note = becca.getNote(noteId);
|
||||||
const blankContent = getBlankContent(false, type, mime);
|
const blankContent = getBlankContent(false, type, mime);
|
||||||
note.setContent(blankContent);
|
if (!note) return;
|
||||||
|
|
||||||
|
if (blankContent) {
|
||||||
|
note.setContent(blankContent);
|
||||||
|
}
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
|
|
||||||
@ -506,7 +560,7 @@ class ConsistencyChecks {
|
|||||||
AND branches.isDeleted = 0`,
|
AND branches.isDeleted = 0`,
|
||||||
({parentNoteId}) => {
|
({parentNoteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const branchIds = sql.getColumn(`
|
const branchIds = sql.getColumn<string>(`
|
||||||
SELECT branchId
|
SELECT branchId
|
||||||
FROM branches
|
FROM branches
|
||||||
WHERE isDeleted = 0
|
WHERE isDeleted = 0
|
||||||
@ -515,6 +569,8 @@ class ConsistencyChecks {
|
|||||||
const branches = branchIds.map(branchId => becca.getBranch(branchId));
|
const branches = branchIds.map(branchId => becca.getBranch(branchId));
|
||||||
|
|
||||||
for (const branch of branches) {
|
for (const branch of branches) {
|
||||||
|
if (!branch) continue;
|
||||||
|
|
||||||
// delete the old wrong branch
|
// delete the old wrong branch
|
||||||
branch.markAsDeleted("parent-is-search");
|
branch.markAsDeleted("parent-is-search");
|
||||||
|
|
||||||
@ -543,6 +599,7 @@ class ConsistencyChecks {
|
|||||||
({attributeId}) => {
|
({attributeId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const relation = becca.getAttribute(attributeId);
|
const relation = becca.getAttribute(attributeId);
|
||||||
|
if (!relation) return;
|
||||||
relation.markAsDeleted();
|
relation.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -563,6 +620,7 @@ class ConsistencyChecks {
|
|||||||
({attributeId, type}) => {
|
({attributeId, type}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const attribute = becca.getAttribute(attributeId);
|
const attribute = becca.getAttribute(attributeId);
|
||||||
|
if (!attribute) return;
|
||||||
attribute.type = 'label';
|
attribute.type = 'label';
|
||||||
attribute.save();
|
attribute.save();
|
||||||
|
|
||||||
@ -584,6 +642,7 @@ class ConsistencyChecks {
|
|||||||
({attributeId, noteId}) => {
|
({attributeId, noteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const attribute = becca.getAttribute(attributeId);
|
const attribute = becca.getAttribute(attributeId);
|
||||||
|
if (!attribute) return;
|
||||||
attribute.markAsDeleted();
|
attribute.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -605,6 +664,7 @@ class ConsistencyChecks {
|
|||||||
({attributeId, targetNoteId}) => {
|
({attributeId, targetNoteId}) => {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
const attribute = becca.getAttribute(attributeId);
|
const attribute = becca.getAttribute(attributeId);
|
||||||
|
if (!attribute) return;
|
||||||
attribute.markAsDeleted();
|
attribute.markAsDeleted();
|
||||||
|
|
||||||
this.reloadNeeded = true;
|
this.reloadNeeded = true;
|
||||||
@ -616,14 +676,14 @@ class ConsistencyChecks {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
runEntityChangeChecks(entityName, key) {
|
runEntityChangeChecks(entityName: string, key: string) {
|
||||||
this.findAndFixIssues(`
|
this.findAndFixIssues(`
|
||||||
SELECT ${key} as entityId
|
SELECT ${key} as entityId
|
||||||
FROM ${entityName}
|
FROM ${entityName}
|
||||||
LEFT JOIN entity_changes ec ON ec.entityName = '${entityName}' AND ec.entityId = ${entityName}.${key}
|
LEFT JOIN entity_changes ec ON ec.entityName = '${entityName}' AND ec.entityId = ${entityName}.${key}
|
||||||
WHERE ec.id IS NULL`,
|
WHERE ec.id IS NULL`,
|
||||||
({entityId}) => {
|
({entityId}) => {
|
||||||
const entityRow = sql.getRow(`SELECT * FROM ${entityName} WHERE ${key} = ?`, [entityId]);
|
const entityRow = sql.getRow<EntityChange>(`SELECT * FROM ${entityName} WHERE ${key} = ?`, [entityId]);
|
||||||
|
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
entityChangesService.putEntityChange({
|
entityChangesService.putEntityChange({
|
||||||
@ -691,10 +751,10 @@ class ConsistencyChecks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
findWronglyNamedAttributes() {
|
findWronglyNamedAttributes() {
|
||||||
const attrNames = sql.getColumn(`SELECT DISTINCT name FROM attributes`);
|
const attrNames = sql.getColumn<string>(`SELECT DISTINCT name FROM attributes`);
|
||||||
|
|
||||||
for (const origName of attrNames) {
|
for (const origName of attrNames) {
|
||||||
const fixedName = sanitizeAttributeName(origName);
|
const fixedName = sanitizeAttributeName.sanitizeAttributeName(origName);
|
||||||
|
|
||||||
if (fixedName !== origName) {
|
if (fixedName !== origName) {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
@ -721,7 +781,7 @@ class ConsistencyChecks {
|
|||||||
|
|
||||||
findSyncIssues() {
|
findSyncIssues() {
|
||||||
const lastSyncedPush = parseInt(sql.getValue("SELECT value FROM options WHERE name = 'lastSyncedPush'"));
|
const lastSyncedPush = parseInt(sql.getValue("SELECT value FROM options WHERE name = 'lastSyncedPush'"));
|
||||||
const maxEntityChangeId = sql.getValue("SELECT MAX(id) FROM entity_changes");
|
const maxEntityChangeId = sql.getValue<number>("SELECT MAX(id) FROM entity_changes");
|
||||||
|
|
||||||
if (lastSyncedPush > maxEntityChangeId) {
|
if (lastSyncedPush > maxEntityChangeId) {
|
||||||
if (this.autoFix) {
|
if (this.autoFix) {
|
||||||
@ -773,8 +833,8 @@ class ConsistencyChecks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runDbDiagnostics() {
|
runDbDiagnostics() {
|
||||||
function getTableRowCount(tableName) {
|
function getTableRowCount(tableName: string) {
|
||||||
const count = sql.getValue(`SELECT COUNT(1) FROM ${tableName}`);
|
const count = sql.getValue<number>(`SELECT COUNT(1) FROM ${tableName}`);
|
||||||
|
|
||||||
return `${tableName}: ${count}`;
|
return `${tableName}: ${count}`;
|
||||||
}
|
}
|
||||||
@ -810,7 +870,7 @@ class ConsistencyChecks {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBlankContent(isProtected, type, mime) {
|
function getBlankContent(isProtected: boolean, type: string, mime: string) {
|
||||||
if (isProtected) {
|
if (isProtected) {
|
||||||
return null; // this is wrong for protected non-erased notes, but we cannot create a valid value without a password
|
return null; // this is wrong for protected non-erased notes, but we cannot create a valid value without a password
|
||||||
}
|
}
|
||||||
@ -822,11 +882,11 @@ function getBlankContent(isProtected, type, mime) {
|
|||||||
return ''; // empty string might be a wrong choice for some note types, but it's the best guess
|
return ''; // empty string might be a wrong choice for some note types, but it's the best guess
|
||||||
}
|
}
|
||||||
|
|
||||||
function logFix(message) {
|
function logFix(message: string) {
|
||||||
log.info(`Consistency issue fixed: ${message}`);
|
log.info(`Consistency issue fixed: ${message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function logError(message) {
|
function logError(message: string) {
|
||||||
log.info(`Consistency error: ${message}`);
|
log.info(`Consistency error: ${message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -837,7 +897,7 @@ function runPeriodicChecks() {
|
|||||||
consistencyChecks.runChecks();
|
consistencyChecks.runChecks();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runOnDemandChecks(autoFix) {
|
async function runOnDemandChecks(autoFix: boolean) {
|
||||||
const consistencyChecks = new ConsistencyChecks(autoFix);
|
const consistencyChecks = new ConsistencyChecks(autoFix);
|
||||||
await consistencyChecks.runChecks();
|
await consistencyChecks.runChecks();
|
||||||
}
|
}
|
@ -7,6 +7,8 @@ export interface EntityChange {
|
|||||||
positions?: Record<string, number>;
|
positions?: Record<string, number>;
|
||||||
hash: string;
|
hash: string;
|
||||||
utcDateChanged?: string;
|
utcDateChanged?: string;
|
||||||
|
utcDateModified?: string;
|
||||||
|
utcDateCreated?: string;
|
||||||
isSynced: boolean | 1 | 0;
|
isSynced: boolean | 1 | 0;
|
||||||
isErased: boolean | 1 | 0;
|
isErased: boolean | 1 | 0;
|
||||||
componentId?: string | null;
|
componentId?: string | null;
|
||||||
|
@ -179,7 +179,7 @@ dbReady.then(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function getDbSize() {
|
function getDbSize() {
|
||||||
return sql.getValue("SELECT page_count * page_size / 1000 as size FROM pragma_page_count(), pragma_page_size()");
|
return sql.getValue<number>("SELECT page_count * page_size / 1000 as size FROM pragma_page_count(), pragma_page_size()");
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(`DB size: ${getDbSize()} KB`);
|
log.info(`DB size: ${getDbSize()} KB`);
|
||||||
|
@ -282,7 +282,7 @@ async function checkContentHash(syncContext: SyncContext) {
|
|||||||
|
|
||||||
if (failedChecks.length > 0) {
|
if (failedChecks.length > 0) {
|
||||||
// before re-queuing sectors, make sure the entity changes are correct
|
// before re-queuing sectors, make sure the entity changes are correct
|
||||||
const consistencyChecks = require('./consistency_checks.js');
|
const consistencyChecks = require('./consistency_checks');
|
||||||
consistencyChecks.runEntityChangesChecks();
|
consistencyChecks.runEntityChangesChecks();
|
||||||
|
|
||||||
await syncRequest(syncContext, 'POST', `/api/sync/check-entity-changes`);
|
await syncRequest(syncContext, 'POST', `/api/sync/check-entity-changes`);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user