Files
thzxx 0f128da34a
CI / test (18.x) (push) Successful in 9m54s
CI / test (20.x) (push) Successful in 9m52s
CI / test (22.x) (push) Successful in 9m54s
CI / test (24.x) (push) Successful in 9m47s
feat: v0.1.13 — 事务回滚 + 子查询 + 外键级联 + 连接池
2026-07-26 16:31:15 +08:00

164 lines
5.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* metona-sqlark Hybrid Engine — 内存 + 磁盘混合存储引擎
* @module hybrid/index
*
* 采用 write-through 策略:
* - 所有写操作同时写入内存和磁盘
* - 所有读操作直接从内存返回
* - 数据库打开时从磁盘加载数据到内存
*/
import type { IStorageEngine } from '../engine/interface';
import type { QueryPlan, TableSchema, DiskEngine } from '../constants';
import { MemoryEngine } from '../engine/memory';
import { IndexedDBEngine } from '../engine/indexeddb';
import { OPFSEngine } from '../engine/opfs';
// ---------------------------------------------------------------------------
// HybridEngine
// ---------------------------------------------------------------------------
export class HybridEngine implements IStorageEngine {
readonly name = 'hybrid';
private memoryEngine: MemoryEngine;
private diskEngine: IStorageEngine;
private diskEngineType: DiskEngine;
constructor(diskEngine: DiskEngine = 'indexeddb') {
this.memoryEngine = new MemoryEngine();
this.diskEngineType = diskEngine;
this.diskEngine = diskEngine === 'opfs' ? new OPFSEngine() : new IndexedDBEngine();
}
// ---- 生命周期 ----
async open(dbName: string, version: number): Promise<void> {
// 先打开磁盘引擎
await this.diskEngine.open(dbName, version);
// 再打开内存引擎
await this.memoryEngine.open(dbName, version);
// 从磁盘加载现存表
const tableNames = await this.diskEngine.getTableNames();
for (const tableName of tableNames) {
const schema = await this.diskEngine.getTableSchema(tableName);
if (!schema) continue;
// 在内存中创建表
await this.memoryEngine.createTable(schema);
// 从磁盘加载数据到内存
const rows = await this.diskEngine.find(tableName, { table: tableName });
if (rows.length > 0) {
try {
await this.memoryEngine.insert(tableName, rows);
} catch (e) {
// eslint-disable-next-line no-console
console.warn(`[metona-sqlark] Failed to load table "${tableName}" data from disk:`, e);
}
}
}
}
async close(): Promise<void> {
await this.memoryEngine.close();
await this.diskEngine.close();
}
isOpen(): boolean {
return this.memoryEngine.isOpen() && this.diskEngine.isOpen();
}
// ---- 表管理 ----
async createTable(schema: TableSchema): Promise<void> {
await this.memoryEngine.createTable(schema);
await this.diskEngine.createTable(schema);
}
async dropTable(tableName: string): Promise<void> {
await this.memoryEngine.dropTable(tableName);
await this.diskEngine.dropTable(tableName);
}
async hasTable(tableName: string): Promise<boolean> {
return this.memoryEngine.hasTable(tableName);
}
async getTableNames(): Promise<string[]> {
return this.memoryEngine.getTableNames();
}
async getTableSchema(tableName: string): Promise<TableSchema | null> {
return this.memoryEngine.getTableSchema(tableName);
}
// ---- CRUDwrite-through 策略) ----
async insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]> {
const pks = await this.memoryEngine.insert(tableName, rows);
// write-through: 同步写入磁盘
await this.diskEngine.insert(tableName, rows);
return pks;
}
async find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]> {
// 直接从内存读取
return this.memoryEngine.find(tableName, query);
}
async update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number> {
const count = await this.memoryEngine.update(tableName, query, updates);
// write-through: 同步更新磁盘
await this.diskEngine.update(tableName, query, updates);
return count;
}
async delete(tableName: string, query: QueryPlan): Promise<number> {
const count = await this.memoryEngine.delete(tableName, query);
// write-through: 同步删除磁盘
await this.diskEngine.delete(tableName, query);
return count;
}
async count(tableName: string, query?: QueryPlan): Promise<number> {
return this.memoryEngine.count(tableName, query);
}
async clear(tableName: string): Promise<void> {
await this.memoryEngine.clear(tableName);
await this.diskEngine.clear(tableName);
}
// ---- 事务 ----
async beginTransaction(): Promise<void> {
await this.memoryEngine.beginTransaction();
await this.diskEngine.beginTransaction();
}
async commitTransaction(): Promise<void> {
await this.memoryEngine.commitTransaction();
await this.diskEngine.commitTransaction();
}
async rollbackTransaction(): Promise<void> {
await this.memoryEngine.rollbackTransaction();
await this.diskEngine.rollbackTransaction();
}
// ---- 引擎信息 ----
/** 获取磁盘引擎类型 */
getDiskEngineType(): DiskEngine {
return this.diskEngineType;
}
/** 获取内存引擎(供内部使用) */
getMemoryEngine(): MemoryEngine {
return this.memoryEngine;
}
}