@@ -9,40 +9,62 @@ import {
99 or ,
1010 websites ,
1111} from '@databuddy/db' ;
12+ import { createDrizzleCache , redis } from '@databuddy/redis' ;
1213import { z } from 'zod' ;
1314import { createTRPCRouter , protectedProcedure } from '../trpc' ;
1415
15- async function getAuthorizedWebsiteIds (
16+ const drizzleCache = createDrizzleCache ( { redis, namespace : 'mini-charts' } ) ;
17+
18+ const CACHE_TTL = 300 ;
19+ const AUTH_CACHE_TTL = 60 ;
20+
21+ interface MiniChartRow {
22+ websiteId : string ;
23+ date : string ;
24+ value : number ;
25+ }
26+
27+ const getAuthorizedWebsiteIds = (
1628 userId : string ,
1729 requestedIds : string [ ]
18- ) : Promise < string [ ] > {
30+ ) : Promise < string [ ] > => {
1931 if ( ! userId || requestedIds . length === 0 ) {
20- return [ ] ;
32+ return Promise . resolve ( [ ] ) ;
2133 }
2234
23- const userOrgs = await db . query . member . findMany ( {
24- where : eq ( member . userId , userId ) ,
25- columns : { organizationId : true } ,
26- } ) ;
27- const orgIds = userOrgs . map ( ( m ) => m . organizationId ) ;
28-
29- const accessibleWebsites = await db . query . websites . findMany ( {
30- where : and (
31- inArray ( websites . id , requestedIds ) ,
32- or (
33- eq ( websites . userId , userId ) ,
34- orgIds . length > 0
35- ? inArray ( websites . organizationId , orgIds )
36- : isNull ( websites . organizationId )
37- )
38- ) ,
39- columns : {
40- id : true ,
35+ const authCacheKey = `auth:${ userId } :${ requestedIds . sort ( ) . join ( ',' ) } ` ;
36+
37+ return drizzleCache . withCache ( {
38+ key : authCacheKey ,
39+ ttl : AUTH_CACHE_TTL ,
40+ tables : [ 'websites' , 'member' ] ,
41+ queryFn : async ( ) => {
42+ const userOrgs = await db . query . member . findMany ( {
43+ where : eq ( member . userId , userId ) ,
44+ columns : { organizationId : true } ,
45+ } ) ;
46+
47+ const orgIds = userOrgs . map ( ( m ) => m . organizationId ) ;
48+
49+ const accessibleWebsites = await db . query . websites . findMany ( {
50+ where : and (
51+ inArray ( websites . id , requestedIds ) ,
52+ or (
53+ eq ( websites . userId , userId ) ,
54+ orgIds . length > 0
55+ ? inArray ( websites . organizationId , orgIds )
56+ : isNull ( websites . organizationId )
57+ )
58+ ) ,
59+ columns : {
60+ id : true ,
61+ } ,
62+ } ) ;
63+
64+ return accessibleWebsites . map ( ( w ) => w . id ) ;
4165 } ,
4266 } ) ;
43-
44- return accessibleWebsites . map ( ( w ) => w . id ) ;
45- }
67+ } ;
4668
4769const getBatchedMiniChartData = async ( websiteIds : string [ ] ) => {
4870 if ( websiteIds . length === 0 ) {
@@ -80,12 +102,6 @@ const getBatchedMiniChartData = async (websiteIds: string[]) => {
80102 date ASC
81103 ` ;
82104
83- interface MiniChartRow {
84- websiteId : string ;
85- date : string ;
86- value : number ;
87- }
88-
89105 const queryResult = await chQuery < MiniChartRow > ( query , { websiteIds } ) ;
90106
91107 const result = websiteIds . reduce (
@@ -115,12 +131,18 @@ export const miniChartsRouter = createTRPCRouter({
115131 websiteIds : z . array ( z . string ( ) ) ,
116132 } )
117133 )
118- . query ( async ( { ctx, input } ) => {
119- const authorizedIds = await getAuthorizedWebsiteIds (
120- ctx . user . id ,
121- input . websiteIds
122- ) ;
123- const charts = await getBatchedMiniChartData ( authorizedIds ) ;
124- return charts ;
134+ . query ( ( { ctx, input } ) => {
135+ const cacheKey = `mini-charts:${ ctx . user . id } :${ input . websiteIds . sort ( ) . join ( ',' ) } ` ;
136+
137+ return drizzleCache . withCache ( {
138+ key : cacheKey ,
139+ ttl : CACHE_TTL ,
140+ tables : [ 'websites' , 'member' ] ,
141+ queryFn : ( ) => {
142+ return getAuthorizedWebsiteIds ( ctx . user . id , input . websiteIds ) . then (
143+ ( authorizedIds ) => getBatchedMiniChartData ( authorizedIds )
144+ ) ;
145+ } ,
146+ } ) ;
125147 } ) ,
126148} ) ;
0 commit comments