2017-12-15 11:16:26 +08:00
"use strict" ;
const sql = require ( './sql' ) ;
const log = require ( './log' ) ;
2017-12-15 12:21:03 +08:00
const messaging = require ( './messaging' ) ;
2017-12-15 11:16:26 +08:00
async function runCheck ( query , errorText , errorList ) {
const result = await sql . getFlattenedResults ( query ) ;
if ( result . length > 0 ) {
const err = errorText + ": " + result ;
errorList . push ( err ) ;
log . error ( err ) ;
}
}
2017-12-16 11:16:28 +08:00
async function runSyncRowChecks ( table , key , errorList ) {
2017-12-20 11:04:51 +08:00
await runCheck ( ` SELECT ${ key } FROM ${ table } LEFT JOIN sync ON sync.entity_name = ' ${ table } ' AND entity_id = ${ key } WHERE sync.id IS NULL ` ,
2017-12-16 11:16:28 +08:00
` Missing sync records for ${ key } in table ${ table } ` , errorList ) ;
await runCheck ( ` SELECT entity_id FROM sync LEFT JOIN ${ table } ON entity_id = ${ key } WHERE sync.entity_name = ' ${ table } ' AND ${ key } IS NULL ` ,
` Missing ${ table } records for existing sync rows ` , errorList ) ;
2017-12-15 11:16:26 +08:00
}
async function runChecks ( ) {
const errorList = [ ] ;
2017-12-20 10:40:48 +08:00
await runCheck ( "SELECT note_id FROM notes LEFT JOIN notes_tree USING(note_id) WHERE note_id != 'root' AND notes_tree.note_tree_id IS NULL" ,
2017-12-15 11:16:26 +08:00
"Missing notes_tree records for following note IDs" , errorList ) ;
2017-12-15 12:21:03 +08:00
await runCheck ( "SELECT note_tree_id || ' > ' || notes_tree.note_id FROM notes_tree LEFT JOIN notes USING(note_id) WHERE notes.note_id IS NULL" ,
"Missing notes records for following note tree ID > note ID" , errorList ) ;
2017-12-15 11:16:26 +08:00
await runCheck ( "SELECT note_tree_id FROM notes_tree JOIN notes USING(note_id) WHERE notes.is_deleted = 1 AND notes_tree.is_deleted = 0" ,
"Note tree is not deleted even though main note is deleted for following note tree IDs" , errorList ) ;
2017-12-20 10:40:48 +08:00
await runCheck ( "SELECT child.parent_note_id || ' > ' || child.note_id FROM notes_tree AS child LEFT JOIN notes_tree AS parent ON parent.note_id = child.parent_note_id WHERE parent.note_id IS NULL AND child.parent_note_id != 'root'" ,
2017-12-15 11:16:26 +08:00
"Not existing parent in the following parent > child relations" , errorList ) ;
await runCheck ( "SELECT note_history_id || ' > ' || notes_history.note_id FROM notes_history LEFT JOIN notes USING(note_id) WHERE notes.note_id IS NULL" ,
"Missing notes records for following note history ID > note ID" , errorList ) ;
2017-12-16 11:16:28 +08:00
await runSyncRowChecks ( "notes" , "note_id" , errorList ) ;
await runSyncRowChecks ( "notes_history" , "note_history_id" , errorList ) ;
await runSyncRowChecks ( "notes_tree" , "note_tree_id" , errorList ) ;
await runSyncRowChecks ( "recent_notes" , "note_tree_id" , errorList ) ;
2017-12-15 12:21:03 +08:00
if ( errorList . length > 0 ) {
2017-12-20 12:22:21 +08:00
messaging . sendMessageToAllClients ( { type : 'consistency-checks-failed' } ) ;
2017-12-15 12:21:03 +08:00
}
2017-12-15 12:30:38 +08:00
else {
log . info ( "All consistency checks passed." ) ;
}
2017-12-15 11:16:26 +08:00
}
sql . dbReady . then ( ( ) => {
setInterval ( runChecks , 60 * 60 * 1000 ) ;
// kickoff backup immediately
2017-12-15 12:21:03 +08:00
setTimeout ( runChecks , 10000 ) ;
2017-12-15 11:16:26 +08:00
} ) ;
module . exports = {
runChecks
} ;