server-ts: Port becca_loader

This commit is contained in:
Elian Doran 2024-02-17 20:45:31 +02:00
parent 3d5ef81860
commit d35613f510
No known key found for this signature in database
13 changed files with 61 additions and 56 deletions

View File

@ -1,5 +1,5 @@
module.exports = () => { module.exports = () => {
const beccaLoader = require('../../src/becca/becca_loader.js'); const beccaLoader = require('../../src/becca/becca_loader');
const becca = require('../../src/becca/becca.js'); const becca = require('../../src/becca/becca.js');
const cls = require('../../src/services/cls'); const cls = require('../../src/services/cls');
const log = require('../../src/services/log'); const log = require('../../src/services/log');

View File

@ -8,7 +8,7 @@ const sessionParser = require('./routes/session_parser.js');
const utils = require('./services/utils'); const utils = require('./services/utils');
require('./services/handlers.js'); require('./services/handlers.js');
require('./becca/becca_loader.js'); require('./becca/becca_loader');
const app = express(); const app = express();

View File

@ -1,19 +1,20 @@
"use strict"; "use strict";
const sql = require('../services/sql'); import sql = require('../services/sql');
const eventService = require('../services/events'); import eventService = require('../services/events');
const becca = require('./becca'); import becca = require('./becca');
const sqlInit = require('../services/sql_init'); import sqlInit = require('../services/sql_init');
const log = require('../services/log'); import log = require('../services/log');
const BNote = require('./entities/bnote'); import BNote = require('./entities/bnote');
const BBranch = require('./entities/bbranch'); import BBranch = require('./entities/bbranch');
const BAttribute = require('./entities/battribute'); import BAttribute = require('./entities/battribute');
const BOption = require('./entities/boption'); import BOption = require('./entities/boption');
const BEtapiToken = require('./entities/betapi_token'); import BEtapiToken = require('./entities/betapi_token');
const cls = require('../services/cls'); import cls = require('../services/cls');
const entityConstructor = require('../becca/entity_constructor'); import entityConstructor = require('../becca/entity_constructor');
import { AttributeRow, BranchRow, EtapiTokenRow, NoteRow, OptionRow } from './entities/rows';
const beccaLoaded = new Promise((res, rej) => { const beccaLoaded = new Promise<void>((res, rej) => {
sqlInit.dbReady.then(() => { sqlInit.dbReady.then(() => {
cls.init(() => { cls.init(() => {
load(); load();
@ -38,7 +39,7 @@ function load() {
new BNote().update(row).init(); new BNote().update(row).init();
} }
const branchRows = sql.getRawRows(`SELECT branchId, noteId, parentNoteId, prefix, notePosition, isExpanded, utcDateModified FROM branches WHERE isDeleted = 0`); const branchRows = sql.getRawRows<{ notePosition: number}>(`SELECT branchId, noteId, parentNoteId, prefix, notePosition, isExpanded, utcDateModified FROM branches WHERE isDeleted = 0`);
// in-memory sort is faster than in the DB // in-memory sort is faster than in the DB
branchRows.sort((a, b) => a.notePosition - b.notePosition); branchRows.sort((a, b) => a.notePosition - b.notePosition);
@ -46,15 +47,15 @@ function load() {
new BBranch().update(row).init(); new BBranch().update(row).init();
} }
for (const row of sql.getRawRows(`SELECT attributeId, noteId, type, name, value, isInheritable, position, utcDateModified FROM attributes WHERE isDeleted = 0`)) { for (const row of sql.getRawRows<AttributeRow>(`SELECT attributeId, noteId, type, name, value, isInheritable, position, utcDateModified FROM attributes WHERE isDeleted = 0`)) {
new BAttribute().update(row).init(); new BAttribute().update(row).init();
} }
for (const row of sql.getRows(`SELECT name, value, isSynced, utcDateModified FROM options`)) { for (const row of sql.getRows<OptionRow>(`SELECT name, value, isSynced, utcDateModified FROM options`)) {
new BOption(row); new BOption(row);
} }
for (const row of sql.getRows(`SELECT etapiTokenId, name, tokenHash, utcDateCreated, utcDateModified FROM etapi_tokens WHERE isDeleted = 0`)) { for (const row of sql.getRows<EtapiTokenRow>(`SELECT etapiTokenId, name, tokenHash, utcDateCreated, utcDateModified FROM etapi_tokens WHERE isDeleted = 0`)) {
new BEtapiToken(row); new BEtapiToken(row);
} }
}); });
@ -68,7 +69,7 @@ function load() {
log.info(`Becca (note cache) load took ${Date.now() - start}ms`); log.info(`Becca (note cache) load took ${Date.now() - start}ms`);
} }
function reload(reason) { function reload(reason: string) {
load(); load();
require('../services/ws').reloadFrontend(reason || "becca reloaded"); require('../services/ws').reloadFrontend(reason || "becca reloaded");
@ -112,7 +113,7 @@ eventService.subscribeBeccaLoader(eventService.ENTITY_CHANGED, ({entityName, en
* @param entityRow - can be a becca entity (change comes from this trilium instance) or just a row (from sync). * @param entityRow - can be a becca entity (change comes from this trilium instance) or just a row (from sync).
* It should be therefore treated as a row. * It should be therefore treated as a row.
*/ */
function postProcessEntityUpdate(entityName, entityRow) { function postProcessEntityUpdate(entityName: string, entityRow: any) {
if (entityName === 'notes') { if (entityName === 'notes') {
noteUpdated(entityRow); noteUpdated(entityRow);
} else if (entityName === 'branches') { } else if (entityName === 'branches') {
@ -140,13 +141,13 @@ eventService.subscribeBeccaLoader([eventService.ENTITY_DELETED, eventService.ENT
} }
}); });
function noteDeleted(noteId) { function noteDeleted(noteId: string) {
delete becca.notes[noteId]; delete becca.notes[noteId];
becca.dirtyNoteSetCache(); becca.dirtyNoteSetCache();
} }
function branchDeleted(branchId) { function branchDeleted(branchId: string) {
const branch = becca.branches[branchId]; const branch = becca.branches[branchId];
if (!branch) { if (!branch) {
@ -173,23 +174,26 @@ function branchDeleted(branchId) {
} }
delete becca.childParentToBranch[`${branch.noteId}-${branch.parentNoteId}`]; delete becca.childParentToBranch[`${branch.noteId}-${branch.parentNoteId}`];
delete becca.branches[branch.branchId]; if (branch.branchId) {
} delete becca.branches[branch.branchId];
function noteUpdated(entityRow) {
const note = becca.notes[entityRow.noteId];
if (note) {
// type / mime could have been changed, and they are present in flatTextCache
note.flatTextCache = null;
} }
} }
function branchUpdated(branchRow) { function noteUpdated(entityRow: NoteRow) {
const note = becca.notes[entityRow.noteId];
if (note) {
// FIXME, this wouldn't have worked in the original implementation since the variable was named __flatTextCache.
// type / mime could have been changed, and they are present in flatTextCache
note.__flatTextCache = null;
}
}
function branchUpdated(branchRow: BranchRow) {
const childNote = becca.notes[branchRow.noteId]; const childNote = becca.notes[branchRow.noteId];
if (childNote) { if (childNote) {
childNote.flatTextCache = null; childNote.__flatTextCache = null;
childNote.sortParents(); childNote.sortParents();
// notes in the subtree can get new inherited attributes // notes in the subtree can get new inherited attributes
@ -204,7 +208,7 @@ function branchUpdated(branchRow) {
} }
} }
function attributeDeleted(attributeId) { function attributeDeleted(attributeId: string) {
const attribute = becca.attributes[attributeId]; const attribute = becca.attributes[attributeId];
if (!attribute) { if (!attribute) {
@ -239,8 +243,7 @@ function attributeDeleted(attributeId) {
} }
} }
/** @param {BAttribute} attributeRow */ function attributeUpdated(attributeRow: BAttribute) {
function attributeUpdated(attributeRow) {
const attribute = becca.attributes[attributeRow.attributeId]; const attribute = becca.attributes[attributeRow.attributeId];
const note = becca.notes[attributeRow.noteId]; const note = becca.notes[attributeRow.noteId];
@ -253,7 +256,7 @@ function attributeUpdated(attributeRow) {
} }
} }
function noteReorderingUpdated(branchIdList) { function noteReorderingUpdated(branchIdList: number[]) {
const parentNoteIds = new Set(); const parentNoteIds = new Set();
for (const branchId in branchIdList) { for (const branchId in branchIdList) {
@ -267,7 +270,7 @@ function noteReorderingUpdated(branchIdList) {
} }
} }
function etapiTokenDeleted(etapiTokenId) { function etapiTokenDeleted(etapiTokenId: string) {
delete becca.etapiTokens[etapiTokenId]; delete becca.etapiTokens[etapiTokenId];
} }
@ -275,14 +278,14 @@ eventService.subscribeBeccaLoader(eventService.ENTER_PROTECTED_SESSION, () => {
try { try {
becca.decryptProtectedNotes(); becca.decryptProtectedNotes();
} }
catch (e) { catch (e: any) {
log.error(`Could not decrypt protected notes: ${e.message} ${e.stack}`); log.error(`Could not decrypt protected notes: ${e.message} ${e.stack}`);
} }
}); });
eventService.subscribeBeccaLoader(eventService.LEAVE_PROTECTED_SESSION, load); eventService.subscribeBeccaLoader(eventService.LEAVE_PROTECTED_SESSION, load);
module.exports = { export = {
load, load,
reload, reload,
beccaLoaded beccaLoaded

View File

@ -28,7 +28,7 @@ class BAttribute extends AbstractBeccaEntity<BAttribute> {
value!: string; value!: string;
isInheritable!: boolean; isInheritable!: boolean;
constructor(row: AttributeRow) { constructor(row?: AttributeRow) {
super(); super();
if (!row) { if (!row) {
@ -52,7 +52,7 @@ class BAttribute extends AbstractBeccaEntity<BAttribute> {
]); ]);
} }
update([attributeId, noteId, type, name, value, isInheritable, position, utcDateModified]: any[]) { update([attributeId, noteId, type, name, value, isInheritable, position, utcDateModified]: any) {
this.attributeId = attributeId; this.attributeId = attributeId;
this.noteId = noteId; this.noteId = noteId;
this.type = type; this.type = type;

View File

@ -30,7 +30,7 @@ class BBranch extends AbstractBeccaEntity<BBranch> {
isExpanded!: boolean; isExpanded!: boolean;
utcDateModified?: string; utcDateModified?: string;
constructor(row: BranchRow) { constructor(row?: BranchRow) {
super(); super();
if (!row) { if (!row) {

View File

@ -24,7 +24,7 @@ class BEtapiToken extends AbstractBeccaEntity<BEtapiToken> {
tokenHash!: string; tokenHash!: string;
private _isDeleted?: boolean; private _isDeleted?: boolean;
constructor(row: EtapiTokenRow) { constructor(row?: EtapiTokenRow) {
super(); super();
if (!row) { if (!row) {

View File

@ -70,7 +70,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
children!: BNote[]; children!: BNote[];
targetRelations!: BAttribute[]; targetRelations!: BAttribute[];
private __flatTextCache!: string | null; __flatTextCache!: string | null;
private __attributeCache!: BAttribute[] | null; private __attributeCache!: BAttribute[] | null;
private __inheritableAttributeCache!: BAttribute[] | null; private __inheritableAttributeCache!: BAttribute[] | null;
@ -86,7 +86,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
/** number of note revisions for this note */ /** number of note revisions for this note */
private revisionCount!: number | null; private revisionCount!: number | null;
constructor(row: Partial<NoteRow>) { constructor(row?: Partial<NoteRow>) {
super(); super();
if (!row) { if (!row) {

View File

@ -16,10 +16,12 @@ class BOption extends AbstractBeccaEntity<BOption> {
value!: string; value!: string;
isSynced!: boolean; isSynced!: boolean;
constructor(row: OptionRow) { constructor(row?: OptionRow) {
super(); super();
this.updateFromRow(row); if (row) {
this.updateFromRow(row);
}
this.becca.options[this.name] = this; this.becca.options[this.name] = this;
} }

View File

@ -7,7 +7,7 @@ const singleImportService = require('../../services/import/single.js');
const cls = require('../../services/cls'); const cls = require('../../services/cls');
const path = require('path'); const path = require('path');
const becca = require('../../becca/becca'); const becca = require('../../becca/becca');
const beccaLoader = require('../../becca/becca_loader.js'); const beccaLoader = require('../../becca/becca_loader');
const log = require('../../services/log'); const log = require('../../services/log');
const TaskContext = require('../../services/task_context'); const TaskContext = require('../../services/task_context');
const ValidationError = require('../../errors/validation_error'); const ValidationError = require('../../errors/validation_error');

View File

@ -766,7 +766,7 @@ class ConsistencyChecks {
} }
if (this.reloadNeeded) { if (this.reloadNeeded) {
require('../becca/becca_loader.js').reload("consistency checks need becca reload"); require('../becca/becca_loader').reload("consistency checks need becca reload");
} }
return !this.unrecoveredConsistencyErrors; return !this.unrecoveredConsistencyErrors;

View File

@ -143,8 +143,8 @@ function getRows<T>(query: string, params: Params = []): T[] {
return wrap(query, s => s.all(params)) as T[]; return wrap(query, s => s.all(params)) as T[];
} }
function getRawRows<T extends {} | unknown[]>(query: string, params: Params = []): T[] | null { function getRawRows<T extends {} | unknown[]>(query: string, params: Params = []): T[] {
return wrap(query, s => s.raw().all(params)) as T[] | null; return (wrap(query, s => s.raw().all(params)) as T[] | null) || [];
} }
function iterateRows(query: string, params: Params = []) { function iterateRows(query: string, params: Params = []) {
@ -259,7 +259,7 @@ function transactional<T>(func: (statement: Statement) => T) {
if (entityChangeIds.length > 0) { if (entityChangeIds.length > 0) {
log.info("Transaction rollback dirtied the becca, forcing reload."); log.info("Transaction rollback dirtied the becca, forcing reload.");
require('../becca/becca_loader.js').load(); require('../becca/becca_loader').load();
} }
// the maxEntityChangeId has been incremented during failed transaction, need to recalculate // the maxEntityChangeId has been incremented during failed transaction, need to recalculate

View File

@ -61,7 +61,7 @@ async function createInitialDatabase() {
sql.executeScript(schema); sql.executeScript(schema);
require('../becca/becca_loader.js').load(); require('../becca/becca_loader').load();
const BNote = require('../becca/entities/bnote'); const BNote = require('../becca/entities/bnote');
const BBranch = require('../becca/entities/bbranch'); const BBranch = require('../becca/entities/bbranch');

View File

@ -399,7 +399,7 @@ function getOutstandingPullCount() {
return outstandingPullCount; return outstandingPullCount;
} }
require('../becca/becca_loader.js').beccaLoaded.then(() => { require('../becca/becca_loader').beccaLoaded.then(() => {
setInterval(cls.wrap(sync), 60000); setInterval(cls.wrap(sync), 60000);
// kickoff initial sync immediately, but should happen after initial consistency checks // kickoff initial sync immediately, but should happen after initial consistency checks