From 30b28793cf524ef50d29a4859e4c034c8f5f4b43 Mon Sep 17 00:00:00 2001 From: David Ventura Date: Mon, 6 Jan 2025 13:46:38 +0100 Subject: [PATCH] Allow populating event's createdAt on the send endpoint --- src/app/api/send/route.ts | 11 +++++++---- src/queries/sql/events/saveEvent.ts | 12 +++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index 80db8f96..4189d7d9 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -26,6 +26,7 @@ const schema = z.object({ tag: z.string().max(50).optional(), ip: z.string().ip().optional(), userAgent: z.string().optional(), + createdAt: yup.number().optional(), }), }); @@ -55,6 +56,7 @@ export async function POST(request: Request) { data, title, tag, + reqCreatedAt, } = payload; // Cache check @@ -119,14 +121,14 @@ export async function POST(request: Request) { } // Visit info - const now = Math.floor(new Date().getTime() / 1000); + const createdAt = Math.floor((reqCreatedAt || new Date()).getTime() / 1000); let visitId = cache?.visitId || uuid(sessionId, visitSalt()); - let iat = cache?.iat || now; + let iat = cache?.iat || createdAt; // Expire visit after 30 minutes - if (now - iat > 1800) { + if (createdAt - iat > 1800) { visitId = uuid(sessionId, visitSalt()); - iat = now; + iat = createdAt; } if (type === COLLECTION_TYPE.event) { @@ -179,6 +181,7 @@ export async function POST(request: Request) { subdivision2, city, tag, + createdAt, }); } diff --git a/src/queries/sql/events/saveEvent.ts b/src/queries/sql/events/saveEvent.ts index 65ee1175..3b3f3a99 100644 --- a/src/queries/sql/events/saveEvent.ts +++ b/src/queries/sql/events/saveEvent.ts @@ -29,6 +29,7 @@ export async function saveEvent(args: { subdivision2?: string; city?: string; tag?: string; + createdAt?: Date; }) { return runQuery({ [PRISMA]: () => relationalQuery(args), @@ -49,6 +50,7 @@ async function relationalQuery(data: { eventName?: string; eventData?: any; tag?: string; + createdAt?: Date; }) { const { websiteId, @@ -63,6 +65,7 @@ async function relationalQuery(data: { eventData, pageTitle, tag, + createdAt, } = data; const websiteEventId = uuid(); @@ -80,6 +83,7 @@ async function relationalQuery(data: { pageTitle: pageTitle?.substring(0, PAGE_TITLE_LENGTH), eventType: eventName ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, eventName: eventName ? eventName?.substring(0, EVENT_NAME_LENGTH) : null, + createdAt, tag, }, }); @@ -121,6 +125,7 @@ async function clickhouseQuery(data: { subdivision2?: string; city?: string; tag?: string; + createdAt?: Date; }) { const { websiteId, @@ -139,12 +144,13 @@ async function clickhouseQuery(data: { subdivision2, city, tag, + createdAt, ...args } = data; const { insert, getUTCString } = clickhouse; const { sendMessage } = kafka; const eventId = uuid(); - const createdAt = getUTCString(); + const createdAtUTC = getUTCString(createdAt); const message = { ...args, @@ -170,7 +176,7 @@ async function clickhouseQuery(data: { event_type: eventName ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, event_name: eventName ? eventName?.substring(0, EVENT_NAME_LENGTH) : null, tag: tag, - created_at: createdAt, + created_at: createdAtUTC, }; if (kafka.enabled) { @@ -187,7 +193,7 @@ async function clickhouseQuery(data: { urlPath: urlPath?.substring(0, URL_LENGTH), eventName: eventName?.substring(0, EVENT_NAME_LENGTH), eventData, - createdAt, + createdAt: createdAtUTC, }); }