banatie-service/apps/api-service/src/services/core/PromptCacheService.ts

99 lines
2.5 KiB
TypeScript

import { eq, and, sql } from 'drizzle-orm';
import { db } from '@/db';
import { promptUrlCache } from '@banatie/database';
import type { PromptUrlCacheEntry, NewPromptUrlCacheEntry } from '@/types/models';
import { computeSHA256 } from '@/utils/helpers';
export class PromptCacheService {
/**
* Compute SHA-256 hash of prompt for cache lookup
*/
computePromptHash(prompt: string): string {
return computeSHA256(prompt);
}
/**
* Check if prompt exists in cache for a project
*/
async getCachedEntry(
promptHash: string,
projectId: string
): Promise<PromptUrlCacheEntry | null> {
const entry = await db.query.promptUrlCache.findFirst({
where: and(
eq(promptUrlCache.promptHash, promptHash),
eq(promptUrlCache.projectId, projectId)
),
});
return entry || null;
}
/**
* Create a new cache entry
*/
async createCacheEntry(data: NewPromptUrlCacheEntry): Promise<PromptUrlCacheEntry> {
const [entry] = await db.insert(promptUrlCache).values(data).returning();
if (!entry) {
throw new Error('Failed to create cache entry');
}
return entry;
}
/**
* Update hit count and last hit time for a cache entry
*/
async recordCacheHit(id: string): Promise<void> {
await db
.update(promptUrlCache)
.set({
hitCount: sql`${promptUrlCache.hitCount} + 1`,
lastHitAt: new Date(),
})
.where(eq(promptUrlCache.id, id));
}
/**
* Get cache statistics for a project
*/
async getCacheStats(projectId: string): Promise<{
totalEntries: number;
totalHits: number;
avgHitCount: number;
}> {
const entries = await db.query.promptUrlCache.findMany({
where: eq(promptUrlCache.projectId, projectId),
});
const totalEntries = entries.length;
const totalHits = entries.reduce((sum, entry) => sum + entry.hitCount, 0);
const avgHitCount = totalEntries > 0 ? totalHits / totalEntries : 0;
return {
totalEntries,
totalHits,
avgHitCount,
};
}
/**
* Clear old cache entries (can be called periodically)
*/
async clearOldEntries(daysOld: number): Promise<number> {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - daysOld);
const result = await db
.delete(promptUrlCache)
.where(
and(
eq(promptUrlCache.hitCount, 0),
// Only delete entries with 0 hits that are old
)
)
.returning();
return result.length;
}
}