UNPKG

id-scanner-lib

Version:

Browser-based ID card, QR code, and face recognition scanner with liveness detection

155 lines (144 loc) 4.56 kB
/** * @file 模型分片缓存管理器 * @description 提供分片模型的 IndexedDB 持久化缓存功能(idb-keyval 风格实现) * @module core/utils/resource-manager */ /** * 模型分片信息 */ export interface ModelShard { name: string; // e.g. 'face-detector' version: string; // e.g. '1.0.0' url: string; // 完整 URL size: number; // bytes hash?: string; // 完整性校验 } /** * 模型缓存信息 */ export interface ModelCacheInfo { name: string; version: string; cachedAt: number; size: number; } /** * IndexedDB 模型缓存管理器 * 提供分片模型的持久化缓存功能 */ export class ModelCacheManager { private _dbName = 'id-scanner-lib-models'; private _storeName = 'model-cache'; private _db: IDBDatabase | null = null; /** * 初始化缓存管理器(打开 IndexedDB) */ async init(): Promise<void> { return new Promise((resolve, reject) => { const request = indexedDB.open(this._dbName, 1); request.onerror = () => reject(new Error('Failed to open IndexedDB')); request.onsuccess = () => { this._db = request.result; resolve(); }; request.onupgradeneeded = (event) => { const db = (event.target as IDBOpenDBRequest).result; if (!db.objectStoreNames.contains(this._storeName)) { const store = db.createObjectStore(this._storeName, { keyPath: 'key' }); store.createIndex('name', 'name', { unique: false }); store.createIndex('version', 'version', { unique: false }); } }; }); } /** * 生成缓存键 */ private _makeKey(model: ModelShard): string { return `${model.name}@${model.version}`; } /** * 检查模型是否已缓存 */ async has(model: ModelShard): Promise<boolean> { if (!this._db) return false; return new Promise((resolve, reject) => { const tx = this._db!.transaction(this._storeName, 'readonly'); const store = tx.objectStore(this._storeName); const req = store.get(this._makeKey(model)); req.onsuccess = () => resolve(!!req.result); req.onerror = () => reject(req.error); }); } /** * 存储模型数据 */ async store(model: ModelShard, data: ArrayBuffer): Promise<void> { if (!this._db) throw new Error('ModelCacheManager not initialized'); return new Promise((resolve, reject) => { const tx = this._db!.transaction(this._storeName, 'readwrite'); const store = tx.objectStore(this._storeName); const record = { key: this._makeKey(model), name: model.name, version: model.version, url: model.url, size: model.size, data, cachedAt: Date.now(), }; const req = store.put(record); req.onsuccess = () => resolve(); req.onerror = () => reject(req.error); }); } /** * 加载模型数据 */ async load(model: ModelShard): Promise<ArrayBuffer | null> { if (!this._db) throw new Error('ModelCacheManager not initialized'); return new Promise((resolve, reject) => { const tx = this._db!.transaction(this._storeName, 'readonly'); const store = tx.objectStore(this._storeName); const req = store.get(this._makeKey(model)); req.onsuccess = () => resolve(req.result ? req.result.data : null); req.onerror = () => reject(req.error); }); } /** * 清除所有缓存 */ async clear(): Promise<void> { if (!this._db) return; return new Promise((resolve, reject) => { const tx = this._db!.transaction(this._storeName, 'readwrite'); const store = tx.objectStore(this._storeName); const req = store.clear(); req.onsuccess = () => resolve(); req.onerror = () => reject(req.error); }); } /** * 列出已缓存模型 */ async listCached(): Promise<ModelCacheInfo[]> { if (!this._db) return []; return new Promise((resolve, reject) => { const tx = this._db!.transaction(this._storeName, 'readonly'); const store = tx.objectStore(this._storeName); const req = store.getAll(); req.onsuccess = () => { const results: ModelCacheInfo[] = req.result.map((r: any) => ({ name: r.name, version: r.version, cachedAt: r.cachedAt, size: r.size, })); resolve(results); }; req.onerror = () => reject(req.error); }); } } /** 全局模型缓存管理器实例 */ export const modelCache = new ModelCacheManager();