11import { drizzle } from "drizzle-orm/neon-http" ;
22import { neon } from "@neondatabase/serverless" ;
33import { config } from "dotenv" ;
4- import { and , desc , eq , gte } from "drizzle-orm" ;
4+ import { avg , desc , gte } from "drizzle-orm" ;
55import { databases , functions , stats , type Database , type Function , type Stat } from "./schema" ;
66
77config ( { path : ".env" } ) ;
88
99const sql = neon ( process . env . DATABASE_URL ! ) ;
1010export const db = drizzle ( sql ) ;
1111
12- /**
13- * Get all databases for a specific function
14- */
15- export async function getAllDatabases ( functionId : number ) : Promise < Database [ ] > {
16- return await db . select ( ) . from ( databases ) . where ( eq ( databases . functionId , functionId ) ) ;
12+ export async function getAllDatabases ( ) : Promise < Database [ ] > {
13+ return await db . select ( ) . from ( databases ) ;
1714}
1815
19- /**
20- * Get all functions
21- */
2216export async function getAllFunctions ( ) : Promise < Function [ ] > {
2317 return await db . select ( ) . from ( functions ) ;
2418}
2519
26- /**
27- * Get stats for the last 24 hours for a specific database
28- */
29- export async function getLastDayStats ( databaseId : number ) : Promise < Stat [ ] > {
30- const oneDayAgo = new Date ( ) ;
31- oneDayAgo . setDate ( oneDayAgo . getDate ( ) - 1 ) ;
20+ export type AvgStat = {
21+ functionId : number ;
22+ databaseId : number ;
23+ queryType : 'cold' | 'hot' ;
24+ avgLatencyMs : string | null ; // `decimal` columns come back as strings
25+ } ;
3226
33- return await db
34- . select ( )
35- . from ( stats )
36- . where (
37- and (
38- eq ( stats . databaseId , databaseId ) ,
39- gte ( stats . dateTime , oneDayAgo )
40- )
41- )
42- . orderBy ( desc ( stats . dateTime ) ) ;
43- }
44-
45- /**
46- * Get stats for the last 30 days for a specific database
47- */
48- export async function getLast30DaysStats ( databaseId : number ) : Promise < Stat [ ] > {
27+ export async function getLast30DaysAvgLatency ( ) : Promise < AvgStat [ ] > {
4928 const thirtyDaysAgo = new Date ( ) ;
5029 thirtyDaysAgo . setDate ( thirtyDaysAgo . getDate ( ) - 30 ) ;
5130
52- return await db
53- . select ( )
31+ return db
32+ . select ( {
33+ functionId : stats . functionId ,
34+ databaseId : stats . databaseId ,
35+ queryType : stats . queryType ,
36+ avgLatencyMs : avg ( stats . latencyMs ) . as ( 'avg_latency_ms' ) ,
37+ } )
5438 . from ( stats )
55- . where (
56- and (
57- eq ( stats . databaseId , databaseId ) ,
58- gte ( stats . dateTime , thirtyDaysAgo )
59- )
60- )
61- . orderBy ( desc ( stats . dateTime ) ) ;
39+ . where ( gte ( stats . dateTime , thirtyDaysAgo ) )
40+ . groupBy ( stats . functionId , stats . databaseId , stats . queryType ) ;
6241}
63-
64- /**
65- * Get stats with database and function details
66- */
67- export async function getStatsWithDetails ( stats : Stat [ ] ) : Promise < ( Stat & { database : Database ; function : Function } ) [ ] > {
68- const databaseIds = new Set ( stats . map ( stat => stat . databaseId ) ) ;
69- const functionIds = new Set ( stats . map ( stat => stat . functionId ) ) ;
70-
71- const [ dbDetails , functionDetails ] = await Promise . all ( [
72- db . select ( ) . from ( databases ) . where ( eq ( databases . id , Array . from ( databaseIds ) [ 0 ] ) ) ,
73- db . select ( ) . from ( functions ) . where ( eq ( functions . id , Array . from ( functionIds ) [ 0 ] ) )
74- ] ) ;
75-
76- const dbMap = new Map ( dbDetails . map ( db => [ db . id , db ] ) ) ;
77- const functionMap = new Map ( functionDetails . map ( fn => [ fn . id , fn ] ) ) ;
78-
79- return stats . map ( stat => ( {
80- ...stat ,
81- database : dbMap . get ( stat . databaseId ) ! ,
82- function : functionMap . get ( stat . functionId ) !
83- } ) ) ;
84- }
0 commit comments