@lmzhen/dsh-evolution-state-storage 0.3.67 → 0.3.68
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 +47 -1
- package/lib/types/index.d.ts +42 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -170,6 +170,52 @@ const PENDING_RESOLVED_CAP = 200;
|
|
|
170
170
|
* interface change, no background sweeper).
|
|
171
171
|
*/
|
|
172
172
|
const REVIEW_STATE_SESSION_CAP = 500;
|
|
173
|
+
/**
|
|
174
|
+
* V27 G2.2: WHICH pending records the audit cap evicts, as one pure rule both
|
|
175
|
+
* providers apply (the two implementations had drifted into separate files and
|
|
176
|
+
* only one of them was ever updated by a later fix).
|
|
177
|
+
*
|
|
178
|
+
* Eligible = resolved (`approved`/`rejected`) and NOT a capability approval:
|
|
179
|
+
* v23 (AP-1) exempts those because the Creator-mode contract reads the LIVE
|
|
180
|
+
* approved list and a capability cannot be re-submitted for the same package,
|
|
181
|
+
* so eviction would make an approved capability permanently unactivatable.
|
|
182
|
+
* Ordering = oldest `resolvedAt` first; a missing or unparseable timestamp sorts
|
|
183
|
+
* LAST (json parity, v16) — an unknown time must never make a record the victim,
|
|
184
|
+
* and pending/executing rows are live work that is never trimmed.
|
|
185
|
+
*
|
|
186
|
+
* @param records - every pending record currently in the live table.
|
|
187
|
+
* @param cap - how many resolved records may be kept.
|
|
188
|
+
* @returns the records to evict, oldest first (empty when within the cap).
|
|
189
|
+
*/
|
|
190
|
+
function selectPendingOverflow(records, cap = 200) {
|
|
191
|
+
const resolved = records.filter((record) => (record.status === "approved" || record.status === "rejected") && record.kind !== "capability");
|
|
192
|
+
const overflow = resolved.length - cap;
|
|
193
|
+
if (overflow <= 0) return [];
|
|
194
|
+
const resolvedAtMs = (record) => {
|
|
195
|
+
if (!record.resolvedAt) return Number.MAX_SAFE_INTEGER;
|
|
196
|
+
const parsed = Date.parse(record.resolvedAt);
|
|
197
|
+
return Number.isNaN(parsed) ? Number.MAX_SAFE_INTEGER : parsed;
|
|
198
|
+
};
|
|
199
|
+
return [...resolved].sort((a, b) => resolvedAtMs(a) - resolvedAtMs(b)).slice(0, overflow);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* V27 G2.2: which review-state session rows a save evicts, as one pure rule
|
|
203
|
+
* both providers apply. The saving session is never a candidate (it is the most
|
|
204
|
+
* recent write by definition); the rest are ordered by their provider stamp
|
|
205
|
+
* ascending, with a missing stamp read as 0 = oldest, because an active session
|
|
206
|
+
* re-stamps its row on its next save and an unknown stamp is stale by
|
|
207
|
+
* construction. Exactly one row is dropped per over-cap save, which keeps the
|
|
208
|
+
* table at the cap in steady state.
|
|
209
|
+
*
|
|
210
|
+
* @param rows - the other sessions' rows, with their stamps.
|
|
211
|
+
* @param cap - how many session rows may exist.
|
|
212
|
+
* @returns the keys to delete, oldest first.
|
|
213
|
+
*/
|
|
214
|
+
function selectSessionOverflow(rows, options, cap = 500) {
|
|
215
|
+
const overflow = rows.length - cap + 1;
|
|
216
|
+
if (overflow <= 0) return [];
|
|
217
|
+
return [...rows].sort((a, b) => options.stampOf(a) - options.stampOf(b)).slice(0, overflow).map((row) => options.keyOf(row));
|
|
218
|
+
}
|
|
173
219
|
var EvolutionStateStorageRegistry = class extends Service {
|
|
174
220
|
providers = /* @__PURE__ */ new Map();
|
|
175
221
|
/** C-7 (v18): per-name dispose, mirroring the evolution-io registry. */
|
|
@@ -216,4 +262,4 @@ var EvolutionStateStorageRegistry = class extends Service {
|
|
|
216
262
|
}
|
|
217
263
|
};
|
|
218
264
|
//#endregion
|
|
219
|
-
export { CURATOR_STATE_FILE, CURATOR_STATE_KEY, CURATOR_STATE_TABLE, EvolutionStateStorageRegistry, EvolutionStateStorageRegistry as default, PENDING_ARCHIVE_BAK_FILE, PENDING_ARCHIVE_FILE, PENDING_LEGACY_FILE, PENDING_RESOLVED_CAP, PENDING_STATE_FILE, PENDING_TABLE, PROVIDER_DOMAIN, PROVIDER_JSON, REVIEW_STATE_FILE, REVIEW_STATE_SESSION_CAP, REVIEW_STATE_TABLE, UNKNOWN_FIELD_POLICY, assertCloneable, canClaimPending, canResolvePending, cloneRecord, recordIssue, releasedStatus };
|
|
265
|
+
export { CURATOR_STATE_FILE, CURATOR_STATE_KEY, CURATOR_STATE_TABLE, EvolutionStateStorageRegistry, EvolutionStateStorageRegistry as default, PENDING_ARCHIVE_BAK_FILE, PENDING_ARCHIVE_FILE, PENDING_LEGACY_FILE, PENDING_RESOLVED_CAP, PENDING_STATE_FILE, PENDING_TABLE, PROVIDER_DOMAIN, PROVIDER_JSON, REVIEW_STATE_FILE, REVIEW_STATE_SESSION_CAP, REVIEW_STATE_TABLE, UNKNOWN_FIELD_POLICY, assertCloneable, canClaimPending, canResolvePending, cloneRecord, recordIssue, releasedStatus, selectPendingOverflow, selectSessionOverflow };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -60,6 +60,41 @@ export declare const PENDING_RESOLVED_CAP = 200;
|
|
|
60
60
|
* interface change, no background sweeper).
|
|
61
61
|
*/
|
|
62
62
|
export declare const REVIEW_STATE_SESSION_CAP = 500;
|
|
63
|
+
/**
|
|
64
|
+
* V27 G2.2: WHICH pending records the audit cap evicts, as one pure rule both
|
|
65
|
+
* providers apply (the two implementations had drifted into separate files and
|
|
66
|
+
* only one of them was ever updated by a later fix).
|
|
67
|
+
*
|
|
68
|
+
* Eligible = resolved (`approved`/`rejected`) and NOT a capability approval:
|
|
69
|
+
* v23 (AP-1) exempts those because the Creator-mode contract reads the LIVE
|
|
70
|
+
* approved list and a capability cannot be re-submitted for the same package,
|
|
71
|
+
* so eviction would make an approved capability permanently unactivatable.
|
|
72
|
+
* Ordering = oldest `resolvedAt` first; a missing or unparseable timestamp sorts
|
|
73
|
+
* LAST (json parity, v16) — an unknown time must never make a record the victim,
|
|
74
|
+
* and pending/executing rows are live work that is never trimmed.
|
|
75
|
+
*
|
|
76
|
+
* @param records - every pending record currently in the live table.
|
|
77
|
+
* @param cap - how many resolved records may be kept.
|
|
78
|
+
* @returns the records to evict, oldest first (empty when within the cap).
|
|
79
|
+
*/
|
|
80
|
+
export declare function selectPendingOverflow(records: readonly PendingRecord[], cap?: number): PendingRecord[];
|
|
81
|
+
/**
|
|
82
|
+
* V27 G2.2: which review-state session rows a save evicts, as one pure rule
|
|
83
|
+
* both providers apply. The saving session is never a candidate (it is the most
|
|
84
|
+
* recent write by definition); the rest are ordered by their provider stamp
|
|
85
|
+
* ascending, with a missing stamp read as 0 = oldest, because an active session
|
|
86
|
+
* re-stamps its row on its next save and an unknown stamp is stale by
|
|
87
|
+
* construction. Exactly one row is dropped per over-cap save, which keeps the
|
|
88
|
+
* table at the cap in steady state.
|
|
89
|
+
*
|
|
90
|
+
* @param rows - the other sessions' rows, with their stamps.
|
|
91
|
+
* @param cap - how many session rows may exist.
|
|
92
|
+
* @returns the keys to delete, oldest first.
|
|
93
|
+
*/
|
|
94
|
+
export declare function selectSessionOverflow<T>(rows: readonly T[], options: {
|
|
95
|
+
keyOf(row: T): string;
|
|
96
|
+
stampOf(row: T): number;
|
|
97
|
+
}, cap?: number): string[];
|
|
63
98
|
/**
|
|
64
99
|
* Claim lifecycle (S3.3): pending →(claim)→ executing →(resolve)→ approved/rejected.
|
|
65
100
|
* release() rolls executing back to pending (failure path). A crash between
|
|
@@ -113,6 +148,13 @@ export interface EvolutionStateStorage {
|
|
|
113
148
|
* whole read → transform → write runs inside one provider transact, so a
|
|
114
149
|
* setPaused racing the run-core bookkeeping write can never interleave a
|
|
115
150
|
* stale load with a newer save.
|
|
151
|
+
*
|
|
152
|
+
* V27 S4: the record handed to `task` belongs to the task — a provider must
|
|
153
|
+
* NEVER pass the object it stores (both current providers hand out a copy:
|
|
154
|
+
* json re-parses its medium, the domain clones its record). Mutating the
|
|
155
|
+
* argument is not a supported way to write: a task that does so and then lets
|
|
156
|
+
* validation refuse the result would otherwise leave a mutated object in the
|
|
157
|
+
* provider's in-memory store.
|
|
116
158
|
*/
|
|
117
159
|
transactCuratorState(task: (current: CuratorStateRecord | null) => CuratorStateRecord | null): Promise<void>;
|
|
118
160
|
listPending(status?: PendingStatus): Promise<PendingRecord[]>;
|