@dudousxd/nestjs-durable-testing 0.20.0 → 0.21.0
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/index.d.ts +30 -1
- package/dist/index.js +61 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AdmissionBackend, StateStore, RunStatus, WorkflowEngine, InMemoryStateStore, InMemoryTransport, RunResult, WorkflowRef, StartOptions, WorkflowRun, StepCheckpoint, Transport } from '@dudousxd/nestjs-durable-core';
|
|
2
|
+
export { RUN_HISTORY_FIXTURE_VERSION } from '@dudousxd/nestjs-durable-core';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Builds an {@link AdmissionBackend} bound to the given test clock. Implementations that hold their
|
|
@@ -184,6 +185,34 @@ interface RunHistory {
|
|
|
184
185
|
run: WorkflowRun;
|
|
185
186
|
checkpoints: StepCheckpoint[];
|
|
186
187
|
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Capture a run's replayable history (the run row + its full checkpoint timeline) from anything with
|
|
191
|
+
* the read API: a `WorkflowEngine`, or a bare `StateStore` (the CLI's `durable export` uses the
|
|
192
|
+
* store). The fixture half of the {@link assertReplayable} loop: capture a representative run,
|
|
193
|
+
* commit it with {@link serializeRunHistory}, and assert it in CI via {@link parseRunHistory}.
|
|
194
|
+
* Returns `null` for an unknown run.
|
|
195
|
+
*/
|
|
196
|
+
declare function captureHistory(source: {
|
|
197
|
+
getRun(runId: string): Promise<WorkflowRun | null | undefined>;
|
|
198
|
+
listCheckpoints(runId: string): Promise<StepCheckpoint[]>;
|
|
199
|
+
}, runId: string): Promise<RunHistory | null>;
|
|
200
|
+
/**
|
|
201
|
+
* Serialize a captured history as a pretty-printed JSON fixture (with a trailing newline, so it
|
|
202
|
+
* commits cleanly). Read it back with {@link parseRunHistory}.
|
|
203
|
+
*/
|
|
204
|
+
declare function serializeRunHistory(history: RunHistory): string;
|
|
205
|
+
/**
|
|
206
|
+
* Parse a committed fixture (what {@link serializeRunHistory} / `durable export` writes) back into a
|
|
207
|
+
* {@link RunHistory}, reviving the `Date` fields JSON flattened to ISO strings, so
|
|
208
|
+
* `assertReplayable(register, parseRunHistory(readFileSync('fixture.json', 'utf8')))` just works.
|
|
209
|
+
*
|
|
210
|
+
* Throws on a fixture whose `version` is not {@link RUN_HISTORY_FIXTURE_VERSION}: a fixture written
|
|
211
|
+
* in another format would otherwise replay against the wrong shape. A fixture with NO `version` (a
|
|
212
|
+
* hand-built `{ run, checkpoints }`, the shape these docs showed before the marker existed) is read
|
|
213
|
+
* as version 1.
|
|
214
|
+
*/
|
|
215
|
+
declare function parseRunHistory(json: string): RunHistory;
|
|
187
216
|
/**
|
|
188
217
|
* Replay a recorded run's history against the CURRENT workflow code and throw if they diverged.
|
|
189
218
|
*
|
|
@@ -288,4 +317,4 @@ declare function aggregationFixture(): StepCheckpoint[];
|
|
|
288
317
|
*/
|
|
289
318
|
declare function registerCheckpointAggregationCases(t: (label: string, fn: () => Promise<void>) => void, getStore: () => StateStore, run: (over?: Partial<WorkflowRun>) => WorkflowRun): void;
|
|
290
319
|
|
|
291
|
-
export { type AdmissionBackendFactory, DURABLE_CANONICAL_COLUMNS, type DurableColumnMap, type DurableColumnMismatch, type HandleableTransport, MutableClock, type RunHistory, type StateStoreContext, type StateStoreFactory, StateStoreUnavailableError, type TestEngine, aggregationFixture, assertDurableColumns, assertOutput, assertReplayable, assertRunStatus, assertStepAttempts, assertStepsRan, assertTransportConformance, createTestEngine, failOnce, failTimes, preserveColumnExpectation, recordedSteps, registerCheckpointAggregationCases, runAdmissionBackendContract, runStateStoreContract };
|
|
320
|
+
export { type AdmissionBackendFactory, DURABLE_CANONICAL_COLUMNS, type DurableColumnMap, type DurableColumnMismatch, type HandleableTransport, MutableClock, type RunHistory, type StateStoreContext, type StateStoreFactory, StateStoreUnavailableError, type TestEngine, aggregationFixture, assertDurableColumns, assertOutput, assertReplayable, assertRunStatus, assertStepAttempts, assertStepsRan, assertTransportConformance, captureHistory, createTestEngine, failOnce, failTimes, parseRunHistory, preserveColumnExpectation, recordedSteps, registerCheckpointAggregationCases, runAdmissionBackendContract, runStateStoreContract, serializeRunHistory };
|
package/dist/index.js
CHANGED
|
@@ -375,7 +375,50 @@ function createTestEngine() {
|
|
|
375
375
|
__name(createTestEngine, "createTestEngine");
|
|
376
376
|
|
|
377
377
|
// src/replay.ts
|
|
378
|
-
import { InMemoryStateStore as InMemoryStateStore2, WorkflowEngine as WorkflowEngine2 } from "@dudousxd/nestjs-durable-core";
|
|
378
|
+
import { InMemoryStateStore as InMemoryStateStore2, RUN_HISTORY_FIXTURE_VERSION, WorkflowEngine as WorkflowEngine2 } from "@dudousxd/nestjs-durable-core";
|
|
379
|
+
async function captureHistory(source, runId) {
|
|
380
|
+
const run2 = await source.getRun(runId);
|
|
381
|
+
if (!run2) return null;
|
|
382
|
+
return {
|
|
383
|
+
run: run2,
|
|
384
|
+
checkpoints: await source.listCheckpoints(runId)
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
__name(captureHistory, "captureHistory");
|
|
388
|
+
function serializeRunHistory(history) {
|
|
389
|
+
return `${JSON.stringify({
|
|
390
|
+
version: RUN_HISTORY_FIXTURE_VERSION,
|
|
391
|
+
...history
|
|
392
|
+
}, null, 2)}
|
|
393
|
+
`;
|
|
394
|
+
}
|
|
395
|
+
__name(serializeRunHistory, "serializeRunHistory");
|
|
396
|
+
function parseRunHistory(json) {
|
|
397
|
+
const raw = JSON.parse(json);
|
|
398
|
+
if (!raw || typeof raw !== "object" || !raw.run || !Array.isArray(raw.checkpoints)) {
|
|
399
|
+
throw new Error("not a run history fixture: expected { run, checkpoints }");
|
|
400
|
+
}
|
|
401
|
+
if (raw.version !== void 0 && raw.version !== RUN_HISTORY_FIXTURE_VERSION) {
|
|
402
|
+
throw new Error(`unsupported run history fixture version ${JSON.stringify(raw.version)} (this kit reads version ${RUN_HISTORY_FIXTURE_VERSION}); re-export the fixture or upgrade @dudousxd/nestjs-durable-testing`);
|
|
403
|
+
}
|
|
404
|
+
const date = /* @__PURE__ */ __name((v) => new Date(v), "date");
|
|
405
|
+
const run2 = {
|
|
406
|
+
...raw.run,
|
|
407
|
+
createdAt: date(raw.run.createdAt),
|
|
408
|
+
updatedAt: date(raw.run.updatedAt)
|
|
409
|
+
};
|
|
410
|
+
const checkpoints = raw.checkpoints.map((cp2) => ({
|
|
411
|
+
...cp2,
|
|
412
|
+
enqueuedAt: date(cp2.enqueuedAt),
|
|
413
|
+
startedAt: date(cp2.startedAt),
|
|
414
|
+
finishedAt: date(cp2.finishedAt)
|
|
415
|
+
}));
|
|
416
|
+
return {
|
|
417
|
+
run: run2,
|
|
418
|
+
checkpoints
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
__name(parseRunHistory, "parseRunHistory");
|
|
379
422
|
async function assertReplayable(register, history) {
|
|
380
423
|
const store = new InMemoryStateStore2();
|
|
381
424
|
await store.createRun({
|
|
@@ -2314,6 +2357,18 @@ function runStateStoreContract(name, makeStore) {
|
|
|
2314
2357
|
await store.releaseRunLock("r1");
|
|
2315
2358
|
expect3(await store.tryLockRun("r1", "C", 9e3, 2600)).toBe(true);
|
|
2316
2359
|
});
|
|
2360
|
+
t("releaseRunLock with an owner clears only a lease that owner still holds", async () => {
|
|
2361
|
+
await store.createRun(run({
|
|
2362
|
+
id: "r1"
|
|
2363
|
+
}));
|
|
2364
|
+
expect3(await store.tryLockRun("r1", "A", 2e3, 1e3)).toBe(true);
|
|
2365
|
+
expect3(await store.tryLockRun("r1", "B", 4e3, 2500)).toBe(true);
|
|
2366
|
+
await store.releaseRunLock("r1", "A");
|
|
2367
|
+
expect3(await store.tryLockRun("r1", "C", 9e3, 3e3)).toBe(false);
|
|
2368
|
+
expect3((await store.getRun("r1"))?.lockedBy).toBe("B");
|
|
2369
|
+
await store.releaseRunLock("r1", "B");
|
|
2370
|
+
expect3(await store.tryLockRun("r1", "C", 9e3, 3e3)).toBe(true);
|
|
2371
|
+
});
|
|
2317
2372
|
t("renewRunLock only succeeds for the current owner", async () => {
|
|
2318
2373
|
await store.createRun(run({
|
|
2319
2374
|
id: "r1"
|
|
@@ -4239,6 +4294,7 @@ __name(assertTransportConformance, "assertTransportConformance");
|
|
|
4239
4294
|
export {
|
|
4240
4295
|
DURABLE_CANONICAL_COLUMNS,
|
|
4241
4296
|
MutableClock,
|
|
4297
|
+
RUN_HISTORY_FIXTURE_VERSION,
|
|
4242
4298
|
StateStoreUnavailableError,
|
|
4243
4299
|
aggregationFixture,
|
|
4244
4300
|
assertDurableColumns,
|
|
@@ -4248,13 +4304,16 @@ export {
|
|
|
4248
4304
|
assertStepAttempts,
|
|
4249
4305
|
assertStepsRan,
|
|
4250
4306
|
assertTransportConformance,
|
|
4307
|
+
captureHistory,
|
|
4251
4308
|
createTestEngine,
|
|
4252
4309
|
failOnce,
|
|
4253
4310
|
failTimes,
|
|
4311
|
+
parseRunHistory,
|
|
4254
4312
|
preserveColumnExpectation,
|
|
4255
4313
|
recordedSteps,
|
|
4256
4314
|
registerCheckpointAggregationCases,
|
|
4257
4315
|
runAdmissionBackendContract,
|
|
4258
|
-
runStateStoreContract
|
|
4316
|
+
runStateStoreContract,
|
|
4317
|
+
serializeRunHistory
|
|
4259
4318
|
};
|
|
4260
4319
|
//# sourceMappingURL=index.js.map
|