/** * AriaEngine Storage Backend — 存储后端抽象层 * @module engine/aria/store/backend * * 封装底层浏览器存储 API(IndexedDB / OPFS / Memory 回退), * 供 Buffer Pool 的 PageIO 和 WAL 的 WALStore 使用。 */ import { DatabaseError } from '../../../constants'; // --------------------------------------------------------------------------- // StorageBackend 接口 // --------------------------------------------------------------------------- export interface IStorageBackend { /** 打开存储 */ open(name: string): Promise; /** 关闭存储 */ close(): Promise; /** 是否已打开 */ isOpen(): boolean; /** 读取数据块 */ read(key: string): Promise; /** 写入数据块 */ write(key: string, data: ArrayBuffer): Promise; /** 删除数据块 */ delete(key: string): Promise; /** 列出所有 key */ listKeys(): Promise; /** 检查 key 是否存在 */ exists(key: string): Promise; /** 清空所有数据 */ clear(): Promise; } // ======================================================================= // IndexedDB Backend // ======================================================================= export class IndexedDBBackend implements IStorageBackend { private db: IDBDatabase | null = null; private dbName = ''; private storeName = 'data'; async open(name: string): Promise { this.dbName = `aria-${name}`; return new Promise((resolve, reject) => { const request = indexedDB.open(this.dbName, 1); request.onupgradeneeded = () => { const db = request.result; if (!db.objectStoreNames.contains(this.storeName)) { db.createObjectStore(this.storeName); } }; request.onsuccess = () => { this.db = request.result; resolve(); }; request.onerror = () => reject(new DatabaseError('Failed to open AriaEngine IndexedDB', 'ARIA_IDB_OPEN_ERROR')); }); } async close(): Promise { if (this.db) { this.db.close(); this.db = null; } } isOpen(): boolean { return this.db !== null; } async read(key: string): Promise { const db = this.ensureDB(); return new Promise((resolve, reject) => { const tx = db.transaction(this.storeName, 'readonly'); const req = tx.objectStore(this.storeName).get(key); req.onsuccess = () => resolve(req.result ?? null); req.onerror = () => reject(new DatabaseError('Failed to read from AriaEngine store', 'ARIA_READ_ERROR')); }); } async write(key: string, data: ArrayBuffer): Promise { const db = this.ensureDB(); return new Promise((resolve, reject) => { const tx = db.transaction(this.storeName, 'readwrite'); tx.objectStore(this.storeName).put(data, key); tx.oncomplete = () => resolve(); tx.onerror = () => reject(new DatabaseError('Failed to write to AriaEngine store', 'ARIA_WRITE_ERROR')); }); } async delete(key: string): Promise { const db = this.ensureDB(); return new Promise((resolve, reject) => { const tx = db.transaction(this.storeName, 'readwrite'); tx.objectStore(this.storeName).delete(key); tx.oncomplete = () => resolve(); tx.onerror = () => reject(new DatabaseError('Failed to delete from AriaEngine store', 'ARIA_DELETE_ERROR')); }); } async listKeys(): Promise { const db = this.ensureDB(); return new Promise((resolve, reject) => { const tx = db.transaction(this.storeName, 'readonly'); const req = tx.objectStore(this.storeName).getAllKeys(); req.onsuccess = () => resolve((req.result ?? []) as string[]); req.onerror = () => reject(new DatabaseError('Failed to list keys', 'ARIA_LIST_ERROR')); }); } async exists(key: string): Promise { const result = await this.read(key); return result !== null; } async clear(): Promise { const db = this.ensureDB(); return new Promise((resolve, reject) => { const tx = db.transaction(this.storeName, 'readwrite'); tx.objectStore(this.storeName).clear(); tx.oncomplete = () => resolve(); tx.onerror = () => reject(new DatabaseError('Failed to clear AriaEngine store', 'ARIA_CLEAR_ERROR')); }); } private ensureDB(): IDBDatabase { if (!this.db) throw new DatabaseError('AriaEngine storage not opened', 'ARIA_DB_NOT_OPEN'); return this.db; } } // ======================================================================= // Memory Backend(回退 / 测试用) // ======================================================================= export class MemoryBackend implements IStorageBackend { private store: Map = new Map(); private opened = false; async open(_name: string): Promise { this.opened = true; } async close(): Promise { this.store.clear(); this.opened = false; } isOpen(): boolean { return this.opened; } async read(key: string): Promise { return this.store.get(key) ?? null; } async write(key: string, data: ArrayBuffer): Promise { this.store.set(key, data); } async delete(key: string): Promise { this.store.delete(key); } async listKeys(): Promise { return Array.from(this.store.keys()); } async exists(key: string): Promise { return this.store.has(key); } async clear(): Promise { this.store.clear(); } }