feat: v0.6.1 — AriaEngine 可选自研 KVStore 后端(storageBackend: 'kv')+ KVStore APPEND 日志类型 + 10 个 aria+kv 集成测试 + 文档全量同步
CI / test (20.x) (push) Successful in 10m55s
CI / test (22.x) (push) Successful in 10m49s
CI / e2e (push) Successful in 9m54s
CI / test (18.x) (push) Successful in 10m58s
CI / test (24.x) (push) Successful in 10m41s

This commit is contained in:
thzxx
2026-08-10 14:52:38 +08:00
parent a56a496148
commit 25bab0f9aa
21 changed files with 895 additions and 42 deletions
+100
View File
@@ -366,3 +366,103 @@ describe('KVStore — 编解码单元', () => {
expect(decodeSnapshot(bytes)).toBeNull();
});
});
// ===================================================================
// APPEND 追加写入(v0.6.1
// ===================================================================
describe('KVStore — APPEND 追加写入', () => {
it('appendValue 拼接 + 恢复完整(跨实例)', async () => {
const dbName = uniqueDB();
const medium = new SharedMemoryBackend();
const kv = new KVStore(medium, 0);
await kv.open(dbName);
await kv.appendValue('log', enc('AAA'));
await kv.appendValue('log', enc('BBB'));
await kv.appendValue('log', enc('CCC'));
expect(dec(await kv.get('log'))).toBe('AAABBBCCC');
await kv.close();
const kv2 = new KVStore(medium, 0);
await kv2.open(dbName);
expect(dec(await kv2.get('log'))).toBe('AAABBBCCC');
await kv2.close();
});
it('append 与 put/delete 混合 + checkpoint 后恢复', async () => {
const dbName = uniqueDB();
const medium = new SharedMemoryBackend();
const kv = new KVStore(medium, 0);
await kv.open(dbName);
await kv.appendValue('log', enc('A'));
await kv.put('meta', enc('M'));
await kv.appendValue('log', enc('B'));
await kv.checkpoint();
await kv.appendValue('log', enc('C'));
await kv.put('meta2', enc('M2'));
await kv.close();
const kv2 = new KVStore(medium, 0);
await kv2.open(dbName);
expect(dec(await kv2.get('log'))).toBe('ABC');
expect(dec(await kv2.get('meta'))).toBe('M');
expect(dec(await kv2.get('meta2'))).toBe('M2');
await kv2.close();
});
it('append 覆盖语义:先 put 后 append 拼接', async () => {
const dbName = uniqueDB();
const medium = new SharedMemoryBackend();
const kv = new KVStore(medium, 0);
await kv.open(dbName);
await kv.put('f', enc('HEAD-'));
await kv.appendValue('f', enc('BODY'));
expect(dec(await kv.get('f'))).toBe('HEAD-BODY');
await kv.close();
const kv2 = new KVStore(medium, 0);
await kv2.open(dbName);
expect(dec(await kv2.get('f'))).toBe('HEAD-BODY');
await kv2.close();
});
it('append 后 delete → 删除生效(索引与恢复一致)', async () => {
const dbName = uniqueDB();
const medium = new SharedMemoryBackend();
const kv = new KVStore(medium, 0);
await kv.open(dbName);
await kv.appendValue('log', enc('X'));
await kv.delete('log');
expect(await kv.exists('log')).toBe(false);
await kv.close();
const kv2 = new KVStore(medium, 0);
await kv2.open(dbName);
expect(await kv2.exists('log')).toBe(false);
await kv2.close();
});
it('日志损坏截断后已确认的 append 数据保留', async () => {
const dbName = uniqueDB();
const medium = new SharedMemoryBackend();
const kv = new KVStore(medium, 0);
await kv.open(dbName);
await kv.appendValue('log', enc('KEEP'));
await kv.close();
// 追加损坏记录
const disk = new SharedMemoryBackend();
await disk.open(dbName);
const log = await disk.read('__kv_log');
const bad = new Uint8Array(encodeLogRecord(999, { x: enc('X') }));
bad[15] ^= 0xff;
const combined = new Uint8Array((log as ArrayBuffer).byteLength + bad.byteLength);
combined.set(new Uint8Array(log as ArrayBuffer), 0);
combined.set(bad, (log as ArrayBuffer).byteLength);
await disk.write('__kv_log', combined.buffer as ArrayBuffer);
const kv2 = new KVStore(medium, 0);
await kv2.open(dbName);
expect(dec(await kv2.get('log'))).toBe('KEEP');
await kv2.close();
});
});