release: v0.6.0 — 完全移除 IndexedDB,自研 KVStore 事务存储引擎(多key原子写/快照日志恢复/CRC自愈)+ KVStoreEngine + 旧库迁移工具 + 10万级压力验证 + 崩溃注入e2e
This commit is contained in:
Vendored
+77
-159
@@ -18,7 +18,7 @@ interface AriaEngineConfig {
|
||||
/** 是否启用页面压缩(默认 false) */
|
||||
compression?: boolean;
|
||||
/** 存储后端 */
|
||||
storageBackend?: 'indexeddb' | 'opfs' | 'memory';
|
||||
storageBackend?: 'opfs' | 'memory';
|
||||
/** WAL 大小阈值(字节,超过则强制 checkpoint,默认 16MB) */
|
||||
walSizeThreshold?: number;
|
||||
/** 最大内存预算(MB,默认 64) */
|
||||
@@ -45,8 +45,8 @@ interface AriaEngineConfig {
|
||||
*/
|
||||
/** 存储模式 */
|
||||
type StorageMode = 'memory' | 'disk' | 'hybrid' | 'aria';
|
||||
/** 磁盘引擎类型 */
|
||||
type DiskEngine = 'indexeddb' | 'opfs';
|
||||
/** 磁盘引擎类型(v0.6.0: IndexedDB 已移除,'memory' 供 aria 内存后端) */
|
||||
type DiskEngine = 'opfs' | 'memory';
|
||||
/** 字段数据类型 */
|
||||
type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'json';
|
||||
/** 列定义 */
|
||||
@@ -164,7 +164,7 @@ interface MetonaPlugin {
|
||||
/** 销毁 */
|
||||
destroy(): void;
|
||||
}
|
||||
declare const VERSION = "0.5.1";
|
||||
declare const VERSION = "0.6.0";
|
||||
|
||||
/**
|
||||
* metona-sqlark Plugin — 插件系统
|
||||
@@ -832,118 +832,75 @@ declare class MemoryEngine implements IStorageEngine {
|
||||
private cascadeDelete;
|
||||
}
|
||||
|
||||
declare class IndexedDBEngine implements IStorageEngine {
|
||||
readonly name = "indexeddb";
|
||||
private db;
|
||||
private dbName;
|
||||
private version;
|
||||
private memoryCache;
|
||||
private txActive;
|
||||
open(dbName: string, version: number): Promise<void>;
|
||||
/** v0.4.2-fix: 多标签页冲突处理 — 其他标签页升级版本时自动关闭当前连接 */
|
||||
private setupVersionChangeHandler;
|
||||
/**
|
||||
* v0.4.2-fix: 打开 IndexedDB 连接。
|
||||
* - P0-2: 请求版本低于库实际版本(VersionError)时,先无版本参数探测库当前版本,
|
||||
* 再以实际版本重开(建表每张表版本号 +1,config.version 会过期)
|
||||
* - P2-8: onblocked 为瞬时状态(另一连接短暂持有),等待后重试多次,超时才抛 IDB_BLOCKED
|
||||
*/
|
||||
private openDatabaseWithRetry;
|
||||
/**
|
||||
* 发起一次 indexedDB.open 请求(success/error/blocked 三态收敛)。
|
||||
* onblocked 不立即失败:阻塞解除后 success 仍会触发,仅超时兜底判失败,
|
||||
* 避免"拒绝后连接迟到成功"泄漏未关闭的数据库连接。
|
||||
*/
|
||||
private openRequest;
|
||||
/** 无版本参数打开库,解析其当前实际版本号(随后立即关闭) */
|
||||
private resolveCurrentVersion;
|
||||
/**
|
||||
* v0.4.2-fix (P2-7): 确保 __metona_schema store 存在。
|
||||
* 新库(或版本升级前创建的旧库)没有该 store 时,通过一次版本升级创建,
|
||||
* 使 getMeta/setMeta(迁移版本持久化)始终可用。
|
||||
*/
|
||||
private ensureSchemaStore;
|
||||
/**
|
||||
* 从 IDB 恢复内存 schema:
|
||||
* 1. 优先读取持久化的 schema 记录('__metona_schema' store,v0.3.2)
|
||||
* 2. 旧数据回退:从 objectStore 主键 / 索引 / 样例数据推断
|
||||
*/
|
||||
private rebuildSchemaFromIDB;
|
||||
/**
|
||||
* AriaEngine Storage Backend — 存储后端抽象层
|
||||
* @module engine/aria/store/backend
|
||||
*
|
||||
* 封装底层浏览器存储 API(IndexedDB / OPFS / Memory 回退),
|
||||
* 供 Buffer Pool 的 PageIO 和 WAL 的 WALStore 使用。
|
||||
*/
|
||||
interface IStorageBackend {
|
||||
/** 打开存储 */
|
||||
open(name: string): Promise<void>;
|
||||
/** 关闭存储 */
|
||||
close(): Promise<void>;
|
||||
/**
|
||||
* v0.4.2-fix: 自愈 — 从磁盘重建内存 schema 与数据(schema 丢失/内存不一致时调用)。
|
||||
* 无删库需求即可恢复可用的库。
|
||||
*/
|
||||
repair(): Promise<void>;
|
||||
/**
|
||||
* v0.4.2-fix: 清空全部数据与表结构(含持久化 schema 记录),保留库本身。
|
||||
* 单个版本升级事务内原子完成。
|
||||
*/
|
||||
clearAll(): Promise<void>;
|
||||
getMeta(key: string): Promise<string | null>;
|
||||
setMeta(key: string, value: string): Promise<void>;
|
||||
/** 是否已打开 */
|
||||
isOpen(): boolean;
|
||||
createTable(schema: TableSchema): Promise<void>;
|
||||
dropTable(tableName: string): Promise<void>;
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
getTableNames(): Promise<string[]>;
|
||||
getTableSchema(tableName: string): Promise<TableSchema | null>;
|
||||
/** 读取数据块 */
|
||||
read(key: string): Promise<ArrayBuffer | null>;
|
||||
/** 写入数据块 */
|
||||
write(key: string, data: ArrayBuffer): Promise<void>;
|
||||
/**
|
||||
* v0.4.2-fix: 引擎级 ALTER TABLE — schema 持久化到 __metona_schema store,
|
||||
* 重启后 ALTER 不丢失(此前通用路径只改内存引用,重启回退;DROP 的行数据也没真正删)。
|
||||
* 追加写入(v0.4.5 WAL 分片用,可选):
|
||||
* - OPFS 后端实现真追加(createWritable keepExistingData + seek,O(chunk))
|
||||
* - 未实现的后端由调用方回退 read+write(EncryptedBackend 包装时整体重写保正确性)
|
||||
* 语义:在 key 现有内容末尾追加 data;key 不存在时等同 write。
|
||||
*/
|
||||
alterTable(tableName: string, action: 'ADD' | 'DROP', column: ColumnDef & {
|
||||
name: string;
|
||||
}): Promise<void>;
|
||||
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
|
||||
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
|
||||
/** v0.4.0: 流式查询 — IDB 批量读入后逐行回调(保持接口一致性) */
|
||||
findStream(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
|
||||
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
|
||||
delete(tableName: string, query: QueryPlan): Promise<number>;
|
||||
count(tableName: string, query?: QueryPlan): Promise<number>;
|
||||
clear(tableName: string): Promise<void>;
|
||||
createIndex(tableName: string, column: string, unique?: boolean): Promise<void>;
|
||||
dropIndex(tableName: string, column: string, _indexName?: string): Promise<void>;
|
||||
beginTransaction(): Promise<void>;
|
||||
commitTransaction(): Promise<void>;
|
||||
rollbackTransaction(): Promise<void>;
|
||||
private idbCreateTable;
|
||||
private idbDropTable;
|
||||
private idbInsert;
|
||||
private idbFind;
|
||||
/** 尝试使用 IDB 索引进行等值查询,成功返回结果,不适用返回 null */
|
||||
private tryIDBIndexLookup;
|
||||
private idbUpdate;
|
||||
private idbDelete;
|
||||
private idbClear;
|
||||
/** 持久化单个表 schema 到 __metona_schema store(v0.4.2-fix: ALTER TABLE 用) */
|
||||
private persistSchema;
|
||||
/** 将内存缓存中的所有表数据原子性刷新到 IndexedDB */
|
||||
private flushToIDB;
|
||||
private ensureDB;
|
||||
append?(key: string, data: ArrayBuffer): Promise<void>;
|
||||
/**
|
||||
* 批量原子写入(v0.4.2-fix):多个 key 在单个底层事务中提交,
|
||||
* 中断时整体回滚,不留半写状态。WAL count 与记录同事务保证一致性。
|
||||
*/
|
||||
writeMany(entries: Record<string, ArrayBuffer>): Promise<void>;
|
||||
/** 删除数据块 */
|
||||
delete(key: string): Promise<void>;
|
||||
/**
|
||||
* 批量原子删除(v0.4.2-fix):多个 key 在单个底层事务中提交。
|
||||
*/
|
||||
deleteMany(keys: string[]): Promise<void>;
|
||||
/** 列出所有 key */
|
||||
listKeys(): Promise<string[]>;
|
||||
/** 检查 key 是否存在 */
|
||||
exists(key: string): Promise<boolean>;
|
||||
/** 清空所有数据 */
|
||||
clear(): Promise<void>;
|
||||
}
|
||||
|
||||
declare class OPFSEngine implements IStorageEngine {
|
||||
readonly name = "opfs";
|
||||
private root;
|
||||
private tablesDir;
|
||||
declare class KVStoreEngine implements IStorageEngine {
|
||||
readonly name = "kv";
|
||||
private kv;
|
||||
private memory;
|
||||
private dbName;
|
||||
private memoryCache;
|
||||
/**
|
||||
* v0.4.3-fix: 写操作串行队列 — 内存写 + 快照 + 文件持久化整体排队执行,
|
||||
* close() 等待队列排空后再释放目录句柄(避免 close 后挂起写泄漏/读旧数据)。
|
||||
* 前一个操作失败不阻塞后续(错误仍返回给调用方)。
|
||||
*/
|
||||
private opQueue;
|
||||
/** 将写操作加入串行队列(快照在队列内取,始终最新) */
|
||||
private enqueueOp;
|
||||
private version;
|
||||
private opened;
|
||||
/** 活跃事务标记 */
|
||||
private txActive;
|
||||
/** 事务中写过的表(commit 时只 flush 这些表) */
|
||||
private txDirtyTables;
|
||||
constructor(medium?: IStorageBackend, checkpointThreshold?: number);
|
||||
private rowKey;
|
||||
private rowPrefix;
|
||||
open(dbName: string, version: number): Promise<void>;
|
||||
close(): Promise<void>;
|
||||
isOpen(): boolean;
|
||||
/** 自愈:重置内存缓存后从 OPFS 重新加载(单文件损坏不影响其他表) */
|
||||
/**
|
||||
* v0.6.0: 从 KVStore 重新加载全部数据到内存(多标签页同步重载用)。
|
||||
* Hybrid 引擎的 reloadMemoryFromDisk 依赖磁盘引擎"读穿透",
|
||||
* KVStoreEngine 读内存 → 提供 reload 重新加载磁盘最新数据。
|
||||
*/
|
||||
reload(): Promise<void>;
|
||||
/** v0.4.2-fix: 自愈 — 校验 KVStore 日志/快照完整性并重建内存 */
|
||||
repair(): Promise<void>;
|
||||
/** 清空全部数据与表结构(删除目录内全部文件) */
|
||||
clearAll(): Promise<void>;
|
||||
getMeta(key: string): Promise<string | null>;
|
||||
setMeta(key: string, value: string): Promise<void>;
|
||||
@@ -952,13 +909,11 @@ declare class OPFSEngine implements IStorageEngine {
|
||||
hasTable(tableName: string): Promise<boolean>;
|
||||
getTableNames(): Promise<string[]>;
|
||||
getTableSchema(tableName: string): Promise<TableSchema | null>;
|
||||
/** v0.4.2-fix: 引擎级 ALTER TABLE — 内存 + schema 持久化 + 整表文件重写 */
|
||||
alterTable(tableName: string, action: 'ADD' | 'DROP', column: ColumnDef & {
|
||||
name: string;
|
||||
}): Promise<void>;
|
||||
insert(tableName: string, rows: Record<string, unknown>[]): Promise<string[]>;
|
||||
find(tableName: string, query: QueryPlan): Promise<Record<string, unknown>[]>;
|
||||
/** v0.4.0: 流式查询(委托内存缓存) */
|
||||
findStream(tableName: string, query: QueryPlan, onRow: (row: Record<string, unknown>) => void): Promise<number>;
|
||||
update(tableName: string, query: QueryPlan, updates: Record<string, unknown>): Promise<number>;
|
||||
delete(tableName: string, query: QueryPlan): Promise<number>;
|
||||
@@ -969,15 +924,22 @@ declare class OPFSEngine implements IStorageEngine {
|
||||
beginTransaction(): Promise<void>;
|
||||
commitTransaction(): Promise<void>;
|
||||
rollbackTransaction(): Promise<void>;
|
||||
private ensureDir;
|
||||
private writeTableData;
|
||||
private readTableData;
|
||||
private ensureOpen;
|
||||
private getPK;
|
||||
/** 收集匹配查询的内存行主键(持久化差异计算用) */
|
||||
private collectMatchingPks;
|
||||
/**
|
||||
* 从 OPFS 加载已有表到内存缓存。
|
||||
* v0.4.2-fix: 优先从持久化 schema(__metona_schema_*.meta)恢复 —
|
||||
* 空表不再消失、索引标记/主键/约束完整;无 schema 记录的旧库从数据推断(兼容)。
|
||||
* 计算外键级联影响的表集合(传递闭包:A 被 B 引用,B 被 C 引用 → {A, B, C})。
|
||||
* 级联操作(delete/update 主键)需要把这些表一并重写持久化。
|
||||
*/
|
||||
private loadExistingTables;
|
||||
private affectedTables;
|
||||
/** 持久化 schema(全部表) */
|
||||
private persistSchema;
|
||||
/**
|
||||
* 整表 diff 持久化:内存行全部 put + KV 残留行删除(原子 putMany + deleteMany)。
|
||||
* 用于主键变更 / 级联 / dropTable / clear / alterTable DROP / 事务 commit。
|
||||
*/
|
||||
private flushTable;
|
||||
}
|
||||
|
||||
declare class AriaEngine implements IStorageEngine {
|
||||
@@ -1322,50 +1284,6 @@ interface Token {
|
||||
/** 将 SQL 字符串解析为 Token 列表 */
|
||||
declare function tokenize(sql: string): Token[];
|
||||
|
||||
/**
|
||||
* AriaEngine Storage Backend — 存储后端抽象层
|
||||
* @module engine/aria/store/backend
|
||||
*
|
||||
* 封装底层浏览器存储 API(IndexedDB / OPFS / Memory 回退),
|
||||
* 供 Buffer Pool 的 PageIO 和 WAL 的 WALStore 使用。
|
||||
*/
|
||||
interface IStorageBackend {
|
||||
/** 打开存储 */
|
||||
open(name: string): Promise<void>;
|
||||
/** 关闭存储 */
|
||||
close(): Promise<void>;
|
||||
/** 是否已打开 */
|
||||
isOpen(): boolean;
|
||||
/** 读取数据块 */
|
||||
read(key: string): Promise<ArrayBuffer | null>;
|
||||
/** 写入数据块 */
|
||||
write(key: string, data: ArrayBuffer): Promise<void>;
|
||||
/**
|
||||
* 追加写入(v0.4.5 WAL 分片用,可选):
|
||||
* - OPFS 后端实现真追加(createWritable keepExistingData + seek,O(chunk))
|
||||
* - 未实现的后端由调用方回退 read+write(EncryptedBackend 包装时整体重写保正确性)
|
||||
* 语义:在 key 现有内容末尾追加 data;key 不存在时等同 write。
|
||||
*/
|
||||
append?(key: string, data: ArrayBuffer): Promise<void>;
|
||||
/**
|
||||
* 批量原子写入(v0.4.2-fix):多个 key 在单个底层事务中提交,
|
||||
* 中断时整体回滚,不留半写状态。WAL count 与记录同事务保证一致性。
|
||||
*/
|
||||
writeMany(entries: Record<string, ArrayBuffer>): Promise<void>;
|
||||
/** 删除数据块 */
|
||||
delete(key: string): Promise<void>;
|
||||
/**
|
||||
* 批量原子删除(v0.4.2-fix):多个 key 在单个底层事务中提交。
|
||||
*/
|
||||
deleteMany(keys: string[]): Promise<void>;
|
||||
/** 列出所有 key */
|
||||
listKeys(): Promise<string[]>;
|
||||
/** 检查 key 是否存在 */
|
||||
exists(key: string): Promise<boolean>;
|
||||
/** 清空所有数据 */
|
||||
clear(): Promise<void>;
|
||||
}
|
||||
|
||||
/**
|
||||
* AriaEngine OPFS Backend — 基于 Origin Private File System 的自研存储后端
|
||||
* @module engine/aria/store/opfs_backend
|
||||
@@ -1463,4 +1381,4 @@ declare global {
|
||||
|
||||
declare const MeSqlark: typeof MetonaSqlark;
|
||||
|
||||
export { AriaEngine, AriaEngineConfig, ColumnDef, DatabaseConfig, DeleteStatement, DiskEngine, FieldType, HybridEngine, IStorageEngine, IndexedDBEngine, InsertStatement, MeSqlark, MemoryEngine, MetonaSqlark, OPFSBackend, OPFSEngine, SelectStatement, Statement, StorageMode, Table, TableSchema, UpdateStatement, VERSION, api, create, api as default, parse, parseAll, tokenize };
|
||||
export { AriaEngine, AriaEngineConfig, ColumnDef, DatabaseConfig, DeleteStatement, DiskEngine, FieldType, HybridEngine, IStorageEngine, InsertStatement, KVStoreEngine, MeSqlark, MemoryEngine, MetonaSqlark, OPFSBackend, SelectStatement, Statement, StorageMode, Table, TableSchema, UpdateStatement, VERSION, api, create, api as default, parse, parseAll, tokenize };
|
||||
|
||||
Reference in New Issue
Block a user