11import { createHash } from "node:crypto" ;
22import { ApiError , WorkspaceClient } from "@databricks/sdk-experimental" ;
3- import type { CacheConfig , CacheStorage } from "shared" ;
3+ import type { CacheConfig , CacheEntry , CacheStorage } from "shared" ;
44import { createLakebasePool } from "../connectors/lakebase" ;
55import { AppKitError , ExecutionError , InitializationError } from "../errors" ;
66import { createLogger } from "../logging/logger" ;
@@ -202,8 +202,7 @@ export class CacheManager {
202202 } ,
203203 async ( span ) => {
204204 try {
205- // check if the value is in the cache
206- const cached = await this . storage . get < T > ( cacheKey ) ;
205+ const cached = await this . getValid < T > ( cacheKey ) ;
207206 if ( cached !== null ) {
208207 span . setAttribute ( "cache.hit" , true ) ;
209208 span . setStatus ( { code : SpanStatusCode . OK } ) ;
@@ -216,7 +215,7 @@ export class CacheManager {
216215 cache_key : cacheKey ,
217216 } ) ;
218217
219- return cached . value as T ;
218+ return cached . value ;
220219 }
221220
222221 // check if the value is being processed by another request
@@ -308,14 +307,26 @@ export class CacheManager {
308307 // probabilistic cleanup trigger
309308 this . maybeCleanup ( ) ;
310309
310+ const entry = await this . getValid < T > ( key ) ;
311+ return entry ?. value ?? null ;
312+ }
313+
314+ /**
315+ * Get a cached entry only if it has not expired.
316+ * Returns null on miss or expired (and deletes the expired entry).
317+ *
318+ * Storage implementations return entries unconditionally — expiry handling
319+ * lives at the CacheManager layer.
320+ */
321+ private async getValid < T > ( key : string ) : Promise < CacheEntry < T > | null > {
311322 const entry = await this . storage . get < T > ( key ) ;
312323 if ( ! entry ) return null ;
313324
314325 if ( Date . now ( ) > entry . expiry ) {
315326 await this . storage . delete ( key ) ;
316327 return null ;
317328 }
318- return entry . value as T ;
329+ return entry ;
319330 }
320331
321332 /** Probabilistically trigger cleanup of expired entries (fire-and-forget) */
@@ -386,14 +397,8 @@ export class CacheManager {
386397 async has ( key : string ) : Promise < boolean > {
387398 if ( ! this . config . enabled ) return false ;
388399
389- const entry = await this . storage . get ( key ) ;
390- if ( ! entry ) return false ;
391-
392- if ( Date . now ( ) > entry . expiry ) {
393- await this . storage . delete ( key ) ;
394- return false ;
395- }
396- return true ;
400+ const entry = await this . getValid ( key ) ;
401+ return entry !== null ;
397402 }
398403
399404 /**
0 commit comments