@elaraai/e3-core 1.0.12 → 1.0.14
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/dist/src/dataflow/state-store/FileStateStore.js +41 -2
- package/dist/src/dataflow/state-store/FileStateStore.js.map +1 -1
- package/dist/src/dataflow/state-store/FileStateStore.spec.d.ts +6 -0
- package/dist/src/dataflow/state-store/FileStateStore.spec.d.ts.map +1 -0
- package/dist/src/dataflow/state-store/FileStateStore.spec.js +116 -0
- package/dist/src/dataflow/state-store/FileStateStore.spec.js.map +1 -0
- package/dist/src/dataflow/steps.spec.js +1 -0
- package/dist/src/dataflow/steps.spec.js.map +1 -1
- package/dist/src/dataflow-orchestration.spec.js +67 -3
- package/dist/src/dataflow-orchestration.spec.js.map +1 -1
- package/dist/src/dataflow.spec.js +1 -0
- package/dist/src/dataflow.spec.js.map +1 -1
- package/dist/src/dataset-refs.d.ts.map +1 -1
- package/dist/src/dataset-refs.js +7 -1
- package/dist/src/dataset-refs.js.map +1 -1
- package/dist/src/errors.d.ts +15 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +22 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/execution/processExec.d.ts.map +1 -1
- package/dist/src/execution/processExec.js +14 -10
- package/dist/src/execution/processExec.js.map +1 -1
- package/dist/src/gc.spec.js +45 -2
- package/dist/src/gc.spec.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/records.d.ts +136 -0
- package/dist/src/records.d.ts.map +1 -0
- package/dist/src/records.js +250 -0
- package/dist/src/records.js.map +1 -0
- package/dist/src/records.spec.d.ts +6 -0
- package/dist/src/records.spec.d.ts.map +1 -0
- package/dist/src/records.spec.js +299 -0
- package/dist/src/records.spec.js.map +1 -0
- package/dist/src/storage/in-memory/InMemoryStorage.d.ts +9 -0
- package/dist/src/storage/in-memory/InMemoryStorage.d.ts.map +1 -1
- package/dist/src/storage/in-memory/InMemoryStorage.js +26 -4
- package/dist/src/storage/in-memory/InMemoryStorage.js.map +1 -1
- package/dist/src/storage/interfaces.d.ts +64 -10
- package/dist/src/storage/interfaces.d.ts.map +1 -1
- package/dist/src/storage/local/LocalDatasetRefStore.d.ts +21 -0
- package/dist/src/storage/local/LocalDatasetRefStore.d.ts.map +1 -1
- package/dist/src/storage/local/LocalDatasetRefStore.js +100 -14
- package/dist/src/storage/local/LocalDatasetRefStore.js.map +1 -1
- package/dist/src/storage/local/LocalDatasetRefStore.spec.d.ts +6 -0
- package/dist/src/storage/local/LocalDatasetRefStore.spec.d.ts.map +1 -0
- package/dist/src/storage/local/LocalDatasetRefStore.spec.js +118 -0
- package/dist/src/storage/local/LocalDatasetRefStore.spec.js.map +1 -0
- package/dist/src/storage/local/LocalRepoStore.d.ts.map +1 -1
- package/dist/src/storage/local/LocalRepoStore.js +9 -0
- package/dist/src/storage/local/LocalRepoStore.js.map +1 -1
- package/dist/src/storage/local/gc.d.ts.map +1 -1
- package/dist/src/storage/local/gc.js +66 -0
- package/dist/src/storage/local/gc.js.map +1 -1
- package/dist/src/trees.d.ts.map +1 -1
- package/dist/src/trees.js +29 -5
- package/dist/src/trees.js.map +1 -1
- package/dist/src/workspaces.d.ts.map +1 -1
- package/dist/src/workspaces.js +116 -5
- package/dist/src/workspaces.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../src/records.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Record mutation execution — the write half of the function machinery.
|
|
7
|
+
*
|
|
8
|
+
* A mutation is a pure East reducer `(State, ...Args) => State` run via the
|
|
9
|
+
* graph-free {@link runDetached} kernel in a compare-and-swap retry loop:
|
|
10
|
+
* read state → reduce → write new state + commit objects → conditional ref
|
|
11
|
+
* write; retry on conflict. A crash at any point leaves only unreferenced
|
|
12
|
+
* objects (GC reclaims them) — never a torn record. The reducer's purity is
|
|
13
|
+
* what makes re-running against fresher state safe.
|
|
14
|
+
*/
|
|
15
|
+
import { variant, some, none, ArrayType, BlobType, encodeBeast2For, decodeBeast2For } from '@elaraai/east';
|
|
16
|
+
import { RecordObjectType, MutationObjectType, RecordCommitType, decodePackageObject, } from '@elaraai/e3-types';
|
|
17
|
+
import { workspaceGetPackage } from './workspaces.js';
|
|
18
|
+
import { refPathToKeypath } from './dataset-refs.js';
|
|
19
|
+
import { DatasetRefConflictError, WorkspaceLockError } from './errors.js';
|
|
20
|
+
const encodeCommit = encodeBeast2For(RecordCommitType);
|
|
21
|
+
const decodeCommit = decodeBeast2For(RecordCommitType);
|
|
22
|
+
const decodeRecordObject = decodeBeast2For(RecordObjectType);
|
|
23
|
+
const decodeMutationObject = decodeBeast2For(MutationObjectType);
|
|
24
|
+
const encodeArgsTuple = encodeBeast2For(ArrayType(BlobType));
|
|
25
|
+
const DEFAULT_LIMITS = {
|
|
26
|
+
timeoutMs: 60_000,
|
|
27
|
+
maxResultBytes: 64 * 1024 * 1024,
|
|
28
|
+
maxLogBytes: 64 * 1024,
|
|
29
|
+
};
|
|
30
|
+
/** Wall-clock budget for the compare-and-swap retry loop. Because each conflict
|
|
31
|
+
* means another writer committed (real progress), a hot record converges; the
|
|
32
|
+
* loop is deadline-bounded rather than capped at a fixed attempt count (which a
|
|
33
|
+
* thundering herd would exhaust, dropping a write). */
|
|
34
|
+
const DEFAULT_MAX_RETRY_MS = 30_000;
|
|
35
|
+
/**
|
|
36
|
+
* Run a record operation under a shared workspace lock (acquired internally
|
|
37
|
+
* unless the caller already holds one), so mutations coexist with dataflow but
|
|
38
|
+
* are fenced out by an exclusive deploy/remove — the §8 concurrency contract.
|
|
39
|
+
*/
|
|
40
|
+
async function withSharedWorkspaceLock(storage, repo, ws, externalLock, fn) {
|
|
41
|
+
let lock = externalLock ?? null;
|
|
42
|
+
if (!lock) {
|
|
43
|
+
lock = await storage.locks.acquire(repo, ws, variant('dataset_write', null), { mode: 'shared' });
|
|
44
|
+
if (!lock) {
|
|
45
|
+
const state = await storage.locks.getState(repo, ws);
|
|
46
|
+
throw new WorkspaceLockError(ws, state ? { acquiredAt: state.acquiredAt.toISOString(), operation: state.operation.type } : undefined);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
return await fn();
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
if (!externalLock)
|
|
54
|
+
await lock.release();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** Jittered exponential backoff (ms) before a compare-and-swap retry, so hot
|
|
58
|
+
* records don't lock-step their (expensive) reducer re-runs under contention. */
|
|
59
|
+
function casBackoffMs(attempt) {
|
|
60
|
+
return Math.min(2 ** attempt, 64) * (0.5 + Math.random());
|
|
61
|
+
}
|
|
62
|
+
/** Resolve a record name in a workspace's deployed package to its ref path and
|
|
63
|
+
* mutation table. Returns null if the workspace has no such record. */
|
|
64
|
+
async function resolveRecord(storage, repo, ws, recordName) {
|
|
65
|
+
const { hash } = await workspaceGetPackage(storage, repo, ws);
|
|
66
|
+
const pkg = decodePackageObject(await storage.objects.read(repo, hash));
|
|
67
|
+
const recHash = pkg.records.get(recordName);
|
|
68
|
+
if (!recHash)
|
|
69
|
+
return null;
|
|
70
|
+
const recObj = decodeRecordObject(await storage.objects.read(repo, recHash));
|
|
71
|
+
return {
|
|
72
|
+
refPath: recObj.path,
|
|
73
|
+
selfKeypath: refPathToKeypath(recObj.path),
|
|
74
|
+
mutations: recObj.mutations,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Map a non-success reducer run to its mutation outcome (nothing written).
|
|
78
|
+
* The reducer's captured stderr is forwarded on every failure so a human
|
|
79
|
+
* debugging a hand-written reducer sees its diagnostics. */
|
|
80
|
+
function failureOutcome(result) {
|
|
81
|
+
switch (result.kind) {
|
|
82
|
+
case 'failed':
|
|
83
|
+
return { kind: 'failed', exitCode: result.exitCode, stderr: result.stderr };
|
|
84
|
+
case 'timed_out':
|
|
85
|
+
return { kind: 'timed_out', ms: result.ms, stderr: result.stderr };
|
|
86
|
+
case 'too_large':
|
|
87
|
+
return { kind: 'too_large', bytes: result.bytes, limit: result.limit, stderr: result.stderr };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Apply a named mutation to a record under optimistic concurrency.
|
|
92
|
+
*
|
|
93
|
+
* Resolves the mutation, then loops: read the current state + revision, run the
|
|
94
|
+
* reducer against it, write the new state and a commit object, and conditionally
|
|
95
|
+
* swing the record ref. On a concurrent commit the conditional write conflicts
|
|
96
|
+
* and the loop retries against fresher state. Two mutations on the same record
|
|
97
|
+
* serialize; mutations on different records never contend.
|
|
98
|
+
*/
|
|
99
|
+
export async function recordMutate(storage, runner, repo, ws, recordName, mutationName, args, opts) {
|
|
100
|
+
return withSharedWorkspaceLock(storage, repo, ws, opts.lock, async () => {
|
|
101
|
+
const resolved = await resolveRecord(storage, repo, ws, recordName);
|
|
102
|
+
if (!resolved)
|
|
103
|
+
return { kind: 'invalid', message: `record '${recordName}' not found` };
|
|
104
|
+
const mutHash = resolved.mutations.get(mutationName);
|
|
105
|
+
if (!mutHash)
|
|
106
|
+
return { kind: 'invalid', message: `mutation '${mutationName}' not found on record '${recordName}'` };
|
|
107
|
+
const mutObj = decodeMutationObject(await storage.objects.read(repo, mutHash));
|
|
108
|
+
if (args.length !== mutObj.argTypes.length) {
|
|
109
|
+
return { kind: 'invalid', message: `mutation '${mutationName}' expects ${mutObj.argTypes.length} argument(s), got ${args.length}` };
|
|
110
|
+
}
|
|
111
|
+
const bodyIr = await storage.objects.read(repo, mutObj.bodyIr);
|
|
112
|
+
const limits = opts.limits ?? DEFAULT_LIMITS;
|
|
113
|
+
const deadline = Date.now() + (opts.maxRetryMs ?? DEFAULT_MAX_RETRY_MS);
|
|
114
|
+
for (let attempt = 1;; attempt++) {
|
|
115
|
+
if (opts.signal?.aborted)
|
|
116
|
+
return { kind: 'failed', exitCode: -1, stderr: 'aborted' };
|
|
117
|
+
const existing = await storage.datasets.readVersioned(repo, ws, resolved.refPath);
|
|
118
|
+
if (!existing || existing.ref.type !== 'value') {
|
|
119
|
+
return { kind: 'invalid', message: `record '${recordName}' has no state` };
|
|
120
|
+
}
|
|
121
|
+
const stateBytes = await storage.objects.read(repo, existing.ref.value.hash);
|
|
122
|
+
const result = await runner.runDetached({ bodyIr, args: [stateBytes, ...args], runner: mutObj.runner, limits }, { signal: opts.signal });
|
|
123
|
+
if (result.kind !== 'success')
|
|
124
|
+
return failureOutcome(result);
|
|
125
|
+
// Objects written before the conditional ref swing are invisible until the
|
|
126
|
+
// ref references them; a conflict simply orphans them for GC.
|
|
127
|
+
const newStateHash = await storage.objects.write(repo, result.value);
|
|
128
|
+
const argsHash = args.length > 0
|
|
129
|
+
? await storage.objects.write(repo, encodeArgsTuple(args))
|
|
130
|
+
: undefined;
|
|
131
|
+
const prevCommit = existing.ref.value.versions.get(resolved.selfKeypath);
|
|
132
|
+
const commit = {
|
|
133
|
+
parent: prevCommit !== undefined ? some(prevCommit) : none,
|
|
134
|
+
state: newStateHash,
|
|
135
|
+
mutation: mutationName,
|
|
136
|
+
args: argsHash !== undefined ? some(argsHash) : none,
|
|
137
|
+
actor: opts.actor,
|
|
138
|
+
at: new Date(),
|
|
139
|
+
};
|
|
140
|
+
const commitHash = await storage.objects.write(repo, encodeCommit(commit));
|
|
141
|
+
try {
|
|
142
|
+
await storage.datasets.writeIf(repo, ws, resolved.refPath, variant('value', { hash: newStateHash, versions: new Map([[resolved.selfKeypath, commitHash]]) }), existing.revision);
|
|
143
|
+
return { kind: 'committed', commitHash, stateHash: newStateHash };
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
if (!(err instanceof DatasetRefConflictError))
|
|
147
|
+
throw err;
|
|
148
|
+
if ((opts.maxAttempts !== undefined && attempt >= opts.maxAttempts) || Date.now() >= deadline) {
|
|
149
|
+
return { kind: 'conflict', attempts: attempt };
|
|
150
|
+
}
|
|
151
|
+
await new Promise((resolve) => setTimeout(resolve, casBackoffMs(attempt)));
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Describe a record's mutations (name + extra arg types), so dynamic callers
|
|
158
|
+
* can encode arguments. Returns null if the workspace has no such record.
|
|
159
|
+
*/
|
|
160
|
+
export async function recordDescribe(storage, repo, ws, recordName) {
|
|
161
|
+
const resolved = await resolveRecord(storage, repo, ws, recordName);
|
|
162
|
+
if (!resolved)
|
|
163
|
+
return null;
|
|
164
|
+
const mutations = [];
|
|
165
|
+
for (const [name, mutHash] of resolved.mutations) {
|
|
166
|
+
const mutObj = decodeMutationObject(await storage.objects.read(repo, mutHash));
|
|
167
|
+
mutations.push({ name, argTypes: mutObj.argTypes });
|
|
168
|
+
}
|
|
169
|
+
return { name: recordName, mutations };
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Compact a record's history: write a fresh `$compact` root commit
|
|
173
|
+
* (`parent: none`) over the current state and swing the ref to it. The prior
|
|
174
|
+
* commit chain becomes unreachable and is reclaimed by GC; the state itself is
|
|
175
|
+
* unchanged. Returns `committed` / `invalid` / `conflict` like a mutation.
|
|
176
|
+
*/
|
|
177
|
+
export async function recordCompact(storage, repo, ws, recordName, opts) {
|
|
178
|
+
return withSharedWorkspaceLock(storage, repo, ws, opts.lock, async () => {
|
|
179
|
+
const resolved = await resolveRecord(storage, repo, ws, recordName);
|
|
180
|
+
if (!resolved)
|
|
181
|
+
return { kind: 'invalid', message: `record '${recordName}' not found` };
|
|
182
|
+
const deadline = Date.now() + (opts.maxRetryMs ?? DEFAULT_MAX_RETRY_MS);
|
|
183
|
+
for (let attempt = 1;; attempt++) {
|
|
184
|
+
const existing = await storage.datasets.readVersioned(repo, ws, resolved.refPath);
|
|
185
|
+
if (!existing || existing.ref.type !== 'value') {
|
|
186
|
+
return { kind: 'invalid', message: `record '${recordName}' has no state` };
|
|
187
|
+
}
|
|
188
|
+
const stateHash = existing.ref.value.hash;
|
|
189
|
+
const commit = {
|
|
190
|
+
parent: none,
|
|
191
|
+
state: stateHash,
|
|
192
|
+
mutation: '$compact',
|
|
193
|
+
args: none,
|
|
194
|
+
actor: opts.actor,
|
|
195
|
+
at: new Date(),
|
|
196
|
+
};
|
|
197
|
+
const commitHash = await storage.objects.write(repo, encodeCommit(commit));
|
|
198
|
+
try {
|
|
199
|
+
await storage.datasets.writeIf(repo, ws, resolved.refPath, variant('value', { hash: stateHash, versions: new Map([[resolved.selfKeypath, commitHash]]) }), existing.revision);
|
|
200
|
+
return { kind: 'committed', commitHash, stateHash };
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
if (!(err instanceof DatasetRefConflictError))
|
|
204
|
+
throw err;
|
|
205
|
+
if ((opts.maxAttempts !== undefined && attempt >= opts.maxAttempts) || Date.now() >= deadline) {
|
|
206
|
+
return { kind: 'conflict', attempts: attempt };
|
|
207
|
+
}
|
|
208
|
+
await new Promise((resolve) => setTimeout(resolve, casBackoffMs(attempt)));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Walk a record's commit chain newest-first.
|
|
215
|
+
*
|
|
216
|
+
* @param opts.limit - Maximum commits to return (default: the whole chain)
|
|
217
|
+
* @param opts.from - Commit hash to start the walk at (a cursor for paging,
|
|
218
|
+
* trusted to be a hash this endpoint previously returned for this record);
|
|
219
|
+
* defaults to the record's head commit. A missing/undecodable cursor (or a
|
|
220
|
+
* corrupt link mid-walk) terminates the walk rather than throwing.
|
|
221
|
+
*/
|
|
222
|
+
export async function recordHistory(storage, repo, ws, recordName, opts = {}) {
|
|
223
|
+
const resolved = await resolveRecord(storage, repo, ws, recordName);
|
|
224
|
+
if (!resolved)
|
|
225
|
+
return [];
|
|
226
|
+
const ref = await storage.datasets.read(repo, ws, resolved.refPath);
|
|
227
|
+
if (!ref || ref.type !== 'value')
|
|
228
|
+
return [];
|
|
229
|
+
const entries = [];
|
|
230
|
+
const seen = new Set();
|
|
231
|
+
let next = opts.from ?? ref.value.versions.get(resolved.selfKeypath);
|
|
232
|
+
const limit = opts.limit ?? Infinity;
|
|
233
|
+
while (next !== undefined && entries.length < limit) {
|
|
234
|
+
// Bound the walk by distinct objects so a corrupted/cyclic parent can't hang.
|
|
235
|
+
if (seen.has(next))
|
|
236
|
+
break;
|
|
237
|
+
seen.add(next);
|
|
238
|
+
let commit;
|
|
239
|
+
try {
|
|
240
|
+
commit = decodeCommit(await storage.objects.read(repo, next));
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
243
|
+
break; // missing object or non-commit cursor — end the walk gracefully
|
|
244
|
+
}
|
|
245
|
+
entries.push({ hash: next, commit });
|
|
246
|
+
next = commit.parent.type === 'some' ? commit.parent.value : undefined;
|
|
247
|
+
}
|
|
248
|
+
return entries;
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=records.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.js","sourceRoot":"","sources":["../../src/records.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.spec.d.ts","sourceRoot":"","sources":["../../src/records.spec.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Licensed under BSL 1.1. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Tests for record mutation execution: deploy genesis, the compare-and-swap
|
|
7
|
+
* commit loop, history, and failure outcomes. The reducer process is faked so
|
|
8
|
+
* the loop is exercised deterministically without spawning a runtime.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, beforeEach, afterEach } from 'node:test';
|
|
11
|
+
import assert from 'node:assert';
|
|
12
|
+
import { join, dirname } from 'node:path';
|
|
13
|
+
import { East, IntegerType, StringType, encodeBeast2For, decodeBeast2For, toEastTypeValue, ArrayType, BlobType, variant } from '@elaraai/east';
|
|
14
|
+
import e3 from '@elaraai/e3';
|
|
15
|
+
import { recordMutate, recordHistory, recordCompact, recordDescribe } from './records.js';
|
|
16
|
+
import { repoGc } from './storage/local/gc.js';
|
|
17
|
+
import { snapshotInputVersions } from './dataset-refs.js';
|
|
18
|
+
import { WorkspaceLockError } from './errors.js';
|
|
19
|
+
import { workspaceGetDataset, workspaceSetDataset } from './trees.js';
|
|
20
|
+
import { packageImport } from './packages.js';
|
|
21
|
+
import { workspaceCreate, workspaceDeploy } from './workspaces.js';
|
|
22
|
+
import { createTestRepo, removeTestRepo, createTempDir, removeTempDir } from './test-helpers.js';
|
|
23
|
+
import { LocalStorage } from './storage/local/index.js';
|
|
24
|
+
const encodeInt = encodeBeast2For(IntegerType);
|
|
25
|
+
const decodeInt = decodeBeast2For(IntegerType);
|
|
26
|
+
const counterPath = [variant('field', 'records'), variant('field', 'counter')];
|
|
27
|
+
// The deployed workspace structure for the `.records.counter` leaf, used to
|
|
28
|
+
// drive snapshotInputVersions directly.
|
|
29
|
+
const counterStructure = variant('struct', new Map([
|
|
30
|
+
['records', variant('struct', new Map([
|
|
31
|
+
['counter', variant('value', { type: toEastTypeValue(IntegerType), writable: false })],
|
|
32
|
+
]))],
|
|
33
|
+
]));
|
|
34
|
+
/** Constant success outcome carrying the given new-state bytes. */
|
|
35
|
+
function successRunner(value) {
|
|
36
|
+
return runnerReturning(async () => ({ kind: 'success', value, stdout: '', stderr: '', stdoutTruncated: false, stderrTruncated: false }));
|
|
37
|
+
}
|
|
38
|
+
/** A runner whose detached run returns a fixed outcome (no subprocess). */
|
|
39
|
+
function runnerReturning(impl) {
|
|
40
|
+
return { runDetached: impl };
|
|
41
|
+
}
|
|
42
|
+
describe('records', () => {
|
|
43
|
+
let repo;
|
|
44
|
+
let tempDir;
|
|
45
|
+
let storage;
|
|
46
|
+
const ws = 'main';
|
|
47
|
+
beforeEach(async () => {
|
|
48
|
+
repo = createTestRepo();
|
|
49
|
+
tempDir = createTempDir();
|
|
50
|
+
// reposDir = parent of the repo, so repoGc's RepoStore scans resolve.
|
|
51
|
+
storage = new LocalStorage(dirname(repo));
|
|
52
|
+
// counter record + increment(state, by) => state + by
|
|
53
|
+
const counter = e3.record('counter', IntegerType, 0n);
|
|
54
|
+
const increment = e3.mutation('increment', counter, East.function([IntegerType, IntegerType], IntegerType, ($, state, by) => state.add(by)));
|
|
55
|
+
const pkg = e3.package('counters', '1.0.0', counter, increment);
|
|
56
|
+
const zip = join(tempDir, 'counters.zip');
|
|
57
|
+
await e3.export(pkg, zip);
|
|
58
|
+
await packageImport(storage, repo, zip);
|
|
59
|
+
await workspaceCreate(storage, repo, ws);
|
|
60
|
+
await workspaceDeploy(storage, repo, ws, 'counters', '1.0.0');
|
|
61
|
+
});
|
|
62
|
+
afterEach(() => {
|
|
63
|
+
removeTestRepo(repo);
|
|
64
|
+
removeTempDir(tempDir);
|
|
65
|
+
});
|
|
66
|
+
it('deploy mints a $init genesis commit and the initial state', async () => {
|
|
67
|
+
const history = await recordHistory(storage, repo, ws, 'counter');
|
|
68
|
+
assert.strictEqual(history.length, 1);
|
|
69
|
+
assert.strictEqual(history[0].commit.mutation, '$init');
|
|
70
|
+
assert.strictEqual(history[0].commit.parent.type, 'none');
|
|
71
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 0n);
|
|
72
|
+
});
|
|
73
|
+
it('commits a mutation: new state, commit chain, readable result', async () => {
|
|
74
|
+
const runner = runnerReturning(async () => ({
|
|
75
|
+
kind: 'success', value: encodeInt(5n),
|
|
76
|
+
stdout: '', stderr: '', stdoutTruncated: false, stderrTruncated: false,
|
|
77
|
+
}));
|
|
78
|
+
const outcome = await recordMutate(storage, runner, repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'cli:test' });
|
|
79
|
+
assert.strictEqual(outcome.kind, 'committed');
|
|
80
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 5n);
|
|
81
|
+
const history = await recordHistory(storage, repo, ws, 'counter');
|
|
82
|
+
assert.strictEqual(history.length, 2);
|
|
83
|
+
assert.strictEqual(history[0].commit.mutation, 'increment');
|
|
84
|
+
assert.strictEqual(history[0].commit.actor, 'cli:test');
|
|
85
|
+
assert.strictEqual(history[0].commit.parent.type, 'some'); // chained onto $init
|
|
86
|
+
});
|
|
87
|
+
it('the version self-entry equals the commit hash and the commit is timestamped (§6.3)', async () => {
|
|
88
|
+
const outcome = await recordMutate(storage, successRunner(encodeInt(5n)), repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'cli:test' });
|
|
89
|
+
assert.strictEqual(outcome.kind, 'committed');
|
|
90
|
+
const commitHash = outcome.commitHash;
|
|
91
|
+
// §6.3: the record ref's version self-entry carries the COMMIT hash (not the
|
|
92
|
+
// state hash), so change detection is commit-granular — asserted equal here,
|
|
93
|
+
// where other tests only observe that it changes.
|
|
94
|
+
const versions = await snapshotInputVersions(storage, repo, ws, counterStructure, new Set());
|
|
95
|
+
assert.strictEqual(versions.get('.records.counter'), commitHash, 'self-entry == commit hash');
|
|
96
|
+
// The head commit is timestamped — the audit trail's `at`.
|
|
97
|
+
const head = (await recordHistory(storage, repo, ws, 'counter'))[0].commit;
|
|
98
|
+
assert.ok(head.at instanceof Date && !Number.isNaN(head.at.getTime()), 'commit.at is a valid timestamp');
|
|
99
|
+
});
|
|
100
|
+
it('a failed reducer writes nothing and leaves history intact', async () => {
|
|
101
|
+
const runner = runnerReturning(async () => ({
|
|
102
|
+
kind: 'failed', exitCode: 1,
|
|
103
|
+
stdout: '', stderr: 'reducer threw', stdoutTruncated: false, stderrTruncated: false,
|
|
104
|
+
}));
|
|
105
|
+
const objectsBefore = (await storage.objects.list(repo)).length;
|
|
106
|
+
const outcome = await recordMutate(storage, runner, repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'cli:test' });
|
|
107
|
+
assert.strictEqual(outcome.kind, 'failed');
|
|
108
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 0n);
|
|
109
|
+
assert.strictEqual((await recordHistory(storage, repo, ws, 'counter')).length, 1);
|
|
110
|
+
// §12.5: an aborted reducer writes NOTHING — recordMutate returns before any
|
|
111
|
+
// objects.write — so not even an orphan state/args/commit object is left.
|
|
112
|
+
assert.strictEqual((await storage.objects.list(repo)).length, objectsBefore, 'no object written on abort');
|
|
113
|
+
});
|
|
114
|
+
it('rejects unknown records, unknown mutations, and wrong arity', async () => {
|
|
115
|
+
const runner = runnerReturning(async () => ({
|
|
116
|
+
kind: 'success', value: encodeInt(1n),
|
|
117
|
+
stdout: '', stderr: '', stdoutTruncated: false, stderrTruncated: false,
|
|
118
|
+
}));
|
|
119
|
+
const unknownRecord = await recordMutate(storage, runner, repo, ws, 'nope', 'increment', [encodeInt(1n)], { actor: 'x' });
|
|
120
|
+
assert.strictEqual(unknownRecord.kind, 'invalid');
|
|
121
|
+
const unknownMutation = await recordMutate(storage, runner, repo, ws, 'counter', 'nope', [encodeInt(1n)], { actor: 'x' });
|
|
122
|
+
assert.strictEqual(unknownMutation.kind, 'invalid');
|
|
123
|
+
const wrongArity = await recordMutate(storage, runner, repo, ws, 'counter', 'increment', [], { actor: 'x' });
|
|
124
|
+
assert.strictEqual(wrongArity.kind, 'invalid');
|
|
125
|
+
// None of the rejects touched state or history.
|
|
126
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 0n);
|
|
127
|
+
assert.strictEqual((await recordHistory(storage, repo, ws, 'counter')).length, 1);
|
|
128
|
+
});
|
|
129
|
+
it('keeps the whole commit chain reachable through gc', async () => {
|
|
130
|
+
const runner = runnerReturning(async () => ({
|
|
131
|
+
kind: 'success', value: encodeInt(5n),
|
|
132
|
+
stdout: '', stderr: '', stdoutTruncated: false, stderrTruncated: false,
|
|
133
|
+
}));
|
|
134
|
+
await recordMutate(storage, runner, repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'cli:test' });
|
|
135
|
+
// gc would collect every commit if the head-commit hash in the ref's
|
|
136
|
+
// version vector and the chain it roots were not walked.
|
|
137
|
+
const result = await repoGc(storage, repo, { minAge: 0 });
|
|
138
|
+
assert.strictEqual(result.deletedObjects, 0, 'no reachable object collected');
|
|
139
|
+
const history = await recordHistory(storage, repo, ws, 'counter');
|
|
140
|
+
assert.strictEqual(history.length, 2, 'increment + $init survive');
|
|
141
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 5n);
|
|
142
|
+
});
|
|
143
|
+
it('retries when a concurrent writer wins the compare-and-swap', async () => {
|
|
144
|
+
const genesis = await storage.datasets.read(repo, ws, 'records/counter');
|
|
145
|
+
assert.ok(genesis && genesis.type === 'value');
|
|
146
|
+
const stateHash = genesis.value.hash;
|
|
147
|
+
let calls = 0;
|
|
148
|
+
const runner = runnerReturning(async () => {
|
|
149
|
+
calls++;
|
|
150
|
+
if (calls === 1) {
|
|
151
|
+
// Interfere mid-flight: same valid state, different version entry — the
|
|
152
|
+
// changed bytes bump the ref revision so the first writeIf conflicts.
|
|
153
|
+
await storage.datasets.write(repo, ws, 'records/counter', variant('value', {
|
|
154
|
+
hash: stateHash,
|
|
155
|
+
versions: new Map([['.records.counter', 'deadbeef'.padEnd(64, '0')]]),
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
return { kind: 'success', value: encodeInt(7n), stdout: '', stderr: '', stdoutTruncated: false, stderrTruncated: false };
|
|
159
|
+
});
|
|
160
|
+
const outcome = await recordMutate(storage, runner, repo, ws, 'counter', 'increment', [encodeInt(7n)], { actor: 'cli:test' });
|
|
161
|
+
assert.strictEqual(outcome.kind, 'committed');
|
|
162
|
+
assert.strictEqual(calls, 2, 'reducer re-ran against fresher state after the conflict');
|
|
163
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 7n);
|
|
164
|
+
});
|
|
165
|
+
it('change detection is commit-granular: an identical-state mutation still changes the version', async () => {
|
|
166
|
+
const before = (await snapshotInputVersions(storage, repo, ws, counterStructure, new Set())).get('.records.counter');
|
|
167
|
+
// A mutation that reproduces the identical state (state hash unchanged).
|
|
168
|
+
const outcome = await recordMutate(storage, successRunner(encodeInt(0n)), repo, ws, 'counter', 'increment', [encodeInt(0n)], { actor: 'cli:test' });
|
|
169
|
+
assert.strictEqual(outcome.kind, 'committed');
|
|
170
|
+
const after = (await snapshotInputVersions(storage, repo, ws, counterStructure, new Set())).get('.records.counter');
|
|
171
|
+
// The snapshot keys on the commit hash, so it changes even though the state did not — no ABA.
|
|
172
|
+
assert.notStrictEqual(after, before);
|
|
173
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 0n);
|
|
174
|
+
});
|
|
175
|
+
it('N concurrent increments all commit and converge with no lost updates', async () => {
|
|
176
|
+
// The reducer reads the current state (arg 0) and adds `by` (arg 1).
|
|
177
|
+
const adder = { runDetached: async (spec) => ({
|
|
178
|
+
kind: 'success', value: encodeInt(decodeInt(spec.args[0]) + decodeInt(spec.args[1])),
|
|
179
|
+
stdout: '', stderr: '', stdoutTruncated: false, stderrTruncated: false,
|
|
180
|
+
}) };
|
|
181
|
+
const K = 8;
|
|
182
|
+
const results = await Promise.all(Array.from({ length: K }, () => recordMutate(storage, adder, repo, ws, 'counter', 'increment', [encodeInt(1n)], { actor: 'cli:test' })));
|
|
183
|
+
assert.ok(results.every((r) => r.kind === 'committed'), 'every mutation committed');
|
|
184
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), BigInt(K));
|
|
185
|
+
// genesis + K commits, a single linear chain (no forks / lost updates).
|
|
186
|
+
assert.strictEqual((await recordHistory(storage, repo, ws, 'counter')).length, K + 1);
|
|
187
|
+
});
|
|
188
|
+
it('recordCompact resets history to a $compact root and gc reclaims the prior chain', async () => {
|
|
189
|
+
await recordMutate(storage, successRunner(encodeInt(5n)), repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'cli:test' });
|
|
190
|
+
assert.strictEqual((await recordHistory(storage, repo, ws, 'counter')).length, 2);
|
|
191
|
+
const outcome = await recordCompact(storage, repo, ws, 'counter', { actor: 'cli:test' });
|
|
192
|
+
assert.strictEqual(outcome.kind, 'committed');
|
|
193
|
+
const hist = await recordHistory(storage, repo, ws, 'counter');
|
|
194
|
+
assert.strictEqual(hist.length, 1);
|
|
195
|
+
assert.strictEqual(hist[0].commit.mutation, '$compact');
|
|
196
|
+
assert.strictEqual(hist[0].commit.parent.type, 'none');
|
|
197
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 5n); // state preserved
|
|
198
|
+
const gc = await repoGc(storage, repo, { minAge: 0 });
|
|
199
|
+
assert.ok(gc.deletedObjects > 0, 'the pre-compact commit chain is collected');
|
|
200
|
+
assert.strictEqual((await recordHistory(storage, repo, ws, 'counter')).length, 1); // head survives
|
|
201
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 5n);
|
|
202
|
+
});
|
|
203
|
+
it('recordCompact on an unknown record is invalid', async () => {
|
|
204
|
+
assert.strictEqual((await recordCompact(storage, repo, ws, 'nope', { actor: 'x' })).kind, 'invalid');
|
|
205
|
+
});
|
|
206
|
+
it('records the args tuple on a commit and none on $init', async () => {
|
|
207
|
+
const decodeArgs = decodeBeast2For(ArrayType(BlobType));
|
|
208
|
+
await recordMutate(storage, successRunner(encodeInt(5n)), repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'cli:test' });
|
|
209
|
+
const hist = await recordHistory(storage, repo, ws, 'counter');
|
|
210
|
+
const incArgs = hist[0].commit.args;
|
|
211
|
+
if (incArgs.type !== 'some')
|
|
212
|
+
throw new Error('expected the increment commit to record its args');
|
|
213
|
+
const storedArgs = decodeArgs(await storage.objects.read(repo, incArgs.value));
|
|
214
|
+
assert.strictEqual(storedArgs.length, 1);
|
|
215
|
+
assert.ok(Buffer.from(storedArgs[0]).equals(Buffer.from(encodeInt(5n))), 'stored args round-trip to the input bytes');
|
|
216
|
+
assert.strictEqual(hist[1].commit.args.type, 'none'); // $init has no args
|
|
217
|
+
});
|
|
218
|
+
it('recordDescribe returns mutation signatures and null for an unknown record', async () => {
|
|
219
|
+
const sig = await recordDescribe(storage, repo, ws, 'counter');
|
|
220
|
+
assert.ok(sig);
|
|
221
|
+
assert.strictEqual(sig.name, 'counter');
|
|
222
|
+
assert.deepStrictEqual(sig.mutations.map((m) => m.name), ['increment']);
|
|
223
|
+
assert.strictEqual(sig.mutations[0].argTypes.length, 1);
|
|
224
|
+
assert.strictEqual(await recordDescribe(storage, repo, ws, 'nope'), null);
|
|
225
|
+
});
|
|
226
|
+
it('rejects a raw set on a record path (mutations are the only door)', async () => {
|
|
227
|
+
await assert.rejects(workspaceSetDataset(storage, repo, ws, counterPath, 42n, IntegerType), /not writable/);
|
|
228
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 0n);
|
|
229
|
+
});
|
|
230
|
+
it('redeploy preserves committed record state and history when the type is unchanged', async () => {
|
|
231
|
+
await recordMutate(storage, successRunner(encodeInt(9n)), repo, ws, 'counter', 'increment', [encodeInt(9n)], { actor: 'cli:test' });
|
|
232
|
+
const lenBefore = (await recordHistory(storage, repo, ws, 'counter')).length;
|
|
233
|
+
await workspaceDeploy(storage, repo, ws, 'counters', '1.0.0'); // redeploy onto the live workspace
|
|
234
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 9n); // not reset to 0n
|
|
235
|
+
assert.strictEqual((await recordHistory(storage, repo, ws, 'counter')).length, lenBefore); // chain intact
|
|
236
|
+
});
|
|
237
|
+
it('a rejected type-change redeploy leaves the workspace fully intact', async () => {
|
|
238
|
+
await recordMutate(storage, successRunner(encodeInt(3n)), repo, ws, 'counter', 'increment', [encodeInt(3n)], { actor: 'x' });
|
|
239
|
+
const lenBefore = (await recordHistory(storage, repo, ws, 'counter')).length;
|
|
240
|
+
// A new package version where `counter` is a String record instead of Integer.
|
|
241
|
+
const counterStr = e3.record('counter', StringType, '');
|
|
242
|
+
const pkg2 = e3.package('counters', '2.0.0', counterStr);
|
|
243
|
+
const zip2 = join(tempDir, 'counters2.zip');
|
|
244
|
+
await e3.export(pkg2, zip2);
|
|
245
|
+
await packageImport(storage, repo, zip2);
|
|
246
|
+
await assert.rejects(workspaceDeploy(storage, repo, ws, 'counters', '2.0.0'), /changed type/);
|
|
247
|
+
// The rejection fires before any destructive write, so state + history + the
|
|
248
|
+
// Integer typing are all untouched (no torn workspace, no data loss).
|
|
249
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 3n);
|
|
250
|
+
assert.strictEqual((await recordHistory(storage, repo, ws, 'counter')).length, lenBefore);
|
|
251
|
+
});
|
|
252
|
+
it('redeploy without the record drops it (record removed)', async () => {
|
|
253
|
+
await recordMutate(storage, successRunner(encodeInt(4n)), repo, ws, 'counter', 'increment', [encodeInt(4n)], { actor: 'x' });
|
|
254
|
+
const noRecord = e3.package('counters', '3.0.0', e3.input('greeting', StringType, 'hi'));
|
|
255
|
+
const zip3 = join(tempDir, 'counters-norecord.zip');
|
|
256
|
+
await e3.export(noRecord, zip3);
|
|
257
|
+
await packageImport(storage, repo, zip3);
|
|
258
|
+
await workspaceDeploy(storage, repo, ws, 'counters', '3.0.0');
|
|
259
|
+
await assert.rejects(workspaceGetDataset(storage, repo, ws, counterPath)); // path gone from the structure
|
|
260
|
+
});
|
|
261
|
+
it('a mutation and a compaction are fenced out by an exclusive deploy/remove lock', async () => {
|
|
262
|
+
const held = await storage.locks.acquire(repo, ws, variant('deployment', null)); // default exclusive
|
|
263
|
+
assert.ok(held);
|
|
264
|
+
try {
|
|
265
|
+
await assert.rejects(recordMutate(storage, successRunner(encodeInt(5n)), repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'x' }), WorkspaceLockError);
|
|
266
|
+
await assert.rejects(recordCompact(storage, repo, ws, 'counter', { actor: 'x' }), WorkspaceLockError);
|
|
267
|
+
assert.strictEqual(await workspaceGetDataset(storage, repo, ws, counterPath), 0n); // untouched while fenced
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
await held.release();
|
|
271
|
+
}
|
|
272
|
+
// Once released, the mutation commits — proving it was the lock, not another failure.
|
|
273
|
+
assert.strictEqual((await recordMutate(storage, successRunner(encodeInt(5n)), repo, ws, 'counter', 'increment', [encodeInt(5n)], { actor: 'x' })).kind, 'committed');
|
|
274
|
+
});
|
|
275
|
+
it('forwards reducer stderr on timed_out and too_large outcomes', async () => {
|
|
276
|
+
const timedOut = await recordMutate(storage, runnerReturning(async () => ({ kind: 'timed_out', ms: 1234, stderr: 'slow reducer', stdout: '', stdoutTruncated: false, stderrTruncated: false })), repo, ws, 'counter', 'increment', [encodeInt(1n)], { actor: 'x' });
|
|
277
|
+
assert.strictEqual(timedOut.kind, 'timed_out');
|
|
278
|
+
assert.strictEqual(timedOut.stderr, 'slow reducer');
|
|
279
|
+
const tooLarge = await recordMutate(storage, runnerReturning(async () => ({ kind: 'too_large', bytes: 999, limit: 100, stderr: 'huge state', stdout: '', stdoutTruncated: false, stderrTruncated: false })), repo, ws, 'counter', 'increment', [encodeInt(1n)], { actor: 'x' });
|
|
280
|
+
assert.strictEqual(tooLarge.kind, 'too_large');
|
|
281
|
+
assert.strictEqual(tooLarge.stderr, 'huge state');
|
|
282
|
+
});
|
|
283
|
+
it('history pages with a from cursor and ends gracefully on an unknown cursor', async () => {
|
|
284
|
+
for (let i = 0; i < 3; i++) {
|
|
285
|
+
await recordMutate(storage, successRunner(encodeInt(BigInt(i + 1))), repo, ws, 'counter', 'increment', [encodeInt(1n)], { actor: 'x' });
|
|
286
|
+
}
|
|
287
|
+
const all = await recordHistory(storage, repo, ws, 'counter');
|
|
288
|
+
assert.strictEqual(all.length, 4); // $init + 3
|
|
289
|
+
const page1 = await recordHistory(storage, repo, ws, 'counter', { limit: 2 });
|
|
290
|
+
assert.deepStrictEqual(page1.map((e) => e.hash), all.slice(0, 2).map((e) => e.hash));
|
|
291
|
+
const cursor = page1[1].commit.parent;
|
|
292
|
+
assert.strictEqual(cursor.type, 'some');
|
|
293
|
+
const page2 = await recordHistory(storage, repo, ws, 'counter', { from: cursor.type === 'some' ? cursor.value : undefined, limit: 10 });
|
|
294
|
+
assert.deepStrictEqual(page2.map((e) => e.hash), all.slice(2).map((e) => e.hash)); // contiguous, no overlap
|
|
295
|
+
// An unknown/garbage cursor terminates the walk rather than throwing.
|
|
296
|
+
assert.deepStrictEqual(await recordHistory(storage, repo, ws, 'counter', { from: 'cafef00d'.padEnd(64, '0') }), []);
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
//# sourceMappingURL=records.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"records.spec.js","sourceRoot":"","sources":["../../src/records.spec.ts"],"names":[],"mappings":"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"}
|