dsh-shared-kb 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/store/docs.js +21 -0
- package/lib/store/manifest.js +8 -2
- package/package.json +1 -1
package/lib/store/docs.js
CHANGED
|
@@ -376,12 +376,20 @@ export async function writeDoc(params) {
|
|
|
376
376
|
|
|
377
377
|
// 清单 CAS 写入:rev 对不上会把上面写好的正文留在磁盘上(幂等,下次重跑会覆盖),
|
|
378
378
|
// 但绝不更新清单,读者看不到半成品。
|
|
379
|
+
//
|
|
380
|
+
// 关键:去重必须在锁内再判一次。锁外那次 findDoc 只是"快速路径",
|
|
381
|
+
// 两个进程同时导入同一份文件时会双双落空,然后都进锁写入 —— 数据不会错
|
|
382
|
+
// (内容相同),但会白白推高 rev、重复触发索引。锁内命中就直接报 unchanged,
|
|
383
|
+
// 且不递增 rev。
|
|
379
384
|
const result = await withManifest(
|
|
380
385
|
dir,
|
|
381
386
|
kb,
|
|
382
387
|
(manifest) => {
|
|
383
388
|
const list = manifest.docs ?? (manifest.docs = []);
|
|
384
389
|
const at = list.findIndex((doc) => doc.id === docId);
|
|
390
|
+
if (at >= 0 && list[at].contentHash === contentHash && !params.force) {
|
|
391
|
+
return { __skip: true, result: { status: "unchanged", version: list[at].version } };
|
|
392
|
+
}
|
|
385
393
|
if (at >= 0) list[at] = entry;
|
|
386
394
|
else list.push(entry);
|
|
387
395
|
return entry;
|
|
@@ -400,6 +408,19 @@ export async function writeDoc(params) {
|
|
|
400
408
|
chars: entry.chars,
|
|
401
409
|
});
|
|
402
410
|
|
|
411
|
+
// 锁内判重命中:这一轮什么都没改,如实报 unchanged
|
|
412
|
+
if (result.skipped === true) {
|
|
413
|
+
return {
|
|
414
|
+
docId,
|
|
415
|
+
status: "unchanged",
|
|
416
|
+
rev: null,
|
|
417
|
+
version: result.result?.version ?? entry.version,
|
|
418
|
+
title: entry.title,
|
|
419
|
+
parts: entry.parts,
|
|
420
|
+
chars: entry.chars,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
|
|
403
424
|
return {
|
|
404
425
|
docId,
|
|
405
426
|
status: existing ? "updated" : "created",
|
package/lib/store/manifest.js
CHANGED
|
@@ -164,11 +164,17 @@ export async function withManifest(dir, name, mutate, options = {}) {
|
|
|
164
164
|
}
|
|
165
165
|
const by = options.by ?? { machine: machineId(), pid: process.pid };
|
|
166
166
|
const now = new Date().toISOString();
|
|
167
|
-
const
|
|
167
|
+
const outcome = await mutate(manifest, { now, by });
|
|
168
|
+
// mutate 可以返回 { __skip: true, result } 表示"读完发现不需要改"。
|
|
169
|
+
// 这种轮次绝不能递增 rev:rev 是"清单内容变了几次"的计数,
|
|
170
|
+
// 空轮递增会让所有人都以为有人在改,也会白白触发索引重建。
|
|
171
|
+
if (outcome && outcome.__skip === true) {
|
|
172
|
+
return { rev: manifest.rev, result: outcome.result ?? null, manifest, skipped: true };
|
|
173
|
+
}
|
|
168
174
|
manifest.rev = manifest.rev + 1;
|
|
169
175
|
touch(manifest, by);
|
|
170
176
|
await writeManifestAtomic(dir, manifest);
|
|
171
|
-
return { rev: manifest.rev, result, manifest };
|
|
177
|
+
return { rev: manifest.rev, result: outcome, manifest, skipped: false };
|
|
172
178
|
},
|
|
173
179
|
{ timeoutMs: options.timeoutMs }
|
|
174
180
|
);
|