Files
Nano-Banana-AI-Image-Editor/src/services/cacheService.ts
2025-09-19 01:25:30 +08:00

119 lines
3.7 KiB
TypeScript

import { get, set, del, keys } from 'idb-keyval';
import { Project, Generation, Asset } from '../types';
const CACHE_PREFIX = 'nano-banana';
const CACHE_VERSION = '1.0';
// 限制缓存项目数量
const MAX_CACHED_ITEMS = 50;
// 限制缓存最大年龄 (3天)
const MAX_CACHE_AGE = 3 * 24 * 60 * 60 * 1000;
export class CacheService {
private static getKey(type: string, id: string): string {
return `${CACHE_PREFIX}-${CACHE_VERSION}-${type}-${id}`;
}
// Project caching
static async saveProject(project: Project): Promise<void> {
// 在保存新项目之前,清理旧缓存
await this.clearOldCache();
await set(this.getKey('project', project.id), project);
}
static async getProject(id: string): Promise<Project | null> {
return (await get(this.getKey('project', id))) || null;
}
static async getAllProjects(): Promise<Project[]> {
const allKeys = await keys();
const projectKeys = allKeys.filter(key =>
typeof key === 'string' && key.includes(`${CACHE_PREFIX}-${CACHE_VERSION}-project-`)
);
const projects = await Promise.all(
projectKeys.map(key => get(key as string))
);
return projects.filter(Boolean) as Project[];
}
// Asset caching (for offline access)
static async cacheAsset(asset: Asset, data: Blob): Promise<void> {
// 在保存新资产之前,清理旧缓存
await this.clearOldCache();
await set(this.getKey('asset', asset.id), {
asset,
data,
cachedAt: Date.now()
});
}
static async getCachedAsset(assetId: string): Promise<{ asset: Asset; data: Blob } | null> {
const cached = await get(this.getKey('asset', assetId));
return cached || null;
}
// Generation metadata caching
static async cacheGeneration(generation: Generation): Promise<void> {
// 在保存新生成记录之前,清理旧缓存
await this.clearOldCache();
await set(this.getKey('generation', generation.id), generation);
}
static async getGeneration(id: string): Promise<Generation | null> {
return (await get(this.getKey('generation', id))) || null;
}
// Clear old cache entries
static async clearOldCache(maxAge: number = MAX_CACHE_AGE): Promise<void> {
const allKeys = await keys();
const now = Date.now();
// 收集需要删除的键
const keysToDelete: string[] = [];
const validCachedItems: Array<{key: string, cachedAt: number}> = [];
for (const key of allKeys) {
if (typeof key === 'string' && key.startsWith(CACHE_PREFIX)) {
const cached = await get(key);
if (cached?.cachedAt) {
// 检查是否过期
if ((now - cached.cachedAt) > maxAge) {
keysToDelete.push(key);
} else {
validCachedItems.push({key, cachedAt: cached.cachedAt});
}
}
}
}
// 如果有效项目数量超过限制,删除最旧的项目
if (validCachedItems.length > MAX_CACHED_ITEMS) {
// 按时间排序,最旧的在前面
validCachedItems.sort((a, b) => a.cachedAt - b.cachedAt);
// 计算需要删除的数量
const excessCount = validCachedItems.length - MAX_CACHED_ITEMS;
// 添加最旧的项目到删除列表
for (let i = 0; i < excessCount; i++) {
keysToDelete.push(validCachedItems[i].key);
}
}
// 执行删除
for (const key of keysToDelete) {
await del(key);
}
}
// 清空所有缓存
static async clearAllCache(): Promise<void> {
const allKeys = await keys();
const cacheKeys = allKeys.filter(key =>
typeof key === 'string' && key.startsWith(CACHE_PREFIX)
);
for (const key of cacheKeys) {
await del(key);
}
}
}