feat: v0.2.0 AriaEngine 自研存储引擎
CI / test (20.x) (push) Canceled after 0s
CI / test (22.x) (push) Canceled after 0s
CI / test (24.x) (push) Canceled after 0s
CI / test (18.x) (push) Canceled after 1h26m17s

- 新增 AriaEngine: LSM-Tree 页面式存储引擎,19 个模块,~3500 行 TS
  - page/: Slotted Page 格式 (header/slot/tuple/format) + CRC32
  - buffer/: Buffer Pool (LRU 缓存 + 驱逐策略)
  - index/: LSM-Tree (MemTable 红黑树 + SSTable + Bloom Filter + Merge Iterator)
  - wal/: WAL 日志 (二进制格式) + Checkpoint 管理
  - transaction/: MVCC 版本链 + 快照隔离
  - store/: IndexedDB / Memory 双后端抽象
  - compression/: LZ4 页面压缩

- 完整持久化: Schema 自动保存、SSTable 元数据管理、WAL 恢复
- 事务感知 CRUD: insert/update/delete 在事务中缓冲到 snapshot
- mode: 'aria' 激活自研引擎

- 新增 7 个测试文件,测试数 318 → 524,套件 20 → 27
  - aria-page.test.ts (32 tests): Page 格式单元测试
  - aria-index.test.ts (26 tests): Bloom Filter + MemTable
  - aria-sstable.test.ts (9 tests): SSTable Builder + Reader
  - aria-buffer.test.ts (25 tests): LRU + Eviction + Buffer Pool
  - aria-wal-mvcc.test.ts (22 tests): WAL 编解码 + MVCC 事务
  - aria-compress.test.ts (11 tests): LZ4 + Merge Iterator
  - aria.test.ts (80 tests): AriaEngine 集成 + 边界测试

- Bug 修复: LRUList size 跟踪、WAL 缓冲区越界、ColumnEncoding 导入
- 全面更新 README.md + site/ 站点文件 (index/docs/demo)
This commit is contained in:
2026-07-27 16:40:29 +08:00
parent c00738aea0
commit f84673e519
47 changed files with 14553 additions and 108 deletions
+112
View File
@@ -0,0 +1,112 @@
/**
* AriaEngine File Manager — 页面文件管理 + PageIO 实现
* @module engine/aria/store/file_manager
*
* 负责管理页面文件的生命周期:分配/释放页面 ID,读写页面。
*/
import type { IStorageBackend } from './backend';
import type { PageIO } from '../buffer/pool';
import { PAGE_SIZE, PageType } from '../types';
import { initPageHeader } from '../page/header';
// ---------------------------------------------------------------------------
// FileManager (implements PageIO)
// ---------------------------------------------------------------------------
export class FileManager implements PageIO {
private backend: IStorageBackend;
private nextPageId = 0;
private metaLoaded = false;
private dbName = '';
constructor(backend: IStorageBackend) {
this.backend = backend;
}
/** 初始化:从存储中读取元数据 */
async init(dbName: string): Promise<void> {
this.dbName = dbName;
// 读取 nextPageId
const meta = await this.backend.read('__aria_meta');
if (meta) {
const view = new DataView(meta);
this.nextPageId = view.getUint32(0, false);
} else {
this.nextPageId = 1;
await this.saveMeta();
}
this.metaLoaded = true;
}
// ---- PageIO ----
async readPage(pageId: number): Promise<ArrayBuffer | null> {
const key = `pg_${pageId}`;
const data = await this.backend.read(key);
if (!data) {
// 第一次访问:创建新页面
return this.createEmptyPage(pageId, PageType.DATA);
}
// 确保大小正确
if (data.byteLength < PAGE_SIZE) {
const padded = new ArrayBuffer(PAGE_SIZE);
new Uint8Array(padded).set(new Uint8Array(data));
return padded;
}
return data;
}
async writePage(pageId: number, data: ArrayBuffer): Promise<void> {
const key = `pg_${pageId}`;
await this.backend.write(key, data);
}
async allocatePageId(): Promise<number> {
const id = this.nextPageId++;
await this.saveMeta();
return id;
}
async freePageId(_pageId: number): Promise<void> {
// 简化实现:不回收 pageId
const key = `pg_${_pageId}`;
await this.backend.delete(key);
}
// ---- 表页面分配 ----
/**
* 分配一个新的表元数据页面。
*/
async allocateTableRootPage(): Promise<number> {
const pageId = await this.allocatePageId();
const data = new ArrayBuffer(PAGE_SIZE);
initPageHeader(data, pageId, PageType.META);
await this.writePage(pageId, data);
return pageId;
}
// ---- 辅助 ----
private async saveMeta(): Promise<void> {
const buf = new ArrayBuffer(8);
new DataView(buf).setUint32(0, this.nextPageId, false);
await this.backend.write('__aria_meta', buf);
}
private createEmptyPage(pageId: number, type: PageType): ArrayBuffer {
const buf = new ArrayBuffer(PAGE_SIZE);
initPageHeader(buf, pageId, type);
return buf;
}
/** 清空所有数据 */
async clearAll(): Promise<void> {
await this.backend.clear();
this.nextPageId = 1;
await this.saveMeta();
}
}