id-scanner-lib
Version:
Browser-based ID card, QR code, and face recognition scanner with liveness detection
155 lines (144 loc) • 4.56 kB
text/typescript
/**
* @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();