Fixed issue with read replica initialization.
Some checks failed
Create docker images (cloud) / Build, push, and deploy (push) Has been cancelled
Node.js CI / build (postgresql, 18.18, 10) (push) Has been cancelled

This commit is contained in:
Mike Cao 2025-10-06 14:49:36 -07:00
parent 3e163940da
commit 767b373484
5 changed files with 104 additions and 138 deletions

View file

@ -1,5 +1,4 @@
import { z } from 'zod';
import debug from 'debug';
import { isbot } from 'isbot';
import { startOfHour, startOfMonth } from 'date-fns';
import clickhouse from '@/lib/clickhouse';
@ -13,8 +12,7 @@ import { COLLECTION_TYPE, EVENT_TYPE } from '@/lib/constants';
import { anyObjectParam, urlOrPathParam } from '@/lib/schema';
import { safeDecodeURI, safeDecodeURIComponent } from '@/lib/url';
import { createSession, saveEvent, saveSessionData } from '@/queries/sql';
const log = debug('umami:send');
import { serializeError } from 'serialize-error';
interface Cache {
websiteId: string;
@ -270,7 +268,8 @@ export async function POST(request: Request) {
return json({ cache: token, sessionId, visitId });
} catch (e) {
log.error(e);
return serverError(e);
const error = serializeError(e);
return serverError({ errorObject: error });
}
}

View file

@ -1,6 +1,7 @@
import debug from 'debug';
import { PrismaPg } from '@prisma/adapter-pg';
import { readReplicas } from '@prisma/extension-read-replicas';
import { PrismaClient } from '@/generated/prisma/client';
import { UmamiPrismaClient } from '@umami/prisma-client';
import { SESSION_COLUMNS, OPERATORS, DEFAULT_PAGE_SIZE, FILTER_COLUMNS } from './constants';
import { QueryOptions, QueryFilters, Operator } from './types';
import { filtersObjectToArray } from './params';
@ -9,6 +10,15 @@ const log = debug('umami:prisma');
const PRISMA = 'prisma';
const PRISMA_LOG_OPTIONS = {
log: [
{
emit: 'event' as const,
level: 'query' as const,
},
],
};
const DATE_FORMATS = {
minute: 'YYYY-MM-DD HH24:MI:00',
hour: 'YYYY-MM-DD HH24:00:00',
@ -281,18 +291,47 @@ function getClient() {
return null;
}
const prisma = new UmamiPrismaClient({
url: process.env.DATABASE_URL,
prismaClient: PrismaClient,
logQuery: !!process.env.LOG_QUERY,
replicaUrl: process.env.DATABASE_REPLICA_URL,
const url = process.env.DATABASE_URL;
const replicaUrl = process.env.DATABASE_REPLICA_URL;
const logQuery = process.env.LOG_QUERY;
const connectionUrl = new URL(url);
const schema = connectionUrl.searchParams.get('schema') ?? undefined;
const adapter = new PrismaPg({ connectionString: url.toString() }, { schema });
const prisma = new PrismaClient({
adapter,
errorFormat: 'pretty',
...(logQuery ? PRISMA_LOG_OPTIONS : {}),
});
if (!globalThis[PRISMA]) {
globalThis[PRISMA] = prisma.client;
if (replicaUrl) {
const replicaAdapter = new PrismaPg({ connectionString: replicaUrl.toString() }, { schema });
const replicaClient = new PrismaClient({
adapter: replicaAdapter,
...(logQuery ? PRISMA_LOG_OPTIONS : {}),
});
prisma.$extends(
readReplicas({
replicas: [replicaClient],
}),
);
}
return prisma.client;
if (logQuery) {
prisma.$on('query' as never, log);
}
log('Prisma initialized');
if (!globalThis[PRISMA]) {
globalThis[PRISMA] = prisma;
}
return prisma;
}
const client: PrismaClient = globalThis[PRISMA] || getClient();