Skip to content

Commit

Permalink
feat(web): improve queries (#162)
Browse files Browse the repository at this point in the history
  • Loading branch information
cstrnt authored Aug 28, 2024
1 parent 3c9e92c commit 393db14
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 153 deletions.
6 changes: 3 additions & 3 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"postbuild": "next-sitemap",
"dev": "next dev",
"postinstall": "pnpm run db:generate",
"db:generate": "prisma generate",
"db:generate": "prisma generate && prisma generate --sql",
"start": "next start",
"seed:events": "ts-node --compiler-options {\\\"module\\\":\\\"CommonJS\\\"} prisma/seedEvents.ts",
"db:migrate": "prisma migrate dev",
Expand All @@ -34,7 +34,7 @@
"@monaco-editor/react": "^4.5.1",
"@next-auth/prisma-adapter": "1.0.5",
"@next/mdx": "14.0.4",
"@prisma/client": "5.18.0",
"@prisma/client": "5.19.0",
"@radix-ui/react-avatar": "^1.0.3",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.6",
Expand Down Expand Up @@ -142,7 +142,7 @@
"jsdom": "^20.0.3",
"postcss": "^8.4.21",
"prettier-plugin-tailwindcss": "^0.1.13",
"prisma": "5.18.0",
"prisma": "5.19.0",
"tailwindcss": "^3.3.1",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/web/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

generator client {
provider = "prisma-client-js"
previewFeatures = ["driverAdapters"]
previewFeatures = ["driverAdapters", "typedSql"]
}

datasource db {
Expand Down
23 changes: 23 additions & 0 deletions apps/web/prisma/sql/getEventsByTestIdForAllTime.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- @param {String} $1:testId
-- @param {Int} $2:type

SELECT
COUNT(*) AS eventCount,
TYPE,
createdAt,
selectedVariant
FROM
`Event`
WHERE
testId = ?
AND TYPE = ?
AND(DATE(createdAt) BETWEEN DATE((
SELECT
createdAt FROM `Event`
ORDER BY
createdAt ASC
LIMIT 1))
AND DATE(NOW()))
GROUP BY
DATE(createdAt),
selectedVariant
17 changes: 17 additions & 0 deletions apps/web/prisma/sql/getEventsByTestIdForDay.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
-- @param {String} $1:testId
-- @param {Int} $2:type

SELECT
COUNT(*) AS eventCount,
TYPE,
createdAt,
selectedVariant
FROM
`Event`
WHERE
testId = ?
AND TYPE = ?
AND DATE(createdAt) = DATE(NOW())
GROUP BY
HOUR(createdAt),
selectedVariant
16 changes: 16 additions & 0 deletions apps/web/prisma/sql/getEventsByTestIdForLast30Days.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- @param {String} $1:testId
-- @param {Int} $2:type
SELECT
COUNT(*) AS eventCount,
TYPE,
createdAt,
selectedVariant
FROM
`Event`
WHERE
testId = ?
AND TYPE = ?
AND DATE(NOW()) - INTERVAL 1 MONTH
GROUP BY
DATE(createdAt),
selectedVariant
45 changes: 3 additions & 42 deletions apps/web/src/lib/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import dayjs from "dayjs";
export enum TIME_INTERVAL {
DAY = "day",
ALL_TIME = "all",
LAST_30_DAYS = "30d",
}

export const INTERVALS = [
Expand All @@ -16,7 +17,7 @@ export const INTERVALS = [
// },
{
label: "Last 30 days",
value: "30d",
value: TIME_INTERVAL.LAST_30_DAYS,
},
// {
// label: "Year to Date",
Expand All @@ -42,25 +43,12 @@ export function isSpecialTimeInterval(
return Object.values(TIME_INTERVAL).includes(timeInterval as TIME_INTERVAL);
}

export function getMSFromSpecialTimeInterval(
timeInterval: TIME_INTERVAL
): number {
switch (timeInterval) {
case TIME_INTERVAL.DAY: {
return 1000 * 60 * 60 * 24;
}
case TIME_INTERVAL.ALL_TIME: {
return Number.POSITIVE_INFINITY;
}
}
}

export function getFormattingByInterval(interval: string) {
switch (interval) {
case TIME_INTERVAL.DAY: {
return "HH:mm";
}
case "30d": {
case TIME_INTERVAL.LAST_30_DAYS: {
return "DD MMM";
}
case TIME_INTERVAL.ALL_TIME: {
Expand Down Expand Up @@ -111,30 +99,3 @@ export function getBaseEventsByInterval(
}
}
}

export function getLabelsByInterval(
interval: (typeof INTERVALS)[number]["value"],
fistEventDate: Date
): Array<string> {
const formatting = getFormattingByInterval(interval);
switch (interval) {
case TIME_INTERVAL.DAY: {
const baseData = dayjs().set("minute", 0);
return [0, 3, 6, 9, 12, 15, 18, 21].map((hour) =>
baseData.set("hour", hour).format(formatting)
);
}
case "30d": {
return Array.from({ length: 30 }, (_, i) =>
dayjs().subtract(i, "day").format(formatting)
).reverse();
}
case TIME_INTERVAL.ALL_TIME: {
const diff = dayjs().diff(dayjs(fistEventDate), "month");

return Array.from({ length: Math.max(diff, 6) }, (_, i) =>
dayjs(fistEventDate).add(i, "month").format(formatting)
).reverse();
}
}
}
73 changes: 25 additions & 48 deletions apps/web/src/server/services/EventService.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { AbbyEvent } from "@tryabby/core";
import dayjs from "dayjs";
import {
TIME_INTERVAL,
getMSFromSpecialTimeInterval,
isSpecialTimeInterval,
} from "lib/events";
import ms from "ms";
getEventsByTestIdForAllTime,
getEventsByTestIdForDay,
getEventsByTestIdForLast30Days,
} from "@prisma/client/sql";
import type { AbbyEvent, AbbyEventType } from "@tryabby/core";
import { TIME_INTERVAL, isSpecialTimeInterval } from "lib/events";
import { PLANS, type PlanName, getLimitByPlan } from "server/common/plans";
import { prisma } from "server/db/client";
import { RequestCache } from "./RequestCache";
Expand Down Expand Up @@ -43,50 +42,28 @@ export abstract class EventService {
});
}

static async getEventsByTestId(testId: string, timeInterval: string) {
const now = new Date().getTime();

static async getEventsByTestId(
testId: string,
timeInterval: string,
eventType: AbbyEventType
// all function should have the same type
): Promise<getEventsByTestIdForDay.Result[]> {
if (isSpecialTimeInterval(timeInterval)) {
const specialIntervalInMs = getMSFromSpecialTimeInterval(timeInterval);
return prisma.event.findMany({
where: {
testId,
...(specialIntervalInMs !== Number.POSITIVE_INFINITY &&
timeInterval !== TIME_INTERVAL.DAY && {
createdAt: {
gte: new Date(now - getMSFromSpecialTimeInterval(timeInterval)),
},
}),
// Special case for day, since we want to include the current day
...(timeInterval === TIME_INTERVAL.DAY && {
createdAt: {
gte: dayjs().startOf("day").toDate(),
},
}),
},
orderBy: {
createdAt: "asc",
},
});
}

const parsedInterval = ms(timeInterval) as number | undefined;

if (parsedInterval === undefined) {
throw new Error("Invalid time interval");
if (timeInterval === TIME_INTERVAL.DAY) {
return await prisma.$queryRawTyped(
getEventsByTestIdForDay(testId, eventType)
);
}
if (timeInterval === TIME_INTERVAL.LAST_30_DAYS) {
return await prisma.$queryRawTyped(
getEventsByTestIdForLast30Days(testId, eventType)
);
}
}

return prisma.event.findMany({
where: {
testId,
createdAt: {
gte: new Date(now - parsedInterval),
},
},
orderBy: {
createdAt: "asc",
},
});
return await prisma.$queryRawTyped(
getEventsByTestIdForAllTime(testId, eventType)
);
}

static async getEventsForCurrentPeriod(projectId: string) {
Expand Down
Loading

0 comments on commit 393db14

Please sign in to comment.