@lmzhen/dsh-evolution-state-domain 0.3.62 → 0.3.64
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/README.md +1 -0
- package/lib/index.js +43 -11
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -23,4 +23,5 @@ Independent of request-prefix construction. This package does not alter the asse
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
- Requires the host-plane `storage-domain` facility. The bundle row stays dormant when it is absent.
|
|
26
|
+
- P2-4 (v15): the live pending table is BOUNDED — resolved (approved/rejected) records are kept to the most recent `PENDING_RESOLVED_CAP` (200, seam constant in `evolution-state-storage`); the oldest by `resolvedAt` are deleted on resolve. The audit ARCHIVE sidecar that the json provider maintains beyond the cap is json-specific (the domain seam has no sidecar facility) — resolved records past the cap are gone, not archived.
|
|
26
27
|
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { DomainError, defineDomain, domainTable } from "@deepseek-ai/dsh-storage-domain";
|
|
3
|
-
import { CURATOR_STATE_KEY, CURATOR_STATE_TABLE, PENDING_TABLE, PROVIDER_DOMAIN, REVIEW_STATE_TABLE, canClaimPending, canResolvePending, releasedStatus } from "@lmzhen/dsh-evolution-state-storage";
|
|
3
|
+
import { CURATOR_STATE_KEY, CURATOR_STATE_TABLE, PENDING_RESOLVED_CAP, PENDING_TABLE, PROVIDER_DOMAIN, REVIEW_STATE_TABLE, canClaimPending, canResolvePending, releasedStatus } from "@lmzhen/dsh-evolution-state-storage";
|
|
4
4
|
//#region lib/types/index.js
|
|
5
5
|
/**
|
|
6
6
|
* storage-domain provider for evolution state.
|
|
@@ -116,16 +116,22 @@ function apply(ctx) {
|
|
|
116
116
|
const provider = {
|
|
117
117
|
name: PROVIDER_DOMAIN,
|
|
118
118
|
async loadReviewState(sessionId) {
|
|
119
|
-
|
|
119
|
+
const record = (await ensure()).table(REVIEW_STATE_TABLE).get(sessionId);
|
|
120
|
+
return record === void 0 ? null : structuredClone(record);
|
|
120
121
|
},
|
|
121
122
|
async saveReviewState(sessionId, record) {
|
|
122
|
-
|
|
123
|
+
const parsed = reviewStateSchema.safeParse(record);
|
|
124
|
+
if (!parsed.success) throw new Error(`evolution-state-domain: refusing to persist an invalid review-state record: ${parsed.error.issues[0]?.message ?? "schema mismatch"}`);
|
|
125
|
+
await (await ensure()).table(REVIEW_STATE_TABLE).put(sessionId, parsed.data);
|
|
123
126
|
},
|
|
124
127
|
async loadCuratorState() {
|
|
125
|
-
|
|
128
|
+
const record = (await ensure()).table(CURATOR_STATE_TABLE).get(CURATOR_STATE_KEY);
|
|
129
|
+
return record === void 0 ? null : structuredClone(record);
|
|
126
130
|
},
|
|
127
131
|
async saveCuratorState(record) {
|
|
128
|
-
|
|
132
|
+
const parsed = curatorStateSchema.safeParse(record);
|
|
133
|
+
if (!parsed.success) throw new Error(`evolution-state-domain: refusing to persist an invalid curator-state record: ${parsed.error.issues[0]?.message ?? "schema mismatch"}`);
|
|
134
|
+
await (await ensure()).table(CURATOR_STATE_TABLE).put(CURATOR_STATE_KEY, parsed.data);
|
|
129
135
|
},
|
|
130
136
|
async transactCuratorState(task) {
|
|
131
137
|
const table = (await ensure()).table(CURATOR_STATE_TABLE);
|
|
@@ -146,10 +152,16 @@ function apply(ctx) {
|
|
|
146
152
|
else await table.delete(CURATOR_STATE_KEY);
|
|
147
153
|
},
|
|
148
154
|
async listPending(status = "pending") {
|
|
149
|
-
return [...(await ensure()).table(PENDING_TABLE).entries()].map(([, value]) => value).filter((record) => record.status === status);
|
|
155
|
+
return [...(await ensure()).table(PENDING_TABLE).entries()].map(([, value]) => structuredClone(value)).filter((record) => record.status === status);
|
|
150
156
|
},
|
|
151
157
|
async savePending(record) {
|
|
152
|
-
|
|
158
|
+
if (!Object.prototype.hasOwnProperty.call(record, "args")) throw new Error("evolution-state-domain: refusing to persist a pending record without the required \"args\" key");
|
|
159
|
+
const parsed = pendingSchema.safeParse({
|
|
160
|
+
...record,
|
|
161
|
+
args: record.args
|
|
162
|
+
});
|
|
163
|
+
if (!parsed.success) throw new Error(`evolution-state-domain: refusing to persist an invalid pending record: ${parsed.error.issues[0]?.message ?? "schema mismatch"}`);
|
|
164
|
+
await (await ensure()).table(PENDING_TABLE).put(record.id, parsed.data);
|
|
153
165
|
},
|
|
154
166
|
async claimPending(id, claimId) {
|
|
155
167
|
const table = (await ensure()).table(PENDING_TABLE);
|
|
@@ -166,7 +178,7 @@ function apply(ctx) {
|
|
|
166
178
|
};
|
|
167
179
|
return slot.record;
|
|
168
180
|
});
|
|
169
|
-
return slot.record === null ? null :
|
|
181
|
+
return slot.record === null ? null : structuredClone(slot.record);
|
|
170
182
|
} catch (error) {
|
|
171
183
|
if (error instanceof DomainError && error.code === "missing-key") return null;
|
|
172
184
|
throw error;
|
|
@@ -195,7 +207,7 @@ function apply(ctx) {
|
|
|
195
207
|
const table = (await ensure()).table(PENDING_TABLE);
|
|
196
208
|
try {
|
|
197
209
|
const resolved = { record: null };
|
|
198
|
-
const
|
|
210
|
+
const record = await table.update(id, (current) => {
|
|
199
211
|
if (!canResolvePending(current.status)) return current;
|
|
200
212
|
if (expectedClaimId !== void 0 && current.claimedBy !== expectedClaimId) return current;
|
|
201
213
|
resolved.record = {
|
|
@@ -205,12 +217,32 @@ function apply(ctx) {
|
|
|
205
217
|
};
|
|
206
218
|
return resolved.record;
|
|
207
219
|
});
|
|
220
|
+
if (resolved.record !== null) {
|
|
221
|
+
const resolvedEntries = [...table.entries()].map(([key, record]) => ({
|
|
222
|
+
key,
|
|
223
|
+
record
|
|
224
|
+
})).filter((entry) => entry.record.status === "approved" || entry.record.status === "rejected");
|
|
225
|
+
const resolvedAtMs = (record) => {
|
|
226
|
+
const parsed = Date.parse(record.resolvedAt ?? "");
|
|
227
|
+
return Number.isNaN(parsed) ? Number.MAX_SAFE_INTEGER : parsed;
|
|
228
|
+
};
|
|
229
|
+
resolvedEntries.sort((a, b) => resolvedAtMs(a.record) - resolvedAtMs(b.record));
|
|
230
|
+
const evicted = resolvedEntries.slice(0, Math.max(0, resolvedEntries.length - PENDING_RESOLVED_CAP));
|
|
231
|
+
for (const entry of evicted) {
|
|
232
|
+
const current = table.get(entry.key);
|
|
233
|
+
if (!(current !== void 0 && (current.status === "approved" || current.status === "rejected") && current.resolvedAt === entry.record.resolvedAt)) continue;
|
|
234
|
+
await table.delete(entry.key).catch((error) => {
|
|
235
|
+
ctx.logger.warn(`evolution-state-domain: pending-cap eviction for "${entry.key}" failed (will retry on the next resolve): ${error instanceof Error ? error.message : String(error)}`);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const rawRecord = record;
|
|
208
240
|
if (resolved.record === null) return {
|
|
209
|
-
record: rawRecord === null ? null :
|
|
241
|
+
record: rawRecord === null ? null : structuredClone(rawRecord),
|
|
210
242
|
applied: false
|
|
211
243
|
};
|
|
212
244
|
return {
|
|
213
|
-
record:
|
|
245
|
+
record: structuredClone(resolved.record),
|
|
214
246
|
applied: true
|
|
215
247
|
};
|
|
216
248
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmzhen/dsh-evolution-state-domain",
|
|
3
3
|
"description": "storage-domain provider for evolution state (community build)",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.64",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
37
37
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
38
38
|
"@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.2",
|
|
39
|
-
"@lmzhen/dsh-evolution-state-storage": "^0.3.
|
|
39
|
+
"@lmzhen/dsh-evolution-state-storage": "^0.3.64"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
43
43
|
"@deepseek-ai/dsh-storage-domain": "^0.1.1-rc.2",
|
|
44
44
|
"@deepseek-ai/dsh-storage": "^0.1.1-rc.2",
|
|
45
45
|
"@deepseek-ai/dsh-storage-json": "^0.1.1-rc.2",
|
|
46
|
-
"@lmzhen/dsh-evolution-state-storage": "^0.3.
|
|
46
|
+
"@lmzhen/dsh-evolution-state-storage": "^0.3.64"
|
|
47
47
|
}
|
|
48
48
|
}
|