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:
parent
4d13b5b821
commit
da0fce708f
6 changed files with 18 additions and 20 deletions
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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(() => {
|
||||
|
|
|
|||
|
|
@ -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 () => {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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 } });
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue