refactor: improve database reliability and clean up code

Enable WAL mode and set a busy timeout for SQLite to better handle
concurrent access and prevent 500 errors. Add error handling to
async calls in UI components and remove unused imports across several
files.
This commit is contained in:
Richard R 2026-02-15 15:44:20 -07:00
parent 4d13b5b821
commit da0fce708f
6 changed files with 18 additions and 20 deletions

View file

@ -1,13 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
import { and, eq, inArray } from 'drizzle-orm';
import { db } from '@/db';
import { documents } from '@/db/schema';
import { requireAuthContext } from '@/lib/server/auth';
import { isValidDocumentId } from '@/lib/server/documents-blobstore';
import { presignDocumentPreviewGet } from '@/lib/server/document-previews-blobstore';
import { ensureDocumentPreview, isPreviewableDocumentType } from '@/lib/server/document-previews';
import { getOpenReaderTestNamespace, getUnclaimedUserIdForNamespace } from '@/lib/server/test-namespace';
import { isS3Configured } from '@/lib/server/s3';
import { ensureDocumentPreview } from '@/lib/server/document-previews';
import { validatePreviewRequest } from '../utils';
export const dynamic = 'force-dynamic';

View file

@ -1,13 +1,6 @@
import { NextRequest, NextResponse } from 'next/server';
import { and, eq, inArray } from 'drizzle-orm';
import { db } from '@/db';
import { documents } from '@/db/schema';
import { requireAuthContext } from '@/lib/server/auth';
import { isValidDocumentId } from '@/lib/server/documents-blobstore';
import { presignDocumentPreviewGet } from '@/lib/server/document-previews-blobstore';
import { ensureDocumentPreview, isPreviewableDocumentType } from '@/lib/server/document-previews';
import { getOpenReaderTestNamespace, getUnclaimedUserIdForNamespace } from '@/lib/server/test-namespace';
import { isS3Configured } from '@/lib/server/s3';
import { ensureDocumentPreview } from '@/lib/server/document-previews';
import { validatePreviewRequest } from '../utils';
export const dynamic = 'force-dynamic';

View file

@ -134,7 +134,9 @@ export function PrivacyModal({ onAccept, authEnabled = false }: PrivacyModalProp
}, []);
useEffect(() => {
checkPrivacyAccepted();
checkPrivacyAccepted().catch((err) => {
console.error('Privacy acceptance check failed:', err);
});
}, [checkPrivacyAccepted]);
useEffect(() => {

View file

@ -160,7 +160,9 @@ export function SettingsModal({ className = '' }: { className?: string }) {
}, [setIsOpen]);
useEffect(() => {
checkFirstVist();
checkFirstVist().catch((err) => {
console.error('First visit check failed:', err);
});
setLocalApiKey(apiKey);
setLocalBaseUrl(baseUrl);
setLocalTTSProvider(ttsProvider);
@ -170,7 +172,9 @@ export function SettingsModal({ className = '' }: { className?: string }) {
useEffect(() => {
const onPrivacyAccepted = () => {
checkFirstVist();
checkFirstVist().catch((err) => {
console.error('First visit check after privacy acceptance failed:', err);
});
};
window.addEventListener('openreader:privacyAccepted', onPrivacyAccepted);
return () => {

View file

@ -1,6 +1,6 @@
'use client';
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Fragment, useCallback, useEffect, useRef, useState } from 'react';
import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild, Button } from '@headlessui/react';
import { getAppConfig, getAllEpubDocuments, getAllHtmlDocuments, getAllPdfDocuments, updateAppConfig } from '@/lib/dexie';
import { listDocuments, mimeTypeForDoc, uploadDocuments } from '@/lib/client-documents';

View file

@ -74,6 +74,12 @@ function getDrizzleDB() {
fs.mkdirSync(dir, { recursive: true });
}
const sqlite = new Database(dbPath);
// WAL mode allows concurrent readers + writer without blocking each other.
// busy_timeout retries on SQLITE_BUSY instead of failing immediately,
// which prevents 500 errors under concurrent API requests (e.g. multiple
// Playwright browser projects hitting the server simultaneously).
sqlite.pragma('journal_mode = WAL');
sqlite.pragma('busy_timeout = 5000');
dbInstance = drizzleSqlite(sqlite, { schema: { ...schema, ...authSchemaSqlite } });
}