xstate 6.0.0-beta.1 → 6.0.0-beta.2
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/{createActor-551369be.development.esm.js → createActor-0250284a.development.esm.js} +244 -41
- package/dist/{createActor-cbe3abac.esm.js → createActor-20a97166.esm.js} +243 -40
- package/dist/{createActor-a49ae0ce.development.cjs.js → createActor-c029d29f.development.cjs.js} +245 -40
- package/dist/{createActor-25900f76.cjs.js → createActor-c91c9ffe.cjs.js} +244 -39
- package/dist/declarations/src/createActor.d.ts +3 -1
- package/dist/declarations/src/createMachine.d.ts +6 -3
- package/dist/declarations/src/durable/index.d.ts +43 -8
- package/dist/declarations/src/effectDescriptor.d.ts +2 -2
- package/dist/declarations/src/machineVersion.types.d.ts +2 -2
- package/dist/declarations/src/setup.d.ts +2 -2
- package/dist/declarations/src/systemTransition.d.ts +1 -1
- package/dist/declarations/src/types.d.ts +4 -2
- package/dist/declarations/src/types.v6.d.ts +37 -2
- package/dist/{effectDescriptor-f73da4ec.development.cjs.js → effectDescriptor-3fff5c51.development.cjs.js} +5 -5
- package/dist/{effectDescriptor-2fa27c54.cjs.js → effectDescriptor-47f73e7e.cjs.js} +5 -5
- package/dist/{effectDescriptor-321a8ce9.development.esm.js → effectDescriptor-5ac7dccb.development.esm.js} +5 -5
- package/dist/{effectDescriptor-d8b0f749.esm.js → effectDescriptor-e93df910.esm.js} +5 -5
- package/dist/{machineSchemas-88d01821.cjs.js → legacySnapshot-8d595687.cjs.js} +117 -1
- package/dist/{machineSchemas-45c21bc2.esm.js → legacySnapshot-9e06feb4.esm.js} +116 -2
- package/dist/{machineSchemas-b5736804.development.esm.js → legacySnapshot-ae6594a7.development.esm.js} +117 -3
- package/dist/{machineSchemas-6d96bef4.development.cjs.js → legacySnapshot-ebf0b2b8.development.cjs.js} +118 -2
- package/dist/xstate-actors.cjs.js +1 -1
- package/dist/xstate-actors.development.cjs.js +1 -1
- package/dist/xstate-actors.development.esm.js +2 -2
- package/dist/xstate-actors.esm.js +2 -2
- package/dist/xstate-actors.umd.min.js +1 -1
- package/dist/xstate-actors.umd.min.js.map +1 -1
- package/dist/xstate-durable.cjs.js +120 -10
- package/dist/xstate-durable.development.cjs.js +120 -10
- package/dist/xstate-durable.development.esm.js +120 -10
- package/dist/xstate-durable.esm.js +120 -10
- package/dist/xstate-durable.umd.min.js +1 -1
- package/dist/xstate-durable.umd.min.js.map +1 -1
- package/dist/xstate-fsm.cjs.js +4 -4
- package/dist/xstate-fsm.development.cjs.js +4 -4
- package/dist/xstate-fsm.development.esm.js +4 -4
- package/dist/xstate-fsm.esm.js +4 -4
- package/dist/xstate-fsm.umd.min.js +1 -1
- package/dist/xstate-fsm.umd.min.js.map +1 -1
- package/dist/xstate-graph.cjs.js +1 -1
- package/dist/xstate-graph.development.cjs.js +1 -1
- package/dist/xstate-graph.development.esm.js +2 -2
- package/dist/xstate-graph.esm.js +2 -2
- package/dist/xstate-graph.umd.min.js +1 -1
- package/dist/xstate-graph.umd.min.js.map +1 -1
- package/dist/xstate-persist.cjs.js +23 -12
- package/dist/xstate-persist.development.cjs.js +23 -12
- package/dist/xstate-persist.development.esm.js +17 -6
- package/dist/xstate-persist.esm.js +17 -6
- package/dist/xstate-persist.umd.min.js +1 -1
- package/dist/xstate-persist.umd.min.js.map +1 -1
- package/dist/xstate-validation.cjs.js +1 -1
- package/dist/xstate-validation.development.cjs.js +1 -1
- package/dist/xstate-validation.development.esm.js +1 -1
- package/dist/xstate-validation.esm.js +1 -1
- package/dist/xstate.cjs.js +63 -51
- package/dist/xstate.development.cjs.js +63 -51
- package/dist/xstate.development.esm.js +53 -41
- package/dist/xstate.esm.js +53 -41
- package/dist/xstate.umd.min.js +1 -1
- package/dist/xstate.umd.min.js.map +1 -1
- package/docs/api-stability.json +267 -249
- package/docs/backend-workflows.md +3 -3
- package/docs/durable-execution.md +72 -48
- package/docs/errors.md +2 -2
- package/docs/examples.md +34 -34
- package/docs/fsm.md +2 -1
- package/docs/guards.md +1 -1
- package/docs/index.md +1 -1
- package/docs/invoke.md +34 -2
- package/docs/persistence.md +16 -10
- package/docs/serialization.md +1 -1
- package/docs/setup-and-provide.md +3 -3
- package/docs/spawn.md +1 -1
- package/docs/system-transitions.md +6 -6
- package/docs/tutorial.md +5 -5
- package/docs/typescript.md +9 -0
- package/docs/xstate-v5-to-v6.md +17 -17
- package/package.json +1 -1
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var dist_xstatePersist = require('./xstate-persist.cjs.js');
|
|
6
|
-
var createActor = require('./createActor-
|
|
7
|
-
var effectDescriptor = require('./effectDescriptor-
|
|
8
|
-
require('./
|
|
6
|
+
var createActor = require('./createActor-c91c9ffe.cjs.js');
|
|
7
|
+
var effectDescriptor = require('./effectDescriptor-47f73e7e.cjs.js');
|
|
8
|
+
require('./legacySnapshot-8d595687.cjs.js');
|
|
9
9
|
require('./validation-4561b43c.cjs.js');
|
|
10
10
|
|
|
11
11
|
/** @experimental */
|
|
@@ -20,6 +20,36 @@ require('./validation-4561b43c.cjs.js');
|
|
|
20
20
|
* @experimental
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* A root-addressed event that the execution received but has not processed,
|
|
25
|
+
* stored in a checkpoint. `source` is the sender's logical address.
|
|
26
|
+
*
|
|
27
|
+
* @experimental
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Everything needed to resume an execution: the persisted snapshot, the next
|
|
32
|
+
* transition index and the events received but not yet processed. Persist
|
|
33
|
+
* the whole object atomically and pass it to `restore()`.
|
|
34
|
+
*
|
|
35
|
+
* @experimental
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
// Lifecycle events that address a child by `actorId`. Snapshot updates are
|
|
39
|
+
// not stored: a restored child reports its current snapshot when it starts.
|
|
40
|
+
const storedLifecycleEvents = new Set(['xstate.done.actor', 'xstate.error.actor', 'xstate.timeout.actor']);
|
|
41
|
+
function isCheckpoint(value) {
|
|
42
|
+
return !!value && typeof value === 'object' && 'inbox' in value && 'nextTransitionIndex' in value && 'snapshot' in value;
|
|
43
|
+
}
|
|
44
|
+
function isInboxEntry(item) {
|
|
45
|
+
if (!item || typeof item !== 'object') return false;
|
|
46
|
+
const {
|
|
47
|
+
event,
|
|
48
|
+
source
|
|
49
|
+
} = item;
|
|
50
|
+
return !!event && typeof event.type === 'string' && (source === undefined || !!source && typeof source['@actor'] === 'string' && (source.incarnation === undefined || typeof source.incarnation === 'string'));
|
|
51
|
+
}
|
|
52
|
+
|
|
23
53
|
/** @experimental */
|
|
24
54
|
|
|
25
55
|
/**
|
|
@@ -149,6 +179,15 @@ function createDurable(logic, adapter, options) {
|
|
|
149
179
|
// loop to take them through `waitForEvent()`.
|
|
150
180
|
const pendingRootEvents = [];
|
|
151
181
|
|
|
182
|
+
// For a stored lifecycle event: the child it addresses in `snapshot`, or
|
|
183
|
+
// `null` when that child is gone. `undefined` for any other event.
|
|
184
|
+
const lifecycleChild = (snapshot, event) => {
|
|
185
|
+
if (!createActor.isMachineSnapshot(snapshot) || !storedLifecycleEvents.has(event.type) || typeof event.actorId !== 'string') {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
return snapshot.children[event.actorId] ?? null;
|
|
189
|
+
};
|
|
190
|
+
|
|
152
191
|
// Every inter-actor edge is an async handoff to the runtime, and every
|
|
153
192
|
// handoff queues behind the last one: hosts whose step or activity model
|
|
154
193
|
// forbids concurrent entries depend on that, and so does deterministic
|
|
@@ -289,6 +328,16 @@ function createDurable(logic, adapter, options) {
|
|
|
289
328
|
}
|
|
290
329
|
const inspect = options?.inspect;
|
|
291
330
|
|
|
331
|
+
// Runs a transition as this execution: views it derives belong to this
|
|
332
|
+
// execution, and its systems report to the execution's inspector.
|
|
333
|
+
const owner = {
|
|
334
|
+
runtime: wrappedSystemRuntime,
|
|
335
|
+
inspect
|
|
336
|
+
};
|
|
337
|
+
function inExecution(fn) {
|
|
338
|
+
return createActor.withExecutionOwner(owner, () => createActor.withSystemInspector(inspect, fn));
|
|
339
|
+
}
|
|
340
|
+
|
|
292
341
|
// Attaches the execution's inspector to a system that does not have it
|
|
293
342
|
// yet. Systems constructed inside a transition get it at construction (the
|
|
294
343
|
// ambient inspector); this covers systems materialized outside that window
|
|
@@ -319,10 +368,12 @@ function createDurable(logic, adapter, options) {
|
|
|
319
368
|
const visit = actor => {
|
|
320
369
|
if (!systems.has(actor.system)) {
|
|
321
370
|
systems.add(actor.system);
|
|
322
|
-
if (
|
|
323
|
-
|
|
371
|
+
if (createActor.adoptSystem(actor.system, owner)) {
|
|
372
|
+
if (wrappedSystemRuntime) {
|
|
373
|
+
actor.system.runtime = wrappedSystemRuntime;
|
|
374
|
+
}
|
|
375
|
+
wireInspection(actor.system);
|
|
324
376
|
}
|
|
325
|
-
wireInspection(actor.system);
|
|
326
377
|
}
|
|
327
378
|
if (recursive) {
|
|
328
379
|
const children = actor.getSnapshot().children;
|
|
@@ -354,14 +405,55 @@ function createDurable(logic, adapter, options) {
|
|
|
354
405
|
get nextTransitionIndex() {
|
|
355
406
|
return nextTransitionIndex;
|
|
356
407
|
},
|
|
357
|
-
|
|
408
|
+
checkpoint(snapshot, persistOptions) {
|
|
409
|
+
const inbox = [];
|
|
410
|
+
for (const {
|
|
411
|
+
event,
|
|
412
|
+
source
|
|
413
|
+
} of pendingRootEvents) {
|
|
414
|
+
const child = lifecycleChild(snapshot, event);
|
|
415
|
+
if (event.type === 'xstate.snapshot.actor' || child !== undefined && (!child || event.sessionId !== undefined && child.sessionId !== undefined && child.sessionId !== event.sessionId)) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
inbox.push({
|
|
419
|
+
event,
|
|
420
|
+
source: source && {
|
|
421
|
+
'@actor': source.address,
|
|
422
|
+
...(createActor.isRemoteActorRef(source) && source.sessionId !== undefined ? {
|
|
423
|
+
incarnation: source.sessionId
|
|
424
|
+
} : {})
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return {
|
|
429
|
+
snapshot: logic.getPersistedSnapshot?.(snapshot, persistOptions) ?? snapshot,
|
|
430
|
+
nextTransitionIndex,
|
|
431
|
+
inbox
|
|
432
|
+
};
|
|
433
|
+
},
|
|
434
|
+
restore(checkpointOrSnapshot) {
|
|
435
|
+
const checkpoint = isCheckpoint(checkpointOrSnapshot) ? checkpointOrSnapshot : undefined;
|
|
358
436
|
if (restored || nextTransitionIndex !== startingTransitionIndex || currentBatch) {
|
|
359
437
|
throw new Error('restore() requires a fresh durable execution');
|
|
360
438
|
}
|
|
439
|
+
if (checkpoint) {
|
|
440
|
+
if (!Array.isArray(checkpoint.inbox) || !checkpoint.inbox.every(isInboxEntry)) {
|
|
441
|
+
throw new TypeError('The checkpoint inbox is invalid.');
|
|
442
|
+
}
|
|
443
|
+
if (adapter.transitionIndex !== undefined && adapter.transitionIndex !== checkpoint.nextTransitionIndex) {
|
|
444
|
+
throw new RangeError(`The adapter's transitionIndex (${adapter.transitionIndex}) does not match the checkpoint's nextTransitionIndex (${checkpoint.nextTransitionIndex}).`);
|
|
445
|
+
}
|
|
446
|
+
if (!Number.isSafeInteger(checkpoint.nextTransitionIndex) || checkpoint.nextTransitionIndex < 0) {
|
|
447
|
+
throw new RangeError('nextTransitionIndex must be a non-negative safe integer');
|
|
448
|
+
}
|
|
449
|
+
nextTransitionIndex = checkpoint.nextTransitionIndex;
|
|
450
|
+
lastTransitionIndex = nextTransitionIndex === 0 ? undefined : nextTransitionIndex - 1;
|
|
451
|
+
}
|
|
452
|
+
const persistedSnapshot = checkpoint ? checkpoint.snapshot : checkpointOrSnapshot;
|
|
361
453
|
const {
|
|
362
454
|
snapshot,
|
|
363
455
|
scope
|
|
364
|
-
} =
|
|
456
|
+
} = inExecution(() => createActor.withExecutionIdentity(executionIdentity, () => {
|
|
365
457
|
const scope = createActor.createInertActorScope(logic);
|
|
366
458
|
const snapshot = dist_xstatePersist.restoreLogicSnapshot(logic, persistedSnapshot, scope);
|
|
367
459
|
createActor.setInertActorScopeSnapshot(scope, snapshot, false);
|
|
@@ -370,6 +462,24 @@ function createDurable(logic, adapter, options) {
|
|
|
370
462
|
scope
|
|
371
463
|
};
|
|
372
464
|
}));
|
|
465
|
+
for (const {
|
|
466
|
+
event,
|
|
467
|
+
source
|
|
468
|
+
} of checkpoint?.inbox ?? []) {
|
|
469
|
+
const child = lifecycleChild(snapshot, event);
|
|
470
|
+
if (child === null) {
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
pendingRootEvents.push({
|
|
474
|
+
// A restored child has a new session; its pending lifecycle events
|
|
475
|
+
// follow it.
|
|
476
|
+
event: child && child.sessionId !== undefined && 'sessionId' in event ? {
|
|
477
|
+
...event,
|
|
478
|
+
sessionId: child.sessionId
|
|
479
|
+
} : event,
|
|
480
|
+
source: source && execution.getActorRef(snapshot, source['@actor'])
|
|
481
|
+
});
|
|
482
|
+
}
|
|
373
483
|
const effects = [];
|
|
374
484
|
if (snapshot.status === 'active') {
|
|
375
485
|
const {
|
|
@@ -399,11 +509,11 @@ function createDurable(logic, adapter, options) {
|
|
|
399
509
|
if (restored) {
|
|
400
510
|
throw new Error('initialTransition() cannot initialize a restored execution');
|
|
401
511
|
}
|
|
402
|
-
const [snapshot, effects] =
|
|
512
|
+
const [snapshot, effects] = inExecution(() => createActor.withExecutionIdentity(executionIdentity, () => effectDescriptor.initialTransition(logic, ...args)));
|
|
403
513
|
return [installSystemRuntime(snapshot), tagEffects(effects)];
|
|
404
514
|
},
|
|
405
515
|
transition(snapshot, event) {
|
|
406
|
-
const [nextSnapshot, effects] =
|
|
516
|
+
const [nextSnapshot, effects] = inExecution(() => createActor.withExecutionIdentity(executionIdentity, () => effectDescriptor.transition(logic, snapshot, event)));
|
|
407
517
|
return [installSystemRuntime(nextSnapshot), tagEffects(effects)];
|
|
408
518
|
},
|
|
409
519
|
getActorRef(snapshot, address) {
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var dist_xstatePersist = require('./xstate-persist.development.cjs.js');
|
|
6
|
-
var createActor = require('./createActor-
|
|
7
|
-
var effectDescriptor = require('./effectDescriptor-
|
|
8
|
-
require('./
|
|
6
|
+
var createActor = require('./createActor-c029d29f.development.cjs.js');
|
|
7
|
+
var effectDescriptor = require('./effectDescriptor-3fff5c51.development.cjs.js');
|
|
8
|
+
require('./legacySnapshot-ebf0b2b8.development.cjs.js');
|
|
9
9
|
require('./validation-f2714a35.development.cjs.js');
|
|
10
10
|
|
|
11
11
|
/** @experimental */
|
|
@@ -20,6 +20,36 @@ require('./validation-f2714a35.development.cjs.js');
|
|
|
20
20
|
* @experimental
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* A root-addressed event that the execution received but has not processed,
|
|
25
|
+
* stored in a checkpoint. `source` is the sender's logical address.
|
|
26
|
+
*
|
|
27
|
+
* @experimental
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Everything needed to resume an execution: the persisted snapshot, the next
|
|
32
|
+
* transition index and the events received but not yet processed. Persist
|
|
33
|
+
* the whole object atomically and pass it to `restore()`.
|
|
34
|
+
*
|
|
35
|
+
* @experimental
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
// Lifecycle events that address a child by `actorId`. Snapshot updates are
|
|
39
|
+
// not stored: a restored child reports its current snapshot when it starts.
|
|
40
|
+
const storedLifecycleEvents = new Set(['xstate.done.actor', 'xstate.error.actor', 'xstate.timeout.actor']);
|
|
41
|
+
function isCheckpoint(value) {
|
|
42
|
+
return !!value && typeof value === 'object' && 'inbox' in value && 'nextTransitionIndex' in value && 'snapshot' in value;
|
|
43
|
+
}
|
|
44
|
+
function isInboxEntry(item) {
|
|
45
|
+
if (!item || typeof item !== 'object') return false;
|
|
46
|
+
const {
|
|
47
|
+
event,
|
|
48
|
+
source
|
|
49
|
+
} = item;
|
|
50
|
+
return !!event && typeof event.type === 'string' && (source === undefined || !!source && typeof source['@actor'] === 'string' && (source.incarnation === undefined || typeof source.incarnation === 'string'));
|
|
51
|
+
}
|
|
52
|
+
|
|
23
53
|
/** @experimental */
|
|
24
54
|
|
|
25
55
|
/**
|
|
@@ -149,6 +179,15 @@ function createDurable(logic, adapter, options) {
|
|
|
149
179
|
// loop to take them through `waitForEvent()`.
|
|
150
180
|
const pendingRootEvents = [];
|
|
151
181
|
|
|
182
|
+
// For a stored lifecycle event: the child it addresses in `snapshot`, or
|
|
183
|
+
// `null` when that child is gone. `undefined` for any other event.
|
|
184
|
+
const lifecycleChild = (snapshot, event) => {
|
|
185
|
+
if (!createActor.isMachineSnapshot(snapshot) || !storedLifecycleEvents.has(event.type) || typeof event.actorId !== 'string') {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
return snapshot.children[event.actorId] ?? null;
|
|
189
|
+
};
|
|
190
|
+
|
|
152
191
|
// Every inter-actor edge is an async handoff to the runtime, and every
|
|
153
192
|
// handoff queues behind the last one: hosts whose step or activity model
|
|
154
193
|
// forbids concurrent entries depend on that, and so does deterministic
|
|
@@ -289,6 +328,16 @@ function createDurable(logic, adapter, options) {
|
|
|
289
328
|
}
|
|
290
329
|
const inspect = options?.inspect;
|
|
291
330
|
|
|
331
|
+
// Runs a transition as this execution: views it derives belong to this
|
|
332
|
+
// execution, and its systems report to the execution's inspector.
|
|
333
|
+
const owner = {
|
|
334
|
+
runtime: wrappedSystemRuntime,
|
|
335
|
+
inspect
|
|
336
|
+
};
|
|
337
|
+
function inExecution(fn) {
|
|
338
|
+
return createActor.withExecutionOwner(owner, () => createActor.withSystemInspector(inspect, fn));
|
|
339
|
+
}
|
|
340
|
+
|
|
292
341
|
// Attaches the execution's inspector to a system that does not have it
|
|
293
342
|
// yet. Systems constructed inside a transition get it at construction (the
|
|
294
343
|
// ambient inspector); this covers systems materialized outside that window
|
|
@@ -319,10 +368,12 @@ function createDurable(logic, adapter, options) {
|
|
|
319
368
|
const visit = actor => {
|
|
320
369
|
if (!systems.has(actor.system)) {
|
|
321
370
|
systems.add(actor.system);
|
|
322
|
-
if (
|
|
323
|
-
|
|
371
|
+
if (createActor.adoptSystem(actor.system, owner)) {
|
|
372
|
+
if (wrappedSystemRuntime) {
|
|
373
|
+
actor.system.runtime = wrappedSystemRuntime;
|
|
374
|
+
}
|
|
375
|
+
wireInspection(actor.system);
|
|
324
376
|
}
|
|
325
|
-
wireInspection(actor.system);
|
|
326
377
|
}
|
|
327
378
|
if (recursive) {
|
|
328
379
|
const children = actor.getSnapshot().children;
|
|
@@ -354,14 +405,55 @@ function createDurable(logic, adapter, options) {
|
|
|
354
405
|
get nextTransitionIndex() {
|
|
355
406
|
return nextTransitionIndex;
|
|
356
407
|
},
|
|
357
|
-
|
|
408
|
+
checkpoint(snapshot, persistOptions) {
|
|
409
|
+
const inbox = [];
|
|
410
|
+
for (const {
|
|
411
|
+
event,
|
|
412
|
+
source
|
|
413
|
+
} of pendingRootEvents) {
|
|
414
|
+
const child = lifecycleChild(snapshot, event);
|
|
415
|
+
if (event.type === 'xstate.snapshot.actor' || child !== undefined && (!child || event.sessionId !== undefined && child.sessionId !== undefined && child.sessionId !== event.sessionId)) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
inbox.push({
|
|
419
|
+
event,
|
|
420
|
+
source: source && {
|
|
421
|
+
'@actor': source.address,
|
|
422
|
+
...(createActor.isRemoteActorRef(source) && source.sessionId !== undefined ? {
|
|
423
|
+
incarnation: source.sessionId
|
|
424
|
+
} : {})
|
|
425
|
+
}
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return {
|
|
429
|
+
snapshot: logic.getPersistedSnapshot?.(snapshot, persistOptions) ?? snapshot,
|
|
430
|
+
nextTransitionIndex,
|
|
431
|
+
inbox
|
|
432
|
+
};
|
|
433
|
+
},
|
|
434
|
+
restore(checkpointOrSnapshot) {
|
|
435
|
+
const checkpoint = isCheckpoint(checkpointOrSnapshot) ? checkpointOrSnapshot : undefined;
|
|
358
436
|
if (restored || nextTransitionIndex !== startingTransitionIndex || currentBatch) {
|
|
359
437
|
throw new Error('restore() requires a fresh durable execution');
|
|
360
438
|
}
|
|
439
|
+
if (checkpoint) {
|
|
440
|
+
if (!Array.isArray(checkpoint.inbox) || !checkpoint.inbox.every(isInboxEntry)) {
|
|
441
|
+
throw new TypeError('The checkpoint inbox is invalid.');
|
|
442
|
+
}
|
|
443
|
+
if (adapter.transitionIndex !== undefined && adapter.transitionIndex !== checkpoint.nextTransitionIndex) {
|
|
444
|
+
throw new RangeError(`The adapter's transitionIndex (${adapter.transitionIndex}) does not match the checkpoint's nextTransitionIndex (${checkpoint.nextTransitionIndex}).`);
|
|
445
|
+
}
|
|
446
|
+
if (!Number.isSafeInteger(checkpoint.nextTransitionIndex) || checkpoint.nextTransitionIndex < 0) {
|
|
447
|
+
throw new RangeError('nextTransitionIndex must be a non-negative safe integer');
|
|
448
|
+
}
|
|
449
|
+
nextTransitionIndex = checkpoint.nextTransitionIndex;
|
|
450
|
+
lastTransitionIndex = nextTransitionIndex === 0 ? undefined : nextTransitionIndex - 1;
|
|
451
|
+
}
|
|
452
|
+
const persistedSnapshot = checkpoint ? checkpoint.snapshot : checkpointOrSnapshot;
|
|
361
453
|
const {
|
|
362
454
|
snapshot,
|
|
363
455
|
scope
|
|
364
|
-
} =
|
|
456
|
+
} = inExecution(() => createActor.withExecutionIdentity(executionIdentity, () => {
|
|
365
457
|
const scope = createActor.createInertActorScope(logic);
|
|
366
458
|
const snapshot = dist_xstatePersist.restoreLogicSnapshot(logic, persistedSnapshot, scope);
|
|
367
459
|
createActor.setInertActorScopeSnapshot(scope, snapshot, false);
|
|
@@ -370,6 +462,24 @@ function createDurable(logic, adapter, options) {
|
|
|
370
462
|
scope
|
|
371
463
|
};
|
|
372
464
|
}));
|
|
465
|
+
for (const {
|
|
466
|
+
event,
|
|
467
|
+
source
|
|
468
|
+
} of checkpoint?.inbox ?? []) {
|
|
469
|
+
const child = lifecycleChild(snapshot, event);
|
|
470
|
+
if (child === null) {
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
pendingRootEvents.push({
|
|
474
|
+
// A restored child has a new session; its pending lifecycle events
|
|
475
|
+
// follow it.
|
|
476
|
+
event: child && child.sessionId !== undefined && 'sessionId' in event ? {
|
|
477
|
+
...event,
|
|
478
|
+
sessionId: child.sessionId
|
|
479
|
+
} : event,
|
|
480
|
+
source: source && execution.getActorRef(snapshot, source['@actor'])
|
|
481
|
+
});
|
|
482
|
+
}
|
|
373
483
|
const effects = [];
|
|
374
484
|
if (snapshot.status === 'active') {
|
|
375
485
|
const {
|
|
@@ -399,11 +509,11 @@ function createDurable(logic, adapter, options) {
|
|
|
399
509
|
if (restored) {
|
|
400
510
|
throw new Error('initialTransition() cannot initialize a restored execution');
|
|
401
511
|
}
|
|
402
|
-
const [snapshot, effects] =
|
|
512
|
+
const [snapshot, effects] = inExecution(() => createActor.withExecutionIdentity(executionIdentity, () => effectDescriptor.initialTransition(logic, ...args)));
|
|
403
513
|
return [installSystemRuntime(snapshot), tagEffects(effects)];
|
|
404
514
|
},
|
|
405
515
|
transition(snapshot, event) {
|
|
406
|
-
const [nextSnapshot, effects] =
|
|
516
|
+
const [nextSnapshot, effects] = inExecution(() => createActor.withExecutionIdentity(executionIdentity, () => effectDescriptor.transition(logic, snapshot, event)));
|
|
407
517
|
return [installSystemRuntime(nextSnapshot), tagEffects(effects)];
|
|
408
518
|
},
|
|
409
519
|
getActorRef(snapshot, address) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { restoreLogicSnapshot } from './xstate-persist.development.esm.js';
|
|
2
|
-
import { j as encodeAddressSegment, aL as getRootActorId, aM as RUNTIME_OPERATIONS,
|
|
3
|
-
import {
|
|
4
|
-
import './
|
|
2
|
+
import { j as encodeAddressSegment, aL as getRootActorId, aM as RUNTIME_OPERATIONS, aI as isRemoteActorRef, aB as createStartEffect, aN as createTimerEffect, aO as getSnapshotActorRef, z as isMachineSnapshot, aP as withExecutionOwner, y as matchesTimerKey, aQ as getTimerStart, aR as recordTimerStart, K as deliverEvent, aS as withSystemInspector, aT as adoptSystem, aU as withExecutionIdentity, ah as createInertActorScope, ai as setInertActorScopeSnapshot, ak as attachSnapshotActorRef } from './createActor-0250284a.development.esm.js';
|
|
3
|
+
import { d as describeExecutableEffect, a as initialTransition, t as transition } from './effectDescriptor-5ac7dccb.development.esm.js';
|
|
4
|
+
import './legacySnapshot-ae6594a7.development.esm.js';
|
|
5
5
|
import './validation-e69470ad.development.esm.js';
|
|
6
6
|
|
|
7
7
|
/** @experimental */
|
|
@@ -16,6 +16,36 @@ import './validation-e69470ad.development.esm.js';
|
|
|
16
16
|
* @experimental
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* A root-addressed event that the execution received but has not processed,
|
|
21
|
+
* stored in a checkpoint. `source` is the sender's logical address.
|
|
22
|
+
*
|
|
23
|
+
* @experimental
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Everything needed to resume an execution: the persisted snapshot, the next
|
|
28
|
+
* transition index and the events received but not yet processed. Persist
|
|
29
|
+
* the whole object atomically and pass it to `restore()`.
|
|
30
|
+
*
|
|
31
|
+
* @experimental
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
// Lifecycle events that address a child by `actorId`. Snapshot updates are
|
|
35
|
+
// not stored: a restored child reports its current snapshot when it starts.
|
|
36
|
+
const storedLifecycleEvents = new Set(['xstate.done.actor', 'xstate.error.actor', 'xstate.timeout.actor']);
|
|
37
|
+
function isCheckpoint(value) {
|
|
38
|
+
return !!value && typeof value === 'object' && 'inbox' in value && 'nextTransitionIndex' in value && 'snapshot' in value;
|
|
39
|
+
}
|
|
40
|
+
function isInboxEntry(item) {
|
|
41
|
+
if (!item || typeof item !== 'object') return false;
|
|
42
|
+
const {
|
|
43
|
+
event,
|
|
44
|
+
source
|
|
45
|
+
} = item;
|
|
46
|
+
return !!event && typeof event.type === 'string' && (source === undefined || !!source && typeof source['@actor'] === 'string' && (source.incarnation === undefined || typeof source.incarnation === 'string'));
|
|
47
|
+
}
|
|
48
|
+
|
|
19
49
|
/** @experimental */
|
|
20
50
|
|
|
21
51
|
/**
|
|
@@ -145,6 +175,15 @@ function createDurable(logic, adapter, options) {
|
|
|
145
175
|
// loop to take them through `waitForEvent()`.
|
|
146
176
|
const pendingRootEvents = [];
|
|
147
177
|
|
|
178
|
+
// For a stored lifecycle event: the child it addresses in `snapshot`, or
|
|
179
|
+
// `null` when that child is gone. `undefined` for any other event.
|
|
180
|
+
const lifecycleChild = (snapshot, event) => {
|
|
181
|
+
if (!isMachineSnapshot(snapshot) || !storedLifecycleEvents.has(event.type) || typeof event.actorId !== 'string') {
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
return snapshot.children[event.actorId] ?? null;
|
|
185
|
+
};
|
|
186
|
+
|
|
148
187
|
// Every inter-actor edge is an async handoff to the runtime, and every
|
|
149
188
|
// handoff queues behind the last one: hosts whose step or activity model
|
|
150
189
|
// forbids concurrent entries depend on that, and so does deterministic
|
|
@@ -285,6 +324,16 @@ function createDurable(logic, adapter, options) {
|
|
|
285
324
|
}
|
|
286
325
|
const inspect = options?.inspect;
|
|
287
326
|
|
|
327
|
+
// Runs a transition as this execution: views it derives belong to this
|
|
328
|
+
// execution, and its systems report to the execution's inspector.
|
|
329
|
+
const owner = {
|
|
330
|
+
runtime: wrappedSystemRuntime,
|
|
331
|
+
inspect
|
|
332
|
+
};
|
|
333
|
+
function inExecution(fn) {
|
|
334
|
+
return withExecutionOwner(owner, () => withSystemInspector(inspect, fn));
|
|
335
|
+
}
|
|
336
|
+
|
|
288
337
|
// Attaches the execution's inspector to a system that does not have it
|
|
289
338
|
// yet. Systems constructed inside a transition get it at construction (the
|
|
290
339
|
// ambient inspector); this covers systems materialized outside that window
|
|
@@ -315,10 +364,12 @@ function createDurable(logic, adapter, options) {
|
|
|
315
364
|
const visit = actor => {
|
|
316
365
|
if (!systems.has(actor.system)) {
|
|
317
366
|
systems.add(actor.system);
|
|
318
|
-
if (
|
|
319
|
-
|
|
367
|
+
if (adoptSystem(actor.system, owner)) {
|
|
368
|
+
if (wrappedSystemRuntime) {
|
|
369
|
+
actor.system.runtime = wrappedSystemRuntime;
|
|
370
|
+
}
|
|
371
|
+
wireInspection(actor.system);
|
|
320
372
|
}
|
|
321
|
-
wireInspection(actor.system);
|
|
322
373
|
}
|
|
323
374
|
if (recursive) {
|
|
324
375
|
const children = actor.getSnapshot().children;
|
|
@@ -350,14 +401,55 @@ function createDurable(logic, adapter, options) {
|
|
|
350
401
|
get nextTransitionIndex() {
|
|
351
402
|
return nextTransitionIndex;
|
|
352
403
|
},
|
|
353
|
-
|
|
404
|
+
checkpoint(snapshot, persistOptions) {
|
|
405
|
+
const inbox = [];
|
|
406
|
+
for (const {
|
|
407
|
+
event,
|
|
408
|
+
source
|
|
409
|
+
} of pendingRootEvents) {
|
|
410
|
+
const child = lifecycleChild(snapshot, event);
|
|
411
|
+
if (event.type === 'xstate.snapshot.actor' || child !== undefined && (!child || event.sessionId !== undefined && child.sessionId !== undefined && child.sessionId !== event.sessionId)) {
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
inbox.push({
|
|
415
|
+
event,
|
|
416
|
+
source: source && {
|
|
417
|
+
'@actor': source.address,
|
|
418
|
+
...(isRemoteActorRef(source) && source.sessionId !== undefined ? {
|
|
419
|
+
incarnation: source.sessionId
|
|
420
|
+
} : {})
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
return {
|
|
425
|
+
snapshot: logic.getPersistedSnapshot?.(snapshot, persistOptions) ?? snapshot,
|
|
426
|
+
nextTransitionIndex,
|
|
427
|
+
inbox
|
|
428
|
+
};
|
|
429
|
+
},
|
|
430
|
+
restore(checkpointOrSnapshot) {
|
|
431
|
+
const checkpoint = isCheckpoint(checkpointOrSnapshot) ? checkpointOrSnapshot : undefined;
|
|
354
432
|
if (restored || nextTransitionIndex !== startingTransitionIndex || currentBatch) {
|
|
355
433
|
throw new Error('restore() requires a fresh durable execution');
|
|
356
434
|
}
|
|
435
|
+
if (checkpoint) {
|
|
436
|
+
if (!Array.isArray(checkpoint.inbox) || !checkpoint.inbox.every(isInboxEntry)) {
|
|
437
|
+
throw new TypeError('The checkpoint inbox is invalid.');
|
|
438
|
+
}
|
|
439
|
+
if (adapter.transitionIndex !== undefined && adapter.transitionIndex !== checkpoint.nextTransitionIndex) {
|
|
440
|
+
throw new RangeError(`The adapter's transitionIndex (${adapter.transitionIndex}) does not match the checkpoint's nextTransitionIndex (${checkpoint.nextTransitionIndex}).`);
|
|
441
|
+
}
|
|
442
|
+
if (!Number.isSafeInteger(checkpoint.nextTransitionIndex) || checkpoint.nextTransitionIndex < 0) {
|
|
443
|
+
throw new RangeError('nextTransitionIndex must be a non-negative safe integer');
|
|
444
|
+
}
|
|
445
|
+
nextTransitionIndex = checkpoint.nextTransitionIndex;
|
|
446
|
+
lastTransitionIndex = nextTransitionIndex === 0 ? undefined : nextTransitionIndex - 1;
|
|
447
|
+
}
|
|
448
|
+
const persistedSnapshot = checkpoint ? checkpoint.snapshot : checkpointOrSnapshot;
|
|
357
449
|
const {
|
|
358
450
|
snapshot,
|
|
359
451
|
scope
|
|
360
|
-
} =
|
|
452
|
+
} = inExecution(() => withExecutionIdentity(executionIdentity, () => {
|
|
361
453
|
const scope = createInertActorScope(logic);
|
|
362
454
|
const snapshot = restoreLogicSnapshot(logic, persistedSnapshot, scope);
|
|
363
455
|
setInertActorScopeSnapshot(scope, snapshot, false);
|
|
@@ -366,6 +458,24 @@ function createDurable(logic, adapter, options) {
|
|
|
366
458
|
scope
|
|
367
459
|
};
|
|
368
460
|
}));
|
|
461
|
+
for (const {
|
|
462
|
+
event,
|
|
463
|
+
source
|
|
464
|
+
} of checkpoint?.inbox ?? []) {
|
|
465
|
+
const child = lifecycleChild(snapshot, event);
|
|
466
|
+
if (child === null) {
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
469
|
+
pendingRootEvents.push({
|
|
470
|
+
// A restored child has a new session; its pending lifecycle events
|
|
471
|
+
// follow it.
|
|
472
|
+
event: child && child.sessionId !== undefined && 'sessionId' in event ? {
|
|
473
|
+
...event,
|
|
474
|
+
sessionId: child.sessionId
|
|
475
|
+
} : event,
|
|
476
|
+
source: source && execution.getActorRef(snapshot, source['@actor'])
|
|
477
|
+
});
|
|
478
|
+
}
|
|
369
479
|
const effects = [];
|
|
370
480
|
if (snapshot.status === 'active') {
|
|
371
481
|
const {
|
|
@@ -395,11 +505,11 @@ function createDurable(logic, adapter, options) {
|
|
|
395
505
|
if (restored) {
|
|
396
506
|
throw new Error('initialTransition() cannot initialize a restored execution');
|
|
397
507
|
}
|
|
398
|
-
const [snapshot, effects] =
|
|
508
|
+
const [snapshot, effects] = inExecution(() => withExecutionIdentity(executionIdentity, () => initialTransition(logic, ...args)));
|
|
399
509
|
return [installSystemRuntime(snapshot), tagEffects(effects)];
|
|
400
510
|
},
|
|
401
511
|
transition(snapshot, event) {
|
|
402
|
-
const [nextSnapshot, effects] =
|
|
512
|
+
const [nextSnapshot, effects] = inExecution(() => withExecutionIdentity(executionIdentity, () => transition(logic, snapshot, event)));
|
|
403
513
|
return [installSystemRuntime(nextSnapshot), tagEffects(effects)];
|
|
404
514
|
},
|
|
405
515
|
getActorRef(snapshot, address) {
|