release: v0.4.2 — 生产就绪与崩溃自愈 + 问题清单修复 + 版本迭代
CI / test (18.x) (push) Successful in 10m7s
CI / test (20.x) (push) Successful in 10m6s
CI / test (22.x) (push) Successful in 10m2s
CI / test (24.x) (push) Successful in 10m0s

This commit is contained in:
thzxx
2026-08-09 19:15:37 +08:00
parent a1e4f5071c
commit 22b0b1fad4
34 changed files with 6626 additions and 565 deletions
+53 -1
View File
@@ -90,6 +90,17 @@ export class MetonaSqlark {
// 打开连接
await this.engine.open(this.name, this.version);
// v0.4.2-fix (P2-7): 从库内加载持久化的迁移版本,
// 重启后 migrateTo 从持久化版本继续执行,不再每次从 config.version 重置
if (typeof this.engine.getMeta === 'function') {
try {
const persistedVersion = await this.engine.getMeta('__metona_version');
if (persistedVersion != null && Number(persistedVersion) >= 1) {
this._version = Math.max(this._version, Math.floor(Number(persistedVersion)));
}
} catch { /* 读取失败回退 config.version */ }
}
// 初始化执行器和事务管理器
this.executor = new QueryExecutor(this.engine, this.maxRowsPerQuery);
this.transactionManager = new TransactionManager(this.engine);
@@ -395,11 +406,52 @@ export class MetonaSqlark {
async migrateTo(targetVersion: number): Promise<void> {
this.ensureReady();
for (const [version, up] of [...this.migrations.entries()].sort((a, b) => a[0] - b[0])) {
if (version <= targetVersion && version > this.version) {
if (version <= targetVersion && version > this._version) {
await up(this);
this._version = version;
}
}
// v0.4.2-fix (P2-7): 迁移版本持久化到库内,重启后从持久化版本继续,
// 避免"version 重置导致已执行迁移重跑(不幂等就炸)"或"版本门槛跳过迁移"
if (typeof this.engine.setMeta === 'function') {
try {
await this.engine.setMeta('__metona_version', String(this._version));
} catch { /* 持久化失败不阻塞迁移流程 */ }
}
}
// ---- 自愈 / 重置(v0.4.2-fix, P2-9 ----
/**
* 崩溃恢复自愈 — 校验并清理损坏数据、恢复一致性。
* 检测到异常后调用,无需删库重建。
*/
async repair(): Promise<void> {
this.ensureReady();
if (typeof this.engine.repair === 'function') {
await this.engine.repair();
this.tableCache.clear();
return;
}
// 兜底:重建表缓存
this.tableCache.clear();
}
/**
* 清空全部数据与表结构(保留库本身)。
* 支持后续继续使用本实例重建表。
*/
async clearAll(): Promise<void> {
this.ensureReady();
if (typeof this.engine.clearAll === 'function') {
await this.engine.clearAll();
} else {
const names = await this.engine.getTableNames();
for (const name of names) {
await this.engine.dropTable(name);
}
}
this.tableCache.clear();
}
// ---- 插件 ----