@lmzhen/dsh-evolution-merge 0.30.11 → 0.30.12
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/index.js +13 -6
- package/lib/types/scan-run.js +7 -6
- package/lib/types/state.d.ts +1 -1
- package/lib/types/state.js +4 -1
- package/package.json +3 -3
package/lib/index.js
CHANGED
|
@@ -345,10 +345,17 @@ async function mutateMergeState(io, home, now, fn) {
|
|
|
345
345
|
});
|
|
346
346
|
return result;
|
|
347
347
|
}
|
|
348
|
-
async function upsertRow(io, home, now, row, expect = "any") {
|
|
348
|
+
async function upsertRow(io, home, now, row, expect = "any", cas) {
|
|
349
349
|
return await mutateMergeState(io, home, now, (rows) => {
|
|
350
350
|
const index = rows.findIndex((item) => item.pairKey === row.pairKey);
|
|
351
351
|
const current = index < 0 ? void 0 : rows[index];
|
|
352
|
+
if (cas !== void 0 && (cas === null && current !== void 0 || cas !== null && current?.updatedAt !== cas)) return {
|
|
353
|
+
rows,
|
|
354
|
+
result: {
|
|
355
|
+
ok: false,
|
|
356
|
+
current: current ?? row
|
|
357
|
+
}
|
|
358
|
+
};
|
|
352
359
|
if (current !== void 0 && expect !== "any" && (expect === "absent" || queueOf(current.state) !== expect)) return {
|
|
353
360
|
rows,
|
|
354
361
|
result: {
|
|
@@ -1790,16 +1797,16 @@ async function runScan(options) {
|
|
|
1790
1797
|
});
|
|
1791
1798
|
if (!created.ok || created.row === null) throw new Error(created.ok ? "candidate row missing" : created.message);
|
|
1792
1799
|
row = created.row;
|
|
1793
|
-
const
|
|
1794
|
-
|
|
1795
|
-
|
|
1800
|
+
const before = (await loadMergeState(options.io, options.home)).state.rows.find((item) => item.pairKey === row.pairKey);
|
|
1801
|
+
const placed = await upsertRow(options.io, options.home, options.now, row, "verify", before?.updatedAt ?? null);
|
|
1802
|
+
if (!placed.ok && before?.state === "skipped") {
|
|
1803
|
+
const restored = transition(before, {
|
|
1796
1804
|
type: "restore",
|
|
1797
1805
|
at: at(options.now)
|
|
1798
1806
|
});
|
|
1799
1807
|
if (!restored.ok || restored.row === null) throw new Error("cannot restore skipped pair");
|
|
1808
|
+
if (!(await upsertRow(options.io, options.home, options.now, restored.row, "any", before.updatedAt)).ok) throw new Error("pair changed while restoring skipped row");
|
|
1800
1809
|
row = restored.row;
|
|
1801
|
-
const retried = await upsertRow(options.io, options.home, options.now, row, "verify");
|
|
1802
|
-
if (!retried.ok) throw new Error("pair already in " + retried.current.state);
|
|
1803
1810
|
} else if (!placed.ok) throw new Error("pair already in " + placed.current.state);
|
|
1804
1811
|
} catch (error) {
|
|
1805
1812
|
totals.failed += 1;
|
package/lib/types/scan-run.js
CHANGED
|
@@ -65,15 +65,16 @@ export async function runScan(options) {
|
|
|
65
65
|
if (!created.ok || created.row === null)
|
|
66
66
|
throw new Error(created.ok ? 'candidate row missing' : created.message);
|
|
67
67
|
row = created.row;
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
const before = (await loadMergeState(options.io, options.home)).state.rows.find(item => item.pairKey === row.pairKey);
|
|
69
|
+
const placed = await upsertRow(options.io, options.home, options.now, row, 'verify', before?.updatedAt ?? null);
|
|
70
|
+
if (!placed.ok && before?.state === 'skipped') {
|
|
71
|
+
const restored = transition(before, { type: 'restore', at: at(options.now) });
|
|
71
72
|
if (!restored.ok || restored.row === null)
|
|
72
73
|
throw new Error('cannot restore skipped pair');
|
|
74
|
+
const persisted = await upsertRow(options.io, options.home, options.now, restored.row, 'any', before.updatedAt);
|
|
75
|
+
if (!persisted.ok)
|
|
76
|
+
throw new Error('pair changed while restoring skipped row');
|
|
73
77
|
row = restored.row;
|
|
74
|
-
const retried = await upsertRow(options.io, options.home, options.now, row, 'verify');
|
|
75
|
-
if (!retried.ok)
|
|
76
|
-
throw new Error('pair already in ' + retried.current.state);
|
|
77
78
|
}
|
|
78
79
|
else if (!placed.ok) {
|
|
79
80
|
throw new Error('pair already in ' + placed.current.state);
|
package/lib/types/state.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export type UpsertResult = {
|
|
|
29
29
|
readonly ok: false;
|
|
30
30
|
readonly current: MergeRow;
|
|
31
31
|
};
|
|
32
|
-
export declare function upsertRow(io: EvolutionIoLike, home: string, now: () => number, row: MergeRow, expect?: UpsertExpect): Promise<UpsertResult>;
|
|
32
|
+
export declare function upsertRow(io: EvolutionIoLike, home: string, now: () => number, row: MergeRow, expect?: UpsertExpect, cas?: string | null): Promise<UpsertResult>;
|
|
33
33
|
export declare function moveRow(io: EvolutionIoLike, home: string, now: () => number, id: string, patch: MoveRowPatch): Promise<MergeRow | undefined>;
|
|
34
34
|
export declare function dropRow(io: EvolutionIoLike, home: string, now: () => number, id: string): Promise<boolean>;
|
|
35
35
|
export declare function rowsOf(io: EvolutionIoLike, home: string, queue?: MergeQueue): Promise<readonly MergeRow[]>;
|
package/lib/types/state.js
CHANGED
|
@@ -55,10 +55,13 @@ export async function mutateMergeState(io, home, now, fn) {
|
|
|
55
55
|
void now;
|
|
56
56
|
return result;
|
|
57
57
|
}
|
|
58
|
-
export async function upsertRow(io, home, now, row, expect = 'any') {
|
|
58
|
+
export async function upsertRow(io, home, now, row, expect = 'any', cas) {
|
|
59
59
|
return await mutateMergeState(io, home, now, (rows) => {
|
|
60
60
|
const index = rows.findIndex(item => item.pairKey === row.pairKey);
|
|
61
61
|
const current = index < 0 ? undefined : rows[index];
|
|
62
|
+
if (cas !== undefined && ((cas === null && current !== undefined) || (cas !== null && current?.updatedAt !== cas))) {
|
|
63
|
+
return { rows, result: { ok: false, current: current ?? row } };
|
|
64
|
+
}
|
|
62
65
|
if (current !== undefined && expect !== 'any' && (expect === 'absent' || queueOf(current.state) !== expect)) {
|
|
63
66
|
return { rows, result: { ok: false, current } };
|
|
64
67
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-merge",
|
|
3
3
|
"description": "Skill auto-merge domain: screening, two-round authoring, queues and commit orchestration (community build)",
|
|
4
|
-
"version": "0.30.
|
|
4
|
+
"version": "0.30.12",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@deepseek-ai/schemastery": "^3.18.5",
|
|
30
|
-
"@lmzhen/dsh-evolution-core": "^0.30.
|
|
31
|
-
"@lmzhen/dsh-evolution-merge-engine": "^0.30.
|
|
30
|
+
"@lmzhen/dsh-evolution-core": "^0.30.12",
|
|
31
|
+
"@lmzhen/dsh-evolution-merge-engine": "^0.30.12"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"@deepseek-ai/cordis": "^4.0.5"
|