From 30da95d75a4d618d52b37cc20465f0af50835e1f Mon Sep 17 00:00:00 2001 From: perfectra1n Date: Sun, 16 Nov 2025 14:17:55 -0800 Subject: [PATCH] feat(search): update fulltext search and add stress test improvements - Modified note_content_fulltext.ts for enhanced search capabilities - Updated becca_mocking.ts for better test support - Improved stress-test-populate.ts script --- .../expressions/note_content_fulltext.ts | 18 ++++++++++----- apps/server/src/test/becca_mocking.ts | 8 +++---- scripts/stress-test-populate.ts | 23 +++++++++++-------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/apps/server/src/services/search/expressions/note_content_fulltext.ts b/apps/server/src/services/search/expressions/note_content_fulltext.ts index 8a64f001c..15ae469cf 100644 --- a/apps/server/src/services/search/expressions/note_content_fulltext.ts +++ b/apps/server/src/services/search/expressions/note_content_fulltext.ts @@ -314,13 +314,19 @@ class NoteContentFulltextExp extends Expression { [key: string]: any; // Other properties that may exist } - let canvasContent = JSON.parse(content); - const elements: Element[] = canvasContent.elements; - const texts = elements - .filter((element: Element) => element.type === "text" && element.text) // Filter for 'text' type elements with a 'text' property - .map((element: Element) => element.text!); // Use `!` to assert `text` is defined after filtering + try { + let canvasContent = JSON.parse(content); + // Canvas content may not have elements array, use empty array as default + const elements: Element[] = canvasContent.elements || []; + const texts = elements + .filter((element: Element) => element.type === "text" && element.text) // Filter for 'text' type elements with a 'text' property + .map((element: Element) => element.text!); // Use `!` to assert `text` is defined after filtering - content = normalize(texts.toString()); + content = normalize(texts.join(" ")); + } catch (e) { + // Handle JSON parse errors or malformed canvas content + content = ""; + } } return content.trim(); diff --git a/apps/server/src/test/becca_mocking.ts b/apps/server/src/test/becca_mocking.ts index 34ec36c3c..26b4c5922 100644 --- a/apps/server/src/test/becca_mocking.ts +++ b/apps/server/src/test/becca_mocking.ts @@ -25,7 +25,7 @@ export class NoteBuilder { isInheritable, name, value - }); + }).save(); return this; } @@ -37,7 +37,7 @@ export class NoteBuilder { type: "relation", name, value: targetNote.noteId - }); + }).save(); return this; } @@ -49,7 +49,7 @@ export class NoteBuilder { parentNoteId: this.note.noteId, prefix, notePosition: 10 - }); + }).save(); return this; } @@ -70,7 +70,7 @@ export function note(title: string, extraParams: Partial = {}) { extraParams ); - const note = new BNote(row); + const note = new BNote(row).save(); return new NoteBuilder(note); } diff --git a/scripts/stress-test-populate.ts b/scripts/stress-test-populate.ts index 991a7ac5c..c0af83b42 100644 --- a/scripts/stress-test-populate.ts +++ b/scripts/stress-test-populate.ts @@ -30,7 +30,6 @@ import BAttribute from "../apps/server/src/becca/entities/battribute.js"; import becca from "../apps/server/src/becca/becca.js"; import { NoteBuilder, id, note } from "../apps/server/src/test/becca_mocking.js"; import type { NoteType } from "@triliumnext/commons"; -import { dbReady } from "../apps/server/src/services/sql_init.js"; // Parse command line arguments const args = process.argv.slice(2); @@ -397,17 +396,23 @@ async function main() { console.log("Initializing translations..."); await initializeTranslations(); - console.log("Initializing database connection..."); - - // Wait for database to be ready (initialized by sql.ts import) - await dbReady; - console.log("Loading becca (backend cache)..."); - // Dynamically import becca_loader to ensure proper initialization order - const { beccaLoaded } = await import("../apps/server/src/becca/becca_loader.js"); - await beccaLoaded; + // Directly load becca instead of waiting for beccaLoaded promise + // (beccaLoaded depends on dbReady which won't resolve in this script context) + const becca_loader = (await import("../apps/server/src/becca/becca_loader.js")).default; + const cls = (await import("../apps/server/src/services/cls.js")).default; + // Load becca and run the population inside CLS context + cls.init(() => { + becca_loader.load(); + console.log("Becca loaded successfully."); + + populateNotes(); + }); +} + +function populateNotes() { const rootNote = becca.getNote("root"); if (!rootNote) { throw new Error("Root note not found!");