fix: funnel notifications

This commit is contained in:
Carl-Gerhard Lindesvärd
2026-02-27 10:24:45 +01:00
parent 928c44ef6a
commit 9c6c7bb037
2 changed files with 82 additions and 45 deletions

View File

@@ -1,24 +1,22 @@
import type { Job } from 'bullmq';
import { logger as baseLogger } from '@/utils/logger';
import {
type IClickhouseSession,
type IServiceCreateEventPayload,
type IServiceEvent,
TABLE_NAMES,
checkNotificationRulesForSessionEnd,
convertClickhouseDateToJs,
createEvent,
eventBuffer,
formatClickhouseDate,
getEvents,
getHasFunnelRules,
getNotificationRulesByProjectId,
type IClickhouseSession,
type IServiceCreateEventPayload,
type IServiceEvent,
profileBackfillBuffer,
sessionBuffer,
TABLE_NAMES,
transformSessionToEvent,
} from '@openpanel/db';
import type { EventsQueuePayloadCreateSessionEnd } from '@openpanel/queue';
import type { Job } from 'bullmq';
import { logger as baseLogger } from '@/utils/logger';
const MAX_SESSION_EVENTS = 500;
@@ -39,7 +37,7 @@ async function getSessionEvents({
WHERE
session_id = '${sessionId}'
AND project_id = '${projectId}'
AND created_at BETWEEN '${formatClickhouseDate(startAt)}' AND '${formatClickhouseDate(endAt)}'
AND created_at BETWEEN '${formatClickhouseDate(new Date(startAt.getTime() - 1000))}' AND '${formatClickhouseDate(new Date(endAt.getTime() + 1000))}'
ORDER BY created_at DESC LIMIT ${MAX_SESSION_EVENTS};
`;
@@ -58,12 +56,12 @@ async function getSessionEvents({
.flatMap((event) => (event ? [event] : []))
.sort(
(a, b) =>
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
);
}
export async function createSessionEnd(
job: Job<EventsQueuePayloadCreateSessionEnd>,
job: Job<EventsQueuePayloadCreateSessionEnd>
) {
const { payload } = job.data;
const logger = baseLogger.child({
@@ -92,18 +90,24 @@ export async function createSessionEnd(
});
}
const profileId = session.profile_id || payload.profileId
const profileId = session.profile_id || payload.profileId;
if (
profileId !== session.device_id
&& process.env.EXPERIMENTAL_PROFILE_BACKFILL === '1'
profileId !== session.device_id &&
process.env.EXPERIMENTAL_PROFILE_BACKFILL === '1'
) {
const runOnProjects = process.env.EXPERIMENTAL_PROFILE_BACKFILL_PROJECTS?.split(',').filter(Boolean) ?? []
if(runOnProjects.length === 0 || runOnProjects.includes(payload.projectId)) {
const runOnProjects =
process.env.EXPERIMENTAL_PROFILE_BACKFILL_PROJECTS?.split(',').filter(
Boolean
) ?? [];
if (
runOnProjects.length === 0 ||
runOnProjects.includes(payload.projectId)
) {
await profileBackfillBuffer.add({
projectId: payload.projectId,
sessionId: payload.sessionId,
profileId: profileId,
profileId,
});
}
}
@@ -119,9 +123,9 @@ export async function createSessionEnd(
duration: session.duration ?? 0,
path: session.exit_path ?? '',
createdAt: new Date(
convertClickhouseDateToJs(session.ended_at).getTime() + 1000,
convertClickhouseDateToJs(session.ended_at).getTime() + 1000
),
profileId: profileId,
profileId,
});
}
@@ -133,7 +137,7 @@ async function handleSessionEndNotifications({
payload: IServiceCreateEventPayload;
}) {
const notificationRules = await getNotificationRulesByProjectId(
payload.projectId,
payload.projectId
);
const hasFunnelRules = getHasFunnelRules(notificationRules);
const isEventCountReasonable =
@@ -143,8 +147,8 @@ async function handleSessionEndNotifications({
const events = await getSessionEvents({
projectId: payload.projectId,
sessionId: payload.sessionId,
startAt: new Date(session.created_at),
endAt: new Date(session.ended_at),
startAt: convertClickhouseDateToJs(session.created_at),
endAt: convertClickhouseDateToJs(session.ended_at),
});
if (events.length > 0) {