diff --git a/apps/server/src/share/routes.ts b/apps/server/src/share/routes.ts index 80544fd998..69489c5522 100644 --- a/apps/server/src/share/routes.ts +++ b/apps/server/src/share/routes.ts @@ -1,6 +1,6 @@ import safeCompare from "safe-compare"; -import type { Request, Response, Router } from "express"; +import type { NextFunction, Request, Response, Router } from "express"; import shaca from "./shaca/shaca.js"; import shacaLoader from "./shaca/shaca_loader.js"; @@ -10,6 +10,16 @@ import type SNote from "./shaca/entities/snote.js"; import type SAttachment from "./shaca/entities/sattachment.js"; import { getDefaultTemplatePath, renderNoteContent } from "./content_renderer.js"; import utils from "../services/utils.js"; +import { isShareDbReady } from "./sql.js"; + +function assertShareDbReady(_req: Request, res: Response, next: NextFunction) { + if (!isShareDbReady()) { + res.status(503).send("The application is still initializing. Please try again in a moment."); + return; + } + + next(); +} function addNoIndexHeader(note: SNote, res: Response) { if (note.isLabelTruthy("shareDisallowRobotIndexing")) { @@ -115,6 +125,8 @@ function render404(res: Response) { } function register(router: Router) { + // Guard: if the share DB is not yet initialized, return 503 for all /share routes. + router.use("/share", assertShareDbReady); function renderNote(note: SNote, req: Request, res: Response) { if (!note) { diff --git a/apps/server/src/share/sql.ts b/apps/server/src/share/sql.ts index 36cca4b5ec..5a127e791f 100644 --- a/apps/server/src/share/sql.ts +++ b/apps/server/src/share/sql.ts @@ -5,12 +5,14 @@ import dataDir from "../services/data_dir.js"; import sql_init from "../services/sql_init.js"; let dbConnection!: Database.Database; +let dbConnectionReady = false; sql_init.dbReady.then(() => { dbConnection = new Database(dataDir.DOCUMENT_PATH, { readonly: true, nativeBinding: process.env.BETTERSQLITE3_NATIVE_PATH || undefined }); + dbConnectionReady = true; [`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach((eventType) => { process.on(eventType, () => { @@ -23,18 +25,31 @@ sql_init.dbReady.then(() => { }); }); +function assertDbReady(): void { + if (!dbConnectionReady) { + throw new Error("Share database connection is not yet ready. The application may still be initializing."); + } +} + function getRawRows(query: string, params = []): T[] { + assertDbReady(); return dbConnection.prepare(query).raw().all(params) as T[]; } function getRow(query: string, params: string[] = []): T { + assertDbReady(); return dbConnection.prepare(query).get(params) as T; } function getColumn(query: string, params: string[] = []): T[] { + assertDbReady(); return dbConnection.prepare(query).pluck().all(params) as T[]; } +export function isShareDbReady(): boolean { + return dbConnectionReady; +} + export default { getRawRows, getRow,