perf: improve monitor query performance
This commit is contained in:
parent
89fed4666d
commit
f5c13cb02f
@ -1,7 +1,13 @@
|
||||
import { createTRPCReact, getQueryKey } from '@trpc/react-query';
|
||||
import type { inferRouterInputs, inferRouterOutputs } from '../../server/trpc';
|
||||
import type { AppRouter } from '../../server/trpc/routers';
|
||||
import { httpBatchLink, loggerLink, TRPCClientErrorLike } from '@trpc/client';
|
||||
import {
|
||||
httpBatchLink,
|
||||
httpLink,
|
||||
loggerLink,
|
||||
splitLink,
|
||||
TRPCClientErrorLike,
|
||||
} from '@trpc/client';
|
||||
import { getJWT } from './auth';
|
||||
import { message } from 'antd';
|
||||
import { isDev } from '../utils/env';
|
||||
@ -13,6 +19,14 @@ export const trpc = createTRPCReact<AppRouter>();
|
||||
export type AppRouterInput = inferRouterInputs<AppRouter>;
|
||||
export type AppRouterOutput = inferRouterOutputs<AppRouter>;
|
||||
|
||||
const url = '/trpc';
|
||||
|
||||
function headers() {
|
||||
return {
|
||||
Authorization: `Bearer ${getJWT()}`,
|
||||
};
|
||||
}
|
||||
|
||||
export const trpcClient = trpc.createClient({
|
||||
links: [
|
||||
loggerLink({
|
||||
@ -20,13 +34,20 @@ export const trpcClient = trpc.createClient({
|
||||
(isDev && typeof window !== 'undefined') ||
|
||||
(opts.direction === 'down' && opts.result instanceof Error),
|
||||
}),
|
||||
httpBatchLink({
|
||||
url: '/trpc',
|
||||
async headers() {
|
||||
return {
|
||||
Authorization: `Bearer ${getJWT()}`,
|
||||
};
|
||||
splitLink({
|
||||
condition(op) {
|
||||
// check for context property `skipBatch`
|
||||
return op.context.skipBatch === true;
|
||||
},
|
||||
true: httpLink({
|
||||
url,
|
||||
headers,
|
||||
}),
|
||||
// when condition is false, use batching
|
||||
false: httpBatchLink({
|
||||
url,
|
||||
headers,
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
@ -15,10 +15,19 @@ export const MonitorDataMetrics: React.FC<{
|
||||
const { t } = useTranslation();
|
||||
const workspaceId = useCurrentWorkspaceId();
|
||||
const { monitorId, monitorType, currectResponse } = props;
|
||||
const { data, isLoading } = trpc.monitor.dataMetrics.useQuery({
|
||||
workspaceId,
|
||||
monitorId,
|
||||
});
|
||||
const { data, isLoading } = trpc.monitor.dataMetrics.useQuery(
|
||||
{
|
||||
workspaceId,
|
||||
monitorId,
|
||||
},
|
||||
{
|
||||
trpc: {
|
||||
context: {
|
||||
skipBatch: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const provider = useMemo(
|
||||
() => getMonitorProvider(monitorType),
|
||||
|
@ -70,6 +70,9 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
||||
active: true,
|
||||
});
|
||||
|
||||
trpcUtils.monitor.all.refetch({
|
||||
workspaceId,
|
||||
});
|
||||
trpcUtils.monitor.get.refetch({
|
||||
workspaceId,
|
||||
monitorId,
|
||||
@ -87,6 +90,9 @@ export const MonitorInfo: React.FC<MonitorInfoProps> = React.memo((props) => {
|
||||
active: false,
|
||||
});
|
||||
|
||||
trpcUtils.monitor.all.refetch({
|
||||
workspaceId,
|
||||
});
|
||||
trpcUtils.monitor.get.refetch({
|
||||
workspaceId,
|
||||
monitorId,
|
||||
|
@ -139,7 +139,7 @@ export const ServerList: React.FC<ServerListProps> = React.memo((props) => {
|
||||
cell: (props) => dayjs(props.getValue()).format('MMM D HH:mm:ss'),
|
||||
}),
|
||||
];
|
||||
}, []);
|
||||
}, [t]);
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
|
@ -10,7 +10,6 @@ import {
|
||||
AlertDialogTrigger,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
|
53
src/server/model/monitor/index.bench.ts
Normal file
53
src/server/model/monitor/index.bench.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { describe, bench } from 'vitest';
|
||||
import { prisma } from '../_client';
|
||||
|
||||
const workspaceId = process.env.BENCH_MONITOR_WORKSPACEID;
|
||||
const monitorId = process.env.BENCH_MONITOR_ID;
|
||||
|
||||
describe.runIf(workspaceId && monitorId)('getMonitorRecentData', () => {
|
||||
bench('find with join', async () => {
|
||||
await prisma.monitorData
|
||||
.findMany({
|
||||
where: {
|
||||
monitor: {
|
||||
id: monitorId,
|
||||
workspaceId,
|
||||
},
|
||||
},
|
||||
take: 20,
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
select: {
|
||||
value: true,
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
.then((arr) => arr.reverse());
|
||||
});
|
||||
|
||||
bench('find with double check', async () => {
|
||||
await prisma.monitor.findFirstOrThrow({
|
||||
where: {
|
||||
workspaceId,
|
||||
id: monitorId,
|
||||
},
|
||||
});
|
||||
|
||||
await prisma.monitorData
|
||||
.findMany({
|
||||
where: {
|
||||
monitorId,
|
||||
},
|
||||
take: 20,
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
select: {
|
||||
value: true,
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
.then((arr) => arr.reverse());
|
||||
});
|
||||
});
|
@ -48,17 +48,22 @@ export function getMonitorRecentData(
|
||||
monitorId: string,
|
||||
take: number
|
||||
) {
|
||||
return prisma.monitorData.findMany({
|
||||
where: {
|
||||
monitor: {
|
||||
id: monitorId,
|
||||
workspaceId,
|
||||
return prisma.monitorData
|
||||
.findMany({
|
||||
where: {
|
||||
monitor: {
|
||||
id: monitorId,
|
||||
workspaceId,
|
||||
},
|
||||
},
|
||||
},
|
||||
take: -take,
|
||||
select: {
|
||||
value: true,
|
||||
createdAt: true,
|
||||
},
|
||||
});
|
||||
take,
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
select: {
|
||||
value: true,
|
||||
createdAt: true,
|
||||
},
|
||||
})
|
||||
.then((arr) => arr.reverse());
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
-- CreateIndex
|
||||
CREATE INDEX "MonitorData_monitorId_createdAt_idx" ON "MonitorData"("monitorId", "createdAt" DESC);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "MonitorData_monitorId_createdAt_value_idx" ON "MonitorData"("monitorId", "createdAt", "value");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "MonitorEvent_monitorId_idx" ON "MonitorEvent"("monitorId");
|
@ -318,6 +318,8 @@ model MonitorEvent {
|
||||
createdAt DateTime @default(now()) @db.Timestamptz(6)
|
||||
|
||||
monitor Monitor @relation(fields: [monitorId], references: [id], onUpdate: Cascade, onDelete: Cascade)
|
||||
|
||||
@@index([monitorId])
|
||||
}
|
||||
|
||||
model MonitorData {
|
||||
@ -329,6 +331,8 @@ model MonitorData {
|
||||
monitor Monitor @relation(fields: [monitorId], references: [id], onUpdate: Cascade, onDelete: Cascade)
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([monitorId, createdAt(sort: Desc)])
|
||||
@@index([monitorId, createdAt, value])
|
||||
}
|
||||
|
||||
// Use for record latest monitor status, for example tls status
|
||||
|
@ -300,14 +300,13 @@ export const monitorRouter = router({
|
||||
return monitor;
|
||||
}),
|
||||
recentData: publicProcedure
|
||||
.meta({
|
||||
openapi: {
|
||||
tags: [OPENAPI_TAG.MONITOR],
|
||||
protect: false,
|
||||
.meta(
|
||||
buildMonitorOpenapi({
|
||||
method: 'GET',
|
||||
path: `/monitor/{monitorId}/recentData`,
|
||||
},
|
||||
})
|
||||
protect: false,
|
||||
path: '/{monitorId}/recentData',
|
||||
})
|
||||
)
|
||||
.input(
|
||||
z.object({
|
||||
workspaceId: z.string().cuid2(),
|
||||
|
Loading…
Reference in New Issue
Block a user