Files
stats/packages/db/src/services/project.service.ts
Carl-Gerhard Lindesvärd 4483e464d1 fix: optimize event buffer (#278)
* fix: how we fetch profiles in the buffer

* perf: optimize event buffer

* remove unused file

* fix

* wip

* wip: try groupmq 2

* try simplified event buffer with duration calculation on the fly instead
2026-03-16 13:29:40 +01:00

112 lines
2.2 KiB
TypeScript

import { cacheable } from '@openpanel/redis';
import sqlstring from 'sqlstring';
import { chQuery, TABLE_NAMES } from '../clickhouse/client';
import type { Prisma, Project } from '../prisma-client';
import { db } from '../prisma-client';
export type IServiceProject = Project;
export type IServiceProjectWithClients = Prisma.ProjectGetPayload<{
include: {
clients: true;
};
}>;
export async function getProjectById(id: string) {
const res = await db.project.findUnique({
where: {
id,
},
});
if (!res) {
return null;
}
return res;
}
/** L1 LRU (60s) + L2 Redis. clear() invalidates Redis + local LRU; other nodes may serve stale from LRU for up to 60s. */
export const getProjectByIdCached = cacheable(getProjectById, 60 * 60 * 24);
export async function getProjectWithClients(id: string) {
const res = await db.$primary().project.findUnique({
where: {
id,
},
include: {
clients: true,
},
});
if (!res) {
return null;
}
return res;
}
export function getProjectsByOrganizationId(organizationId: string) {
return db.project.findMany({
where: {
organizationId,
},
orderBy: {
eventsCount: 'desc',
},
});
}
export async function getProjects({
organizationId,
userId,
}: {
organizationId: string;
userId: string | null;
}) {
if (!userId) {
return [];
}
const [projects, members, access] = await Promise.all([
db.project.findMany({
where: {
organizationId,
},
orderBy: {
eventsCount: 'desc',
},
}),
db.member.findMany({
where: {
userId,
organizationId,
},
}),
db.projectAccess.findMany({
where: {
userId,
organizationId,
},
}),
]);
if (members.length === 0) {
return [];
}
if (access.length > 0) {
return projects.filter((project) =>
access.some((a) => a.projectId === project.id)
);
}
return projects;
}
export const getProjectEventsCount = async (projectId: string) => {
const res = await chQuery<{ count: number }>(
`SELECT count(*) as count FROM ${TABLE_NAMES.events} WHERE project_id = ${sqlstring.escape(projectId)} AND name NOT IN ('session_start', 'session_end')`
);
return res[0]?.count;
};