release: v0.6.0 — 完全移除 IndexedDB,自研 KVStore 事务存储引擎(多key原子写/快照日志恢复/CRC自愈)+ KVStoreEngine + 旧库迁移工具 + 10万级压力验证 + 崩溃注入e2e
This commit is contained in:
@@ -11,7 +11,10 @@
|
||||
import { AriaEngine } from '../../src/engine/aria/index';
|
||||
import { DatabaseLock, lockName } from '../../src/engine/aria/locks';
|
||||
import { createSchema } from '../../src/table/schema';
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
import { installOPFSMock } from '../helpers/opfs-mock';
|
||||
|
||||
beforeEach(() => { installOPFSMock(new Map()); });
|
||||
|
||||
let idbCounter = 0;
|
||||
function uniqueDB(): string {
|
||||
@@ -25,8 +28,12 @@ let lockHolders: Map<string, true>;
|
||||
|
||||
function installLocksMock() {
|
||||
lockHolders = new Map();
|
||||
// 保留 storage(OPFS mock 设置过),与 locks 共存
|
||||
const existingNav = (globalThis as { navigator?: { storage?: unknown } }).navigator;
|
||||
const storage = existingNav?.storage;
|
||||
Object.defineProperty(globalThis, 'navigator', {
|
||||
value: {
|
||||
storage,
|
||||
locks: {
|
||||
request: async (_name: string, opts: { ifAvailable?: boolean }, cb: (lock: { name: string } | null) => Promise<void> | void) => {
|
||||
const name = _name;
|
||||
@@ -53,8 +60,10 @@ function installLocksMock() {
|
||||
}
|
||||
|
||||
function removeLocksMock() {
|
||||
// 只移除 locks,保留 storage(OPFS mock 需要)
|
||||
const existingNav = (globalThis as { navigator?: { storage?: unknown } }).navigator;
|
||||
Object.defineProperty(globalThis, 'navigator', {
|
||||
value: {},
|
||||
value: { storage: existingNav?.storage },
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
@@ -120,11 +129,11 @@ describe('AriaEngine — 多标签页锁(集成)', () => {
|
||||
|
||||
it('第二个标签页打开同一库 → ARIA_LOCKED', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine1 = new AriaEngine({ storageBackend: 'indexeddb' });
|
||||
const engine1 = new AriaEngine({ storageBackend: 'opfs' });
|
||||
await engine1.open(dbName, 1);
|
||||
await engine1.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } }));
|
||||
|
||||
const engine2 = new AriaEngine({ storageBackend: 'indexeddb' });
|
||||
const engine2 = new AriaEngine({ storageBackend: 'opfs' });
|
||||
await expect(engine2.open(dbName, 1)).rejects.toMatchObject({ code: 'ARIA_LOCKED' });
|
||||
// engine2 未持锁、未 opened
|
||||
expect((engine2 as any).opened).toBe(false);
|
||||
@@ -132,7 +141,7 @@ describe('AriaEngine — 多标签页锁(集成)', () => {
|
||||
await engine1.close();
|
||||
|
||||
// 释放后可打开
|
||||
const engine3 = new AriaEngine({ storageBackend: 'indexeddb' });
|
||||
const engine3 = new AriaEngine({ storageBackend: 'opfs' });
|
||||
await engine3.open(dbName, 1);
|
||||
expect(await engine3.count('t')).toBe(0);
|
||||
await engine3.close();
|
||||
@@ -140,19 +149,19 @@ describe('AriaEngine — 多标签页锁(集成)', () => {
|
||||
|
||||
it('open 失败(错误密码)→ 锁释放,其他标签页可打开', async () => {
|
||||
const dbName = uniqueDB();
|
||||
const engine1 = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'pw' } });
|
||||
const engine1 = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'pw' } });
|
||||
await engine1.open(dbName, 1);
|
||||
await engine1.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } }));
|
||||
await engine1.close();
|
||||
|
||||
// 错误密码 → open 失败
|
||||
const engineBad = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'wrong' } });
|
||||
const engineBad = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'wrong' } });
|
||||
await expect(engineBad.open(dbName, 1)).rejects.toMatchObject({ code: 'ARIA_DECRYPT_ERROR' });
|
||||
// 失败后锁已释放(未泄漏)
|
||||
expect(lockHolders.has(lockName(dbName))).toBe(false);
|
||||
|
||||
// 正确密码可打开
|
||||
const engineOk = new AriaEngine({ storageBackend: 'indexeddb', encryption: { password: 'pw' } });
|
||||
const engineOk = new AriaEngine({ storageBackend: 'opfs', encryption: { password: 'pw' } });
|
||||
await engineOk.open(dbName, 1);
|
||||
await engineOk.close();
|
||||
});
|
||||
@@ -160,7 +169,7 @@ describe('AriaEngine — 多标签页锁(集成)', () => {
|
||||
it('无 Web Locks 环境 → 降级打开(不抛错)', async () => {
|
||||
removeLocksMock();
|
||||
const dbName = uniqueDB();
|
||||
const engine = new AriaEngine({ storageBackend: 'indexeddb' });
|
||||
const engine = new AriaEngine({ storageBackend: 'opfs' });
|
||||
await engine.open(dbName, 1);
|
||||
await engine.createTable(createSchema('t', { id: { type: 'string', primaryKey: true } }));
|
||||
await engine.insert('t', [{ id: '1' }]);
|
||||
|
||||
Reference in New Issue
Block a user