mirror of
https://github.com/zadam/trilium.git
synced 2025-01-01 12:52:17 +08:00
added sync mutex for consistency checks and backup
This commit is contained in:
parent
a6a687c4a6
commit
663bd1a8fe
7 changed files with 61 additions and 40 deletions
21
package-lock.json
generated
21
package-lock.json
generated
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "trilium",
|
||||
"version": "0.0.1",
|
||||
"version": "0.2.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -333,6 +333,11 @@
|
|||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
|
||||
},
|
||||
"async-mutex": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.1.3.tgz",
|
||||
"integrity": "sha1-Cq0hEjaXlas/F+M3RFVtLs9UdWY="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
|
@ -2909,15 +2914,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"electron-search-text": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/electron-search-text/-/electron-search-text-0.3.0.tgz",
|
||||
"integrity": "sha1-7/B6qelfmzeDqTGXNiyL43iKPT0=",
|
||||
"requires": {
|
||||
"eventemitter2": "2.2.2",
|
||||
"lodash": "4.17.4"
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.27",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz",
|
||||
|
@ -3535,11 +3531,6 @@
|
|||
"es5-ext": "0.10.35"
|
||||
}
|
||||
},
|
||||
"eventemitter2": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-2.2.2.tgz",
|
||||
"integrity": "sha1-QH6nHCAgzVdTggOrfnpr3Pt2ktU="
|
||||
},
|
||||
"execa": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
|
||||
|
|
|
@ -2,6 +2,11 @@
|
|||
"name": "trilium",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.2.2",
|
||||
"license": "AGPL-3.0-only",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zadam/trilium.git"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node ./bin/www",
|
||||
"test-electron": "xo",
|
||||
|
@ -14,6 +19,7 @@
|
|||
"publish-forge": "electron-forge publish"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-mutex": "^0.1.3",
|
||||
"body-parser": "~1.18.2",
|
||||
"cookie-parser": "~1.4.3",
|
||||
"debug": "~3.1.0",
|
||||
|
|
|
@ -190,7 +190,7 @@ async function validateParentChild(res, parentNoteId, childNoteId, noteTreeId =
|
|||
if (existing && (noteTreeId === null || existing.note_tree_id !== noteTreeId)) {
|
||||
res.send({
|
||||
success: false,
|
||||
message: 'This note already exists in target parent note.'
|
||||
message: 'This note already exists in the target.'
|
||||
});
|
||||
|
||||
return false;
|
||||
|
|
|
@ -6,6 +6,7 @@ const fs = require('fs-extra');
|
|||
const dataDir = require('./data_dir');
|
||||
const log = require('./log');
|
||||
const sql = require('./sql');
|
||||
const sync_mutex = require('./sync_mutex');
|
||||
|
||||
async function regularBackup() {
|
||||
const now = new Date();
|
||||
|
@ -21,17 +22,25 @@ async function regularBackup() {
|
|||
}
|
||||
|
||||
async function backupNow() {
|
||||
const now = utils.nowDate();
|
||||
// we don't want to backup DB in the middle of sync with potentially inconsistent DB state
|
||||
const releaseMutex = await sync_mutex.acquire();
|
||||
|
||||
const backupFile = dataDir.BACKUP_DIR + "/" + "backup-" + utils.getDateTimeForFile() + ".db";
|
||||
try {
|
||||
const now = utils.nowDate();
|
||||
|
||||
fs.copySync(dataDir.DOCUMENT_PATH, backupFile);
|
||||
const backupFile = dataDir.BACKUP_DIR + "/" + "backup-" + utils.getDateTimeForFile() + ".db";
|
||||
|
||||
log.info("Created backup at " + backupFile);
|
||||
fs.copySync(dataDir.DOCUMENT_PATH, backupFile);
|
||||
|
||||
await sql.doInTransaction(async () => {
|
||||
await options.setOption('last_backup_date', now);
|
||||
});
|
||||
log.info("Created backup at " + backupFile);
|
||||
|
||||
await sql.doInTransaction(async () => {
|
||||
await options.setOption('last_backup_date', now);
|
||||
});
|
||||
}
|
||||
finally {
|
||||
releaseMutex();
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanupOldBackups() {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
const sql = require('./sql');
|
||||
const log = require('./log');
|
||||
const messaging = require('./messaging');
|
||||
const sync_mutex = require('./sync_mutex');
|
||||
|
||||
async function runCheck(query, errorText, errorList) {
|
||||
const result = await sql.getFirstColumn(query);
|
||||
|
@ -80,11 +81,9 @@ async function runSyncRowChecks(table, key, errorList) {
|
|||
`Missing ${table} records for existing sync rows`, errorList);
|
||||
}
|
||||
|
||||
async function runChecks() {
|
||||
async function runAllChecks() {
|
||||
const errorList = [];
|
||||
|
||||
const startTime = new Date();
|
||||
|
||||
await runCheck(`
|
||||
SELECT
|
||||
note_id
|
||||
|
@ -139,7 +138,7 @@ async function runChecks() {
|
|||
WHERE
|
||||
(SELECT COUNT(*) FROM notes_tree WHERE notes.note_id = notes_tree.note_id AND notes_tree.is_deleted = 0) = 0
|
||||
AND notes.is_deleted = 0
|
||||
`, );
|
||||
`,);
|
||||
|
||||
await runCheck(`
|
||||
SELECT
|
||||
|
@ -186,7 +185,24 @@ async function runChecks() {
|
|||
await checkTreeCycles(errorList);
|
||||
}
|
||||
|
||||
const elapsedTimeMs = new Date().getTime() - startTime.getTime();
|
||||
return errorList;
|
||||
}
|
||||
|
||||
async function runChecks() {
|
||||
let errorList;
|
||||
let elapsedTimeMs;
|
||||
const releaseMutex = await sync_mutex.acquire();
|
||||
|
||||
try {
|
||||
const startTime = new Date();
|
||||
|
||||
errorList = await runAllChecks();
|
||||
|
||||
elapsedTimeMs = new Date().getTime() - startTime.getTime();
|
||||
}
|
||||
finally {
|
||||
releaseMutex();
|
||||
}
|
||||
|
||||
if (errorList.length > 0) {
|
||||
log.info(`Consistency checks failed (took ${elapsedTimeMs}ms) with these errors: ` + JSON.stringify(errorList));
|
||||
|
|
|
@ -14,22 +14,13 @@ const fs = require('fs');
|
|||
const app_info = require('./app_info');
|
||||
const messaging = require('./messaging');
|
||||
const sync_setup = require('./sync_setup');
|
||||
const sync_mutex = require('./sync_mutex');
|
||||
|
||||
let syncInProgress = false;
|
||||
let proxyToggle = true;
|
||||
let syncServerCertificate = null;
|
||||
|
||||
async function sync() {
|
||||
if (syncInProgress) {
|
||||
log.info("Sync already in progress");
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: "Sync already in progress"
|
||||
};
|
||||
}
|
||||
|
||||
syncInProgress = true;
|
||||
const releaseMutex = await sync_mutex.acquire();
|
||||
|
||||
try {
|
||||
if (!await sql.isDbUpToDate()) {
|
||||
|
@ -74,7 +65,7 @@ async function sync() {
|
|||
}
|
||||
}
|
||||
finally {
|
||||
syncInProgress = false;
|
||||
releaseMutex();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
8
services/sync_mutex.js
Normal file
8
services/sync_mutex.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Sync makes process can make data intermittently inconsistent. Processes which require strong data consistency
|
||||
* (like consistency checks) can use this mutex to make sure sync isn't currently running.
|
||||
*/
|
||||
|
||||
const Mutex = require('async-mutex').Mutex;
|
||||
|
||||
module.exports = new Mutex();
|
Loading…
Reference in a new issue