Fixed realtime chart rendering.

This commit is contained in:
Mike Cao 2023-12-09 20:55:50 -08:00
parent 7a5f28870f
commit 92a513e4d0
5 changed files with 49 additions and 26 deletions

View File

@ -19,9 +19,9 @@ import { RealtimeData } from 'lib/types';
import styles from './Realtime.module.css';
function mergeData(state = [], data = [], time: number) {
const ids = state.map(({ __id }) => __id);
const ids = state.map(({ id }) => id);
return state
.concat(data.filter(({ __id }) => !ids.includes(__id)))
.concat(data.filter(({ id }) => !ids.includes(id)))
.filter(({ timestamp }) => timestamp >= time);
}
@ -38,21 +38,18 @@ export function Realtime({ websiteId }) {
useEffect(() => {
if (data) {
if (!currentData) {
setCurrentData(data);
} else {
const date = subMinutes(startOfMinute(new Date()), REALTIME_RANGE);
const time = date.getTime();
const { pageviews, sessions, events, timestamp } = data;
setCurrentData(state => ({
pageviews: mergeData(state?.pageviews, data.pageviews, time),
sessions: mergeData(state?.sessions, data.sessions, time),
events: mergeData(state?.events, data.events, time),
timestamp: data.timestamp,
pageviews: mergeData(state?.pageviews, pageviews, time),
sessions: mergeData(state?.sessions, sessions, time),
events: mergeData(state?.events, events, time),
timestamp,
}));
}
}
}, [data]);
}, [data, currentData]);
const realtimeData: RealtimeData = useMemo(() => {
if (!currentData) {

View File

@ -1,4 +1,4 @@
import { subMinutes } from 'date-fns';
import { startOfMinute, subMinutes } from 'date-fns';
import { canViewWebsite } from 'lib/auth';
import { useAuth, useValidate } from 'lib/middleware';
import { NextApiRequestQueryBody, RealtimeInit } from 'lib/types';
@ -6,6 +6,8 @@ import { NextApiResponse } from 'next';
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getRealtimeData } from 'queries';
import * as yup from 'yup';
import { REALTIME_RANGE } from 'lib/constants';
export interface RealtimeRequestQuery {
id: string;
startAt: number;
@ -32,7 +34,7 @@ export default async (
return unauthorized(res);
}
let startTime = subMinutes(new Date(), 30);
let startTime = subMinutes(startOfMinute(new Date()), REALTIME_RANGE);
if (+startAt > startTime.getTime()) {
startTime = new Date(+startAt);

View File

@ -18,6 +18,9 @@ function relationalQuery(websiteId: string, startDate: Date, eventType: number)
gte: startDate,
},
},
orderBy: {
createdAt: 'asc',
},
});
}
@ -39,6 +42,7 @@ function clickhouseQuery(websiteId: string, startDate: Date, eventType: number)
where website_id = {websiteId:UUID}
and created_at >= {startDate:DateTime64}
and event_type = {eventType:UInt32}
order by created_at asc
`,
{
websiteId,

View File

@ -1,4 +1,3 @@
import { md5 } from 'next-basics';
import { getSessions, getEvents } from 'queries/index';
import { EVENT_TYPE } from 'lib/constants';
@ -9,18 +8,35 @@ export async function getRealtimeData(websiteId: string, startDate: Date) {
getEvents(websiteId, startDate, EVENT_TYPE.customEvent),
]);
const decorate = (id: string, data: any[]) => {
return data.map((props: { [key: string]: any }) => ({
...props,
__id: md5(id, ...Object.values(props)),
__type: id,
timestamp: props.timestamp ? props.timestamp * 1000 : new Date(props.createdAt).getTime(),
const decorate = (type: string, data: any[]) => {
return data.map((values: { [key: string]: any }) => ({
...values,
__type: type,
timestamp: values.timestamp ? values.timestamp * 1000 : new Date(values.createdAt).getTime(),
}));
};
const set = new Set();
const uniques = (type: string, data: any[]) => {
return data.reduce((arr, values: { [key: string]: any }) => {
if (!set.has(values.id)) {
set.add(values.id);
return arr.concat({
...values,
__type: type,
timestamp: values.timestamp
? values.timestamp * 1000
: new Date(values.createdAt).getTime(),
});
}
return arr;
}, []);
};
return {
pageviews: decorate('pageview', pageviews),
sessions: decorate('session', sessions),
sessions: uniques('session', sessions),
events: decorate('event', events),
timestamp: Date.now(),
};

View File

@ -17,6 +17,9 @@ async function relationalQuery(websiteId: string, startDate: Date) {
gte: startDate,
},
},
orderBy: {
createdAt: 'asc',
},
});
}
@ -25,7 +28,7 @@ async function clickhouseQuery(websiteId: string, startDate: Date) {
return rawQuery(
`
select distinct
select
session_id as id,
website_id as websiteId,
created_at as createdAt,
@ -43,6 +46,7 @@ async function clickhouseQuery(websiteId: string, startDate: Date) {
from website_event
where website_id = {websiteId:UUID}
and created_at >= {startDate:DateTime64}
order by created_at asc
`,
{
websiteId,