perf: lazy load heavy dependencies and db drivers
Move database drivers and heavy server-side modules to be loaded lazily via require() and dynamic import(). This reduces the initial memory footprint and improves cold start performance for serverless functions by avoiding loading unused dependencies on every request.
This commit is contained in:
parent
9931c7d0d8
commit
fc24b31cc3
2 changed files with 29 additions and 16 deletions
|
|
@ -1,14 +1,16 @@
|
|||
import { drizzle as drizzlePg } from 'drizzle-orm/node-postgres';
|
||||
import { drizzle as drizzleSqlite } from 'drizzle-orm/better-sqlite3';
|
||||
import { sql } from 'drizzle-orm';
|
||||
import { Pool } from 'pg';
|
||||
import Database from 'better-sqlite3';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import * as schema from './schema';
|
||||
import * as authSchemaSqlite from './schema_auth_sqlite';
|
||||
import * as authSchemaPostgres from './schema_auth_postgres';
|
||||
|
||||
// Database driver modules are loaded lazily via require() inside getDrizzleDB()
|
||||
// to avoid loading the unused driver (~15-20 MB each) in every serverless function.
|
||||
// require() is used instead of dynamic import() because getDrizzleDB() must remain
|
||||
// synchronous for the SQLite code path.
|
||||
|
||||
|
||||
const UNCLAIMED_USER_ID = 'unclaimed';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
|
@ -62,12 +64,20 @@ function getDrizzleDB() {
|
|||
dbIsPostgres = !!process.env.POSTGRES_URL;
|
||||
|
||||
if (dbIsPostgres) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { drizzle: drizzlePg } = require('drizzle-orm/node-postgres');
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { Pool } = require('pg');
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.POSTGRES_URL,
|
||||
});
|
||||
dbInstance = drizzlePg(pool, { schema: { ...schema, ...authSchemaPostgres } });
|
||||
} else {
|
||||
// Fallback to SQLite
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const { drizzle: drizzleSqlite } = require('drizzle-orm/better-sqlite3');
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const Database = require('better-sqlite3');
|
||||
const dbPath = path.join(process.cwd(), 'docstore', 'sqlite3.db');
|
||||
const dir = path.dirname(dbPath);
|
||||
if (!fs.existsSync(dir)) {
|
||||
|
|
|
|||
|
|
@ -5,17 +5,13 @@ import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|||
import { NextResponse } from 'next/server';
|
||||
import type { NextRequest } from 'next/server';
|
||||
import { db } from "@/db";
|
||||
import { rateLimiter } from "@/lib/server/rate-limiter";
|
||||
import { isAuthEnabled, isAnonymousAuthSessionsEnabled } from "@/lib/server/auth-config";
|
||||
import { deleteUserStorageData } from "@/lib/server/user-data-cleanup";
|
||||
import * as authSchemaSqlite from "@/db/schema_auth_sqlite";
|
||||
import * as authSchemaPostgres from "@/db/schema_auth_postgres";
|
||||
import {
|
||||
transferUserAudiobooks,
|
||||
transferUserDocuments,
|
||||
transferUserPreferences,
|
||||
transferUserProgress,
|
||||
} from "@/lib/server/claim-data";
|
||||
|
||||
// Heavy modules (S3 SDK, blobstore, rate-limiter, claim-data) are loaded
|
||||
// lazily via dynamic import() inside the beforeDelete / onLinkAccount
|
||||
// callbacks to avoid inflating every serverless function that touches auth.
|
||||
|
||||
// ...
|
||||
|
||||
|
|
@ -80,6 +76,7 @@ const createAuth = () => betterAuth({
|
|||
enabled: true,
|
||||
beforeDelete: async (user) => {
|
||||
try {
|
||||
const { deleteUserStorageData } = await import('@/lib/server/user-data-cleanup');
|
||||
await deleteUserStorageData(user.id, null);
|
||||
} catch (error) {
|
||||
console.error('[auth] Failed to clean up user storage before deletion:', error);
|
||||
|
|
@ -123,6 +120,12 @@ const createAuth = () => betterAuth({
|
|||
newUserEmail: newUser.user.email,
|
||||
});
|
||||
|
||||
// Lazy-load heavy modules only when account linking actually happens
|
||||
const [{ rateLimiter }, claimData] = await Promise.all([
|
||||
import('@/lib/server/rate-limiter'),
|
||||
import('@/lib/server/claim-data'),
|
||||
]);
|
||||
|
||||
// Transfer rate limiting data (TTS char counts) from anonymous user to authenticated user
|
||||
try {
|
||||
await rateLimiter.transferAnonymousUsage(anonymousUser.user.id, newUser.user.id);
|
||||
|
|
@ -134,7 +137,7 @@ const createAuth = () => betterAuth({
|
|||
|
||||
// Transfer audiobooks from anonymous user to new authenticated user
|
||||
try {
|
||||
const transferred = await transferUserAudiobooks(anonymousUser.user.id, newUser.user.id);
|
||||
const transferred = await claimData.transferUserAudiobooks(anonymousUser.user.id, newUser.user.id);
|
||||
if (transferred > 0) {
|
||||
console.log(`Successfully transferred ${transferred} audiobook(s) from anonymous user ${anonymousUser.user.id} to user ${newUser.user.id}`);
|
||||
}
|
||||
|
|
@ -145,7 +148,7 @@ const createAuth = () => betterAuth({
|
|||
|
||||
// Transfer documents from anonymous user to new authenticated user
|
||||
try {
|
||||
const transferred = await transferUserDocuments(anonymousUser.user.id, newUser.user.id);
|
||||
const transferred = await claimData.transferUserDocuments(anonymousUser.user.id, newUser.user.id);
|
||||
if (transferred > 0) {
|
||||
console.log(`Successfully transferred ${transferred} document(s) from anonymous user ${anonymousUser.user.id} to user ${newUser.user.id}`);
|
||||
}
|
||||
|
|
@ -156,7 +159,7 @@ const createAuth = () => betterAuth({
|
|||
|
||||
// Transfer preferences from anonymous user to new authenticated user
|
||||
try {
|
||||
const transferred = await transferUserPreferences(anonymousUser.user.id, newUser.user.id);
|
||||
const transferred = await claimData.transferUserPreferences(anonymousUser.user.id, newUser.user.id);
|
||||
if (transferred > 0) {
|
||||
console.log(`Successfully transferred preferences from anonymous user ${anonymousUser.user.id} to user ${newUser.user.id}`);
|
||||
}
|
||||
|
|
@ -167,7 +170,7 @@ const createAuth = () => betterAuth({
|
|||
|
||||
// Transfer reading progress from anonymous user to new authenticated user
|
||||
try {
|
||||
const transferred = await transferUserProgress(anonymousUser.user.id, newUser.user.id);
|
||||
const transferred = await claimData.transferUserProgress(anonymousUser.user.id, newUser.user.id);
|
||||
if (transferred > 0) {
|
||||
console.log(`Successfully transferred ${transferred} progress row(s) from anonymous user ${anonymousUser.user.id} to user ${newUser.user.id}`);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue