From 15f22988b0d61f5d201986c97afbb5efc2f8fd59 Mon Sep 17 00:00:00 2001 From: Yuri Date: Wed, 5 Nov 2025 22:38:09 +0100 Subject: [PATCH] fix(cache): use setWithTTL for Redis to properly set TTL on cache entries - Add optional setWithTTL method to CacheStore interface - Create helper function to use setWithTTL when available - Replace all store.set() calls with TTL-aware helper - Export missing types (CacheBackendConfig, CacheStore, CacheEntry) and createCacheBackend function - Forward TTL option from createCached to createCachedFunction for consistency - Fixes issue where Redis keys were stored without expiration - Fixes issue where TTL needed to be specified twice when using createCached --- packages/cache/src/cache.ts | 38 ++++++++++++++++++++++++++++--------- packages/cache/src/index.ts | 6 ++++++ packages/cache/src/types.ts | 3 +++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/packages/cache/src/cache.ts b/packages/cache/src/cache.ts index 3802324..454daa5 100644 --- a/packages/cache/src/cache.ts +++ b/packages/cache/src/cache.ts @@ -1,7 +1,25 @@ import type { Tool } from "ai"; import { createCacheBackend } from "./backends/factory"; import { LRUCacheStore } from "./cache-store"; -import type { CachedTool, CacheOptions, CacheStats, CacheStore } from "./types"; +import type { CachedTool, CacheOptions, CacheStats, CacheStore, CacheEntry } from "./types"; + +/** + * Helper function to set cache entry with TTL support + * Uses setWithTTL if available (Redis), otherwise falls back to regular set + */ +async function setCacheEntryWithTTL( + store: CacheStore, + key: string, + entry: CacheEntry, + ttlMs: number, +): Promise { + if (store.setWithTTL && ttlMs > 0) { + const ttlSeconds = Math.floor(ttlMs / 1000); + await store.setWithTTL(key, entry, ttlSeconds); + } else { + await store.set(key, entry); + } +} /** * Default cache key generator - stable and deterministic @@ -237,11 +255,11 @@ function createStreamingCachedTool( }; if (shouldCache(params, completeResult)) { - await cacheStore.set(key, { + await setCacheEntryWithTTL(cacheStore, key, { result: completeResult, timestamp: now, key, - }); + }, ttl); if (debug) { const cacheItems = typeof cacheStore.size === "function" @@ -491,11 +509,11 @@ export function cached( }; if (shouldCache(params, completeResult)) { - await cacheStore.set(key, { + await setCacheEntryWithTTL(cacheStore, key, { result: completeResult, timestamp: now, key, - }); + }, effectiveTTL); log( `[Cache] STORED streaming result with ${capturedMessages.length} messages`, ); @@ -508,11 +526,11 @@ export function cached( // Regular tool if (shouldCache(params, result)) { - await cacheStore.set(key, { + await setCacheEntryWithTTL(cacheStore, key, { result, timestamp: now, key, - }); + }, effectiveTTL); log(`[Cache] STORED result`); } @@ -543,11 +561,11 @@ export function cached( const result = await target.execute?.(params, executionOptions); if (shouldCache(params, result)) { - await cacheStore.set(key, { + await setCacheEntryWithTTL(cacheStore, key, { result, timestamp: now, key, - }); + }, effectiveTTL); log(`[Cache] STORED result`); } @@ -636,6 +654,7 @@ export function createCached( }); return createCachedFunction(lruStore, { + ttl: options.ttl, debug: options.debug || false, cacheKey: options.cacheKey, onHit: options.onHit, @@ -654,6 +673,7 @@ export function createCached( }); return createCachedFunction(redisStore, { + ttl: options.ttl, debug: options.debug || false, cacheKey: options.cacheKey, onHit: options.onHit, diff --git a/packages/cache/src/index.ts b/packages/cache/src/index.ts index 3f642ef..e4e4a81 100644 --- a/packages/cache/src/index.ts +++ b/packages/cache/src/index.ts @@ -9,7 +9,13 @@ export { cached, createCached, cacheTools } from "./cache"; export type { CacheOptions, CachedTool, + CacheStore, + CacheEntry, } from "./types"; +export { createCacheBackend } from "./backends/factory"; +export type { CacheBackendConfig } from "./backends/factory"; +export { LRUCacheStore, SimpleCacheStore, RedisCacheStore, MemoryCacheStore } from "./backends/index"; + // Re-export useful types from ai package export type { Tool } from "ai"; diff --git a/packages/cache/src/types.ts b/packages/cache/src/types.ts index 22868e1..2337de8 100644 --- a/packages/cache/src/types.ts +++ b/packages/cache/src/types.ts @@ -94,6 +94,9 @@ export interface CacheStore { /** Set cache entry */ set(key: string, entry: CacheEntry): void | Promise; + /** Set cache entry with TTL (time-to-live) in seconds */ + setWithTTL?(key: string, entry: CacheEntry, ttlSeconds: number): void | Promise; + /** Delete cache entry */ delete(key: string): boolean | Promise;