effect-machine 0.14.0 → 0.15.1
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 +5 -2
- package/dist/actor.d.ts +13 -4
- package/dist/actor.js +91 -55
- package/dist/cluster/entity-machine.js +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/internal/runtime.d.ts +20 -1
- package/dist/internal/runtime.js +60 -47
- package/dist/machine.d.ts +37 -30
- package/dist/machine.js +5 -5
- package/dist/schema.d.ts +12 -5
- package/dist/schema.js +1 -0
- package/package.json +1 -1
- package/v3/dist/actor.d.ts +10 -4
- package/v3/dist/actor.js +80 -50
- package/v3/dist/cluster/entity-machine.js +1 -0
- package/v3/dist/index.d.ts +2 -2
- package/v3/dist/internal/runtime.d.ts +20 -1
- package/v3/dist/internal/runtime.js +60 -47
- package/v3/dist/machine.d.ts +37 -30
- package/v3/dist/machine.js +5 -5
package/README.md
CHANGED
|
@@ -98,6 +98,7 @@ const actor =
|
|
|
98
98
|
}),
|
|
99
99
|
},
|
|
100
100
|
});
|
|
101
|
+
yield * actor.start;
|
|
101
102
|
```
|
|
102
103
|
|
|
103
104
|
The same machine can run with different slot implementations in tests, local apps, or production. Slots are accepted everywhere the machine runs:
|
|
@@ -109,7 +110,7 @@ The same machine can run with different slot implementations in tests, local app
|
|
|
109
110
|
|
|
110
111
|
## Running Actors
|
|
111
112
|
|
|
112
|
-
`Machine.spawn`
|
|
113
|
+
`Machine.spawn` allocates an actor but does not start it. Call `actor.start` to fork the event loop, background effects, and spawn effects. Events sent before `start()` are queued.
|
|
113
114
|
|
|
114
115
|
```ts
|
|
115
116
|
const program = Effect.gen(function* () {
|
|
@@ -123,6 +124,7 @@ const program = Effect.gen(function* () {
|
|
|
123
124
|
),
|
|
124
125
|
},
|
|
125
126
|
});
|
|
127
|
+
yield* actor.start;
|
|
126
128
|
|
|
127
129
|
yield* actor.send(CheckoutEvent.Submit);
|
|
128
130
|
const finalState = yield* actor.awaitFinal;
|
|
@@ -133,6 +135,7 @@ Effect.runPromise(Effect.scoped(program));
|
|
|
133
135
|
|
|
134
136
|
Key actor operations:
|
|
135
137
|
|
|
138
|
+
- `start` forks the event loop (idempotent, required after `Machine.spawn`)
|
|
136
139
|
- `send(event)` queues and returns immediately
|
|
137
140
|
- `call(event)` returns full transition info
|
|
138
141
|
- `ask(event)` returns a typed domain reply (requires `Event.reply(...)`)
|
|
@@ -140,7 +143,7 @@ Key actor operations:
|
|
|
140
143
|
- `stop` interrupts now; `drain` processes the remaining queue first
|
|
141
144
|
- `watch(other)` completes when another actor stops
|
|
142
145
|
|
|
143
|
-
For named actors or shared lookup, use an actor system:
|
|
146
|
+
For named actors or shared lookup, use an actor system. `system.spawn` auto-starts — no `actor.start` needed:
|
|
144
147
|
|
|
145
148
|
```ts
|
|
146
149
|
import { ActorSystemDefault, ActorSystemService } from "effect-machine";
|
package/dist/actor.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ActorStoppedError, DuplicateActorError, NoReplyError } from "./errors.j
|
|
|
3
3
|
import { ProvideSlots, SlotsDef } from "./slot.js";
|
|
4
4
|
import { ActorExit, Supervision } from "./supervision.js";
|
|
5
5
|
import { ProcessEventError, ProcessEventHooks, ProcessEventResult, processEventCore, resolveTransition, runSpawnEffects } from "./internal/transition.js";
|
|
6
|
-
import {
|
|
6
|
+
import { Lifecycle, Machine } from "./machine.js";
|
|
7
7
|
import { RuntimeQueuedEvent } from "./internal/runtime.js";
|
|
8
8
|
import { Deferred, Effect, Layer, Option, PubSub, Queue, Ref, Scope, ServiceMap, Stream, SubscriptionRef } from "effect";
|
|
9
9
|
|
|
@@ -54,6 +54,15 @@ interface ActorRef<State extends {
|
|
|
54
54
|
readonly state: SubscriptionRef.SubscriptionRef<State>;
|
|
55
55
|
/** Stop the actor gracefully. */
|
|
56
56
|
readonly stop: Effect.Effect<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Start the actor — fork event loop, background effects, spawn effects.
|
|
59
|
+
* Idempotent: first caller runs initialization, subsequent callers await completion.
|
|
60
|
+
* Events sent before start() are queued and processed when start() runs.
|
|
61
|
+
*
|
|
62
|
+
* Called automatically by `system.spawn`. For `Machine.spawn`, the caller
|
|
63
|
+
* must call `start` explicitly.
|
|
64
|
+
*/
|
|
65
|
+
readonly start: Effect.Effect<void>;
|
|
57
66
|
/** Get current state snapshot. */
|
|
58
67
|
readonly snapshot: Effect.Effect<State>;
|
|
59
68
|
/** Check if current state matches tag. */
|
|
@@ -161,7 +170,7 @@ interface ActorSystem {
|
|
|
161
170
|
}, R, SD extends SlotsDef = Record<string, never>>(id: string, machine: Machine<S, E, R, any, any, SD>, options?: {
|
|
162
171
|
readonly supervision?: Supervision.Policy;
|
|
163
172
|
readonly slots?: ProvideSlots<SD, any>;
|
|
164
|
-
readonly
|
|
173
|
+
readonly lifecycle?: Lifecycle<S, E>;
|
|
165
174
|
}) => Effect.Effect<ActorRef<S, E>, DuplicateActorError, R>;
|
|
166
175
|
/**
|
|
167
176
|
* Get an existing actor by ID
|
|
@@ -204,7 +213,7 @@ declare const buildActorRefCore: <S extends {
|
|
|
204
213
|
readonly _tag: string;
|
|
205
214
|
}, E extends {
|
|
206
215
|
readonly _tag: string;
|
|
207
|
-
}, R, SD extends SlotsDef>(id: string, machine: Machine<S, E, R, any, any, SD>, stateRef: SubscriptionRef.SubscriptionRef<S>, eventQueueRef: Ref.Ref<Queue.Queue<QueuedEvent<E>>>, stoppedRef: Ref.Ref<boolean>, listeners: Listeners<S>, stop: Effect.Effect<void>, system: ActorSystem, childrenMap: ReadonlyMap<string, ActorRef<AnyState, unknown>>, pendingReplies: Set<Deferred.Deferred<unknown, unknown>>, transitionsPubSub: PubSub.PubSub<TransitionInfo<S, E>> | undefined, exitDeferred: Deferred.Deferred<ActorExit<S>, never>) => ActorRef<S, E>;
|
|
216
|
+
}, R, SD extends SlotsDef>(id: string, machine: Machine<S, E, R, any, any, SD>, stateRef: SubscriptionRef.SubscriptionRef<S>, eventQueueRef: Ref.Ref<Queue.Queue<QueuedEvent<E>>>, stoppedRef: Ref.Ref<boolean>, listeners: Listeners<S>, stop: Effect.Effect<void>, start: Effect.Effect<void>, system: ActorSystem, childrenMap: ReadonlyMap<string, ActorRef<AnyState, unknown>>, pendingReplies: Set<Deferred.Deferred<unknown, unknown>>, transitionsPubSub: PubSub.PubSub<TransitionInfo<S, E>> | undefined, exitDeferred: Deferred.Deferred<ActorExit<S>, never>) => ActorRef<S, E>;
|
|
208
217
|
/**
|
|
209
218
|
* Create and start an actor for a machine.
|
|
210
219
|
* Delegates to the shared runtime kernel with actor-specific lifecycle hooks.
|
|
@@ -216,7 +225,7 @@ declare const createActor: <S extends {
|
|
|
216
225
|
}, R, SD extends SlotsDef>(id: string, machine: Machine<S, E, R, any, any, SD>, options?: {
|
|
217
226
|
initialState?: S;
|
|
218
227
|
supervision?: Supervision.Policy;
|
|
219
|
-
|
|
228
|
+
lifecycle?: Lifecycle<S, E>; /** @internal Called by system after each restart — emits ActorRestarted system event */
|
|
220
229
|
onRestart?: (generation: number, exit: ActorExit<unknown>) => Effect.Effect<void>;
|
|
221
230
|
} | undefined) => Effect.Effect<ActorRef<S, E>, never, never>;
|
|
222
231
|
/** Fail all pending call/ask Deferreds with ActorStoppedError. Safe to call multiple times. */
|
package/dist/actor.js
CHANGED
|
@@ -29,7 +29,7 @@ const notifyListeners = (listeners, state) => {
|
|
|
29
29
|
/**
|
|
30
30
|
* Build core ActorRef methods.
|
|
31
31
|
*/
|
|
32
|
-
const buildActorRefCore = (id, machine, stateRef, eventQueueRef, stoppedRef, listeners, stop, system, childrenMap, pendingReplies, transitionsPubSub, exitDeferred) => {
|
|
32
|
+
const buildActorRefCore = (id, machine, stateRef, eventQueueRef, stoppedRef, listeners, stop, start, system, childrenMap, pendingReplies, transitionsPubSub, exitDeferred) => {
|
|
33
33
|
const send = Effect.fn("effect-machine.actor.send")(function* (event) {
|
|
34
34
|
if (yield* Ref.get(stoppedRef)) return;
|
|
35
35
|
const q = yield* Ref.get(eventQueueRef);
|
|
@@ -116,6 +116,7 @@ const buildActorRefCore = (id, machine, stateRef, eventQueueRef, stoppedRef, lis
|
|
|
116
116
|
ask,
|
|
117
117
|
state: stateRef,
|
|
118
118
|
stop,
|
|
119
|
+
start,
|
|
119
120
|
snapshot,
|
|
120
121
|
matches,
|
|
121
122
|
can,
|
|
@@ -191,18 +192,6 @@ const buildInspectionHooks = (actorId, inspector) => ({
|
|
|
191
192
|
}))
|
|
192
193
|
});
|
|
193
194
|
/**
|
|
194
|
-
* Load persisted state and run onRestore hook if present.
|
|
195
|
-
* Returns the resolved initial state (loaded, restored, or fallback to machineInitial).
|
|
196
|
-
* @internal
|
|
197
|
-
*/
|
|
198
|
-
const loadAndRestore = (persist, machineInitial) => Effect.gen(function* () {
|
|
199
|
-
const loaded = yield* persist.load();
|
|
200
|
-
if (Option.isNone(loaded)) return machineInitial;
|
|
201
|
-
if (persist.onRestore === void 0) return loaded.value;
|
|
202
|
-
const restored = yield* persist.onRestore(loaded.value, { initial: machineInitial });
|
|
203
|
-
return Option.getOrElse(restored, () => machineInitial);
|
|
204
|
-
});
|
|
205
|
-
/**
|
|
206
195
|
* Resolve actor system from context, creating an implicit one if none exists.
|
|
207
196
|
* @internal
|
|
208
197
|
*/
|
|
@@ -225,7 +214,6 @@ const resolveActorSystem = Effect.fn("effect-machine.resolveActorSystem")(functi
|
|
|
225
214
|
*/
|
|
226
215
|
const runSupervisionLoop = (params) => Effect.gen(function* () {
|
|
227
216
|
const step = yield* Schedule.toStepWithSleep(params.supervision.schedule);
|
|
228
|
-
let generation = 0;
|
|
229
217
|
while (true) {
|
|
230
218
|
const currentRuntime = params.runtimeRef.current;
|
|
231
219
|
if (currentRuntime === void 0) return;
|
|
@@ -242,7 +230,17 @@ const runSupervisionLoop = (params) => Effect.gen(function* () {
|
|
|
242
230
|
yield* Deferred.succeed(params.terminalExitDeferred, generationExit);
|
|
243
231
|
return;
|
|
244
232
|
}
|
|
245
|
-
const
|
|
233
|
+
const nextGeneration = params.generationRef.get() + 1;
|
|
234
|
+
params.generationRef.set(nextGeneration);
|
|
235
|
+
let restartState = params.machine.initial;
|
|
236
|
+
if (params.lifecycle?.recovery !== void 0) {
|
|
237
|
+
const resolved = yield* params.lifecycle.recovery.resolve({
|
|
238
|
+
actorId: params.id,
|
|
239
|
+
generation: nextGeneration,
|
|
240
|
+
machineInitial: params.machine.initial
|
|
241
|
+
});
|
|
242
|
+
if (Option.isSome(resolved)) restartState = resolved.value;
|
|
243
|
+
}
|
|
246
244
|
yield* settlePendingReplies(params.pendingReplies, params.id);
|
|
247
245
|
const freshQueue = yield* Queue.unbounded();
|
|
248
246
|
yield* Ref.set(params.eventQueueRef, freshQueue);
|
|
@@ -255,8 +253,8 @@ const runSupervisionLoop = (params) => Effect.gen(function* () {
|
|
|
255
253
|
} }) : params.machine;
|
|
256
254
|
const newRuntime = yield* params.spawnGeneration(machineForRestart);
|
|
257
255
|
params.runtimeRef.current = newRuntime;
|
|
258
|
-
|
|
259
|
-
if (params.onRestart !== void 0) yield* params.onRestart(
|
|
256
|
+
yield* newRuntime.start;
|
|
257
|
+
if (params.onRestart !== void 0) yield* params.onRestart(nextGeneration, generationExit);
|
|
260
258
|
notifyListeners(params.listeners, restartState);
|
|
261
259
|
}
|
|
262
260
|
});
|
|
@@ -265,8 +263,8 @@ const runSupervisionLoop = (params) => Effect.gen(function* () {
|
|
|
265
263
|
* Delegates to the shared runtime kernel with actor-specific lifecycle hooks.
|
|
266
264
|
*/
|
|
267
265
|
const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine, options) {
|
|
268
|
-
const
|
|
269
|
-
const initial = options?.initialState ??
|
|
266
|
+
const lifecycle = options?.lifecycle;
|
|
267
|
+
const initial = options?.initialState ?? machine.initial;
|
|
270
268
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.id", id);
|
|
271
269
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state", initial._tag);
|
|
272
270
|
const { system, implicitSystemScope } = yield* resolveActorSystem();
|
|
@@ -275,12 +273,6 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
275
273
|
const pendingReplies = /* @__PURE__ */ new Set();
|
|
276
274
|
const listeners = /* @__PURE__ */ new Set();
|
|
277
275
|
const transitionsPubSub = yield* PubSub.unbounded();
|
|
278
|
-
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
279
|
-
type: "@machine.spawn",
|
|
280
|
-
actorId: id,
|
|
281
|
-
initialState: initial,
|
|
282
|
-
timestamp
|
|
283
|
-
}));
|
|
284
276
|
const hooks = inspectorValue !== void 0 ? buildInspectionHooks(id, inspectorValue) : void 0;
|
|
285
277
|
const machineWithState = initial !== machine.initial ? Object.create(machine, { initial: {
|
|
286
278
|
value: initial,
|
|
@@ -292,9 +284,11 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
292
284
|
const eventQueueRef = yield* Ref.make(initialQueue);
|
|
293
285
|
const terminalExitDeferred = yield* Deferred.make();
|
|
294
286
|
let stopEmitted = false;
|
|
287
|
+
let generation = 0;
|
|
295
288
|
const runtimeRef = { current: void 0 };
|
|
289
|
+
const supervisorFiberRef = { current: void 0 };
|
|
296
290
|
/** Build lifecycle hooks for a generation */
|
|
297
|
-
const
|
|
291
|
+
const buildRuntimeLifecycle = () => {
|
|
298
292
|
stopEmitted = false;
|
|
299
293
|
return {
|
|
300
294
|
onEvent: inspectorValue !== void 0 ? (state, event) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
@@ -304,10 +298,17 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
304
298
|
event,
|
|
305
299
|
timestamp
|
|
306
300
|
})) : void 0,
|
|
307
|
-
onStateChange: (result,
|
|
301
|
+
onStateChange: (result, event) => Effect.gen(function* () {
|
|
308
302
|
notifyListeners(listeners, result.newState);
|
|
309
|
-
if (
|
|
310
|
-
|
|
303
|
+
if (lifecycle?.durability !== void 0 && result.transitioned) {
|
|
304
|
+
const durability = lifecycle.durability;
|
|
305
|
+
if (durability.shouldSave === void 0 || durability.shouldSave(result.newState, result.previousState)) yield* durability.save({
|
|
306
|
+
actorId: id,
|
|
307
|
+
generation,
|
|
308
|
+
previousState: result.previousState,
|
|
309
|
+
nextState: result.newState,
|
|
310
|
+
event
|
|
311
|
+
});
|
|
311
312
|
}
|
|
312
313
|
yield* Effect.annotateCurrentSpan("effect_machine.transition.matched", true);
|
|
313
314
|
if (result.lifecycleRan) {
|
|
@@ -360,7 +361,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
360
361
|
stoppedRef,
|
|
361
362
|
eventQueue: currentQueue
|
|
362
363
|
},
|
|
363
|
-
lifecycle:
|
|
364
|
+
lifecycle: buildRuntimeLifecycle(),
|
|
364
365
|
wrapProcess: (state, event, inner) => Effect.withSpan("effect-machine.event.process", { attributes: {
|
|
365
366
|
"effect_machine.actor.id": id,
|
|
366
367
|
"effect_machine.state.current": state._tag,
|
|
@@ -374,34 +375,67 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
374
375
|
}));
|
|
375
376
|
})
|
|
376
377
|
})));
|
|
377
|
-
|
|
378
|
-
runtimeRef.current = runtime;
|
|
378
|
+
runtimeRef.current = yield* spawnGeneration(machineWithState);
|
|
379
379
|
const supervision = options?.supervision;
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
supervision,
|
|
383
|
-
machine,
|
|
384
|
-
id,
|
|
385
|
-
runtimeRef,
|
|
386
|
-
terminalExitDeferred,
|
|
387
|
-
pendingReplies,
|
|
388
|
-
eventQueueRef,
|
|
389
|
-
stateRef,
|
|
390
|
-
stoppedRef,
|
|
391
|
-
childrenMap,
|
|
392
|
-
listeners,
|
|
393
|
-
spawnGeneration,
|
|
394
|
-
persist,
|
|
395
|
-
onRestart: options?.onRestart
|
|
396
|
-
}));
|
|
397
|
-
else yield* Effect.forkDetach(Deferred.await(runtime.exitDeferred).pipe(Effect.tap((exit) => Deferred.succeed(terminalExitDeferred, exit))));
|
|
398
|
-
return buildActorRefCore(id, machine, stateRef, eventQueueRef, stoppedRef, listeners, Effect.gen(function* () {
|
|
399
|
-
if (supervisorFiber !== void 0) yield* Fiber.interrupt(supervisorFiber);
|
|
380
|
+
const stop = Effect.gen(function* () {
|
|
381
|
+
if (supervisorFiberRef.current !== void 0) yield* Fiber.interrupt(supervisorFiberRef.current);
|
|
400
382
|
const currentRuntime = runtimeRef.current;
|
|
401
383
|
if (currentRuntime !== void 0) yield* currentRuntime.stop;
|
|
402
384
|
yield* Deferred.succeed(terminalExitDeferred, { _tag: "Stopped" });
|
|
403
385
|
if (implicitSystemScope !== void 0) yield* Scope.close(implicitSystemScope, Exit.void);
|
|
404
|
-
}).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid)
|
|
386
|
+
}).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid);
|
|
387
|
+
const isHydrated = options?.initialState !== void 0;
|
|
388
|
+
return buildActorRefCore(id, machine, stateRef, eventQueueRef, stoppedRef, listeners, stop, Effect.gen(function* () {
|
|
389
|
+
if (lifecycle?.recovery !== void 0 && !isHydrated) {
|
|
390
|
+
const resolved = yield* lifecycle.recovery.resolve({
|
|
391
|
+
actorId: id,
|
|
392
|
+
generation,
|
|
393
|
+
machineInitial: machine.initial
|
|
394
|
+
});
|
|
395
|
+
if (Option.isSome(resolved)) {
|
|
396
|
+
yield* SubscriptionRef.set(stateRef, resolved.value);
|
|
397
|
+
runtimeRef.current = yield* spawnGeneration(Object.create(machine, { initial: {
|
|
398
|
+
value: resolved.value,
|
|
399
|
+
enumerable: true
|
|
400
|
+
} }));
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const currentState = yield* SubscriptionRef.get(stateRef);
|
|
404
|
+
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
405
|
+
type: "@machine.spawn",
|
|
406
|
+
actorId: id,
|
|
407
|
+
initialState: currentState,
|
|
408
|
+
timestamp
|
|
409
|
+
}));
|
|
410
|
+
if (supervision !== void 0) supervisorFiberRef.current = yield* Effect.forkDetach(runSupervisionLoop({
|
|
411
|
+
supervision,
|
|
412
|
+
machine,
|
|
413
|
+
id,
|
|
414
|
+
runtimeRef,
|
|
415
|
+
terminalExitDeferred,
|
|
416
|
+
pendingReplies,
|
|
417
|
+
eventQueueRef,
|
|
418
|
+
stateRef,
|
|
419
|
+
stoppedRef,
|
|
420
|
+
childrenMap,
|
|
421
|
+
listeners,
|
|
422
|
+
spawnGeneration,
|
|
423
|
+
lifecycle,
|
|
424
|
+
generationRef: {
|
|
425
|
+
get: () => generation,
|
|
426
|
+
set: (g) => {
|
|
427
|
+
generation = g;
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
onRestart: options?.onRestart
|
|
431
|
+
}));
|
|
432
|
+
else {
|
|
433
|
+
const currentRuntime = runtimeRef.current;
|
|
434
|
+
if (currentRuntime !== void 0) yield* Effect.forkDetach(Deferred.await(currentRuntime.exitDeferred).pipe(Effect.tap((exit) => Deferred.succeed(terminalExitDeferred, exit))));
|
|
435
|
+
}
|
|
436
|
+
const currentRuntime = runtimeRef.current;
|
|
437
|
+
if (currentRuntime !== void 0) yield* currentRuntime.start;
|
|
438
|
+
}).pipe(Effect.withSpan("effect-machine.actor.start"), Effect.asVoid), system, childrenMap, pendingReplies, transitionsPubSub, terminalExitDeferred);
|
|
405
439
|
});
|
|
406
440
|
/** Fail all pending call/ask Deferreds with ActorStoppedError. Safe to call multiple times. */
|
|
407
441
|
const settlePendingReplies = (pendingReplies, actorId) => Effect.sync(() => {
|
|
@@ -462,7 +496,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
462
496
|
let actorRef;
|
|
463
497
|
const actor = yield* createActor(id, materialized, {
|
|
464
498
|
supervision: spawnOptions?.supervision,
|
|
465
|
-
|
|
499
|
+
lifecycle: spawnOptions?.lifecycle,
|
|
466
500
|
onRestart: spawnOptions?.supervision !== void 0 ? (generation, exit) => actorRef !== void 0 ? emitSystemEvent({
|
|
467
501
|
_tag: "ActorRestarted",
|
|
468
502
|
id,
|
|
@@ -472,7 +506,9 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
472
506
|
}) : Effect.void : void 0
|
|
473
507
|
});
|
|
474
508
|
actorRef = actor;
|
|
475
|
-
|
|
509
|
+
yield* registerActor(id, actor);
|
|
510
|
+
yield* actor.start.pipe(Effect.catchCause((cause) => actor.stop.pipe(Effect.andThen(Effect.failCause(cause)))));
|
|
511
|
+
return actor;
|
|
476
512
|
});
|
|
477
513
|
const spawn = (id, machine, options) => withSpawnGate(spawnRegular(id, machine, options));
|
|
478
514
|
const get = Effect.fn("effect-machine.actorSystem.get")(function* (id) {
|
package/dist/index.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaEr
|
|
|
4
4
|
import { HasSlotKeys, MachineContext, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema } from "./slot.js";
|
|
5
5
|
import { ActorExit, CellPhase, DefectPhase, Supervision } from "./supervision.js";
|
|
6
6
|
import { ProcessEventResult } from "./internal/transition.js";
|
|
7
|
-
import { BackgroundEffect, HandlerContext, Machine, MachineRef, MakeConfig, SpawnEffect, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, machine_d_exports } from "./machine.js";
|
|
7
|
+
import { BackgroundEffect, Durability, DurabilityCommit, HandlerContext, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, SpawnEffect, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, machine_d_exports } from "./machine.js";
|
|
8
8
|
import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
|
|
9
9
|
import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
10
10
|
import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
11
|
-
export { ActorExit, type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type CellPhase, type DefectPhase, type DeferReplyResult, DuplicateActorError, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type HandlerContext, type HasSlotKeys, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, type ProcessEventResult, type ProvideSlots, ProvisionValidationError, type ReplyFields, type ReplyResult, type SimulationResult, Slot, type SlotCall, type SlotCalls, SlotCodecError, type SlotFnDef, type SlotHandler, type SlotInvocation, SlotProvisionError, type SlotRequest, type SlotResult, type SlotsDef, type SlotsSchema, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, Supervision, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TimeoutConfig, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
|
11
|
+
export { ActorExit, type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type CellPhase, type DefectPhase, type DeferReplyResult, DuplicateActorError, type Durability, type DurabilityCommit, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type HandlerContext, type HasSlotKeys, type InspectionEvent, type Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, type Lifecycle, machine_d_exports as Machine, type MachineContext, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, type ProcessEventResult, type ProvideSlots, ProvisionValidationError, type Recovery, type RecoveryContext, type ReplyFields, type ReplyResult, type SimulationResult, Slot, type SlotCall, type SlotCalls, SlotCodecError, type SlotFnDef, type SlotHandler, type SlotInvocation, SlotProvisionError, type SlotRequest, type SlotResult, type SlotsDef, type SlotsSchema, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, Supervision, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TimeoutConfig, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
|
@@ -55,6 +55,12 @@ interface RuntimeHandle<S, E> {
|
|
|
55
55
|
readonly isStopped: Effect.Effect<boolean>;
|
|
56
56
|
/** Stop the runtime (interrupt event loop, clean up) */
|
|
57
57
|
readonly stop: Effect.Effect<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Start the runtime — fork event loop, background effects, spawn effects.
|
|
60
|
+
* Idempotent: first caller runs initialization, subsequent callers await completion.
|
|
61
|
+
* Events sent before start() are queued and processed when start() runs.
|
|
62
|
+
*/
|
|
63
|
+
readonly start: Effect.Effect<void>;
|
|
58
64
|
/** @internal — raw event queue for direct enqueue (actor.ts uses this for pendingReplies tracking) */
|
|
59
65
|
readonly _queue: Queue.Queue<RuntimeQueuedEvent<E>>;
|
|
60
66
|
/** @internal — stopped ref for direct access */
|
|
@@ -137,6 +143,19 @@ declare const createRuntime: <S extends {
|
|
|
137
143
|
readonly _tag: string;
|
|
138
144
|
}, E extends {
|
|
139
145
|
readonly _tag: string;
|
|
140
|
-
}, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, system: ActorSystem, config: RuntimeConfig<S, E>) => Effect.Effect<
|
|
146
|
+
}, R, SD extends SlotsDef>(machine: Machine<S, E, R, any, any, SD>, system: ActorSystem, config: RuntimeConfig<S, E>) => Effect.Effect<{
|
|
147
|
+
stop: Effect.Effect<void, never, never>;
|
|
148
|
+
start: Effect.Effect<void, unknown, Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
|
|
149
|
+
send: (event: E) => Effect.Effect<void>;
|
|
150
|
+
sendWait: (event: E) => Effect.Effect<void, unknown>;
|
|
151
|
+
ask: (event: E) => Effect.Effect<unknown, NoReplyError>;
|
|
152
|
+
getState: Effect.Effect<S, never, never>;
|
|
153
|
+
stateRef: SubscriptionRef.SubscriptionRef<S>;
|
|
154
|
+
isStopped: Effect.Effect<boolean>;
|
|
155
|
+
_queue: Queue.Queue<RuntimeQueuedEvent<E>, never>;
|
|
156
|
+
_stoppedRef: Ref.Ref<boolean>;
|
|
157
|
+
exitDeferred: Deferred.Deferred<ActorExit<S>, never>;
|
|
158
|
+
actorScope: Scope.Closeable;
|
|
159
|
+
}, never, Scope.Scope>;
|
|
141
160
|
//#endregion
|
|
142
161
|
export { ProcessQueuedResult, RuntimeCellResources, RuntimeConfig, RuntimeHandle, RuntimeLifecycleHooks, RuntimeQueuedEvent, createRuntime };
|
package/dist/internal/runtime.js
CHANGED
|
@@ -72,7 +72,6 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
72
72
|
})
|
|
73
73
|
};
|
|
74
74
|
const stateScopeRef = { current: yield* Scope.make() };
|
|
75
|
-
const backgroundFibers = [];
|
|
76
75
|
const initEvent = { _tag: INTERNAL_INIT_EVENT };
|
|
77
76
|
const ctx = {
|
|
78
77
|
actorId,
|
|
@@ -82,59 +81,71 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
82
81
|
system
|
|
83
82
|
};
|
|
84
83
|
const slots = machine._slots;
|
|
85
|
-
for (const bg of machine.backgroundEffects) {
|
|
86
|
-
const fiber = yield* bg.handler({
|
|
87
|
-
actorId,
|
|
88
|
-
state: machine.initial,
|
|
89
|
-
event: initEvent,
|
|
90
|
-
self,
|
|
91
|
-
slots,
|
|
92
|
-
system
|
|
93
|
-
}).pipe(Effect.provideService(machine.Context, ctx), Effect.forkIn(actorScope));
|
|
94
|
-
backgroundFibers.push(fiber);
|
|
95
|
-
}
|
|
96
|
-
if (lifecycle?.onInitialSpawnEffects !== void 0) yield* lifecycle.onInitialSpawnEffects(machine.initial);
|
|
97
84
|
const loopFiberRef = { current: void 0 };
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
/** Set the exit deferred exactly once. */
|
|
86
|
+
const setExit = (exit) => Deferred.succeed(exitDeferred, exit).pipe(Effect.asVoid);
|
|
87
|
+
const startDeferred = yield* Deferred.make();
|
|
88
|
+
const startedRef = yield* Ref.make(false);
|
|
89
|
+
const start = Effect.gen(function* () {
|
|
90
|
+
if (yield* Ref.getAndSet(startedRef, true)) {
|
|
91
|
+
yield* Deferred.await(startDeferred);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const backgroundFibers = [];
|
|
95
|
+
for (const bg of machine.backgroundEffects) {
|
|
96
|
+
const fiber = yield* bg.handler({
|
|
97
|
+
actorId,
|
|
98
|
+
state: machine.initial,
|
|
99
|
+
event: initEvent,
|
|
100
|
+
self,
|
|
101
|
+
slots,
|
|
102
|
+
system
|
|
103
|
+
}).pipe(Effect.provideService(machine.Context, ctx), Effect.forkIn(actorScope));
|
|
104
|
+
backgroundFibers.push(fiber);
|
|
105
|
+
}
|
|
106
|
+
if (lifecycle?.onInitialSpawnEffects !== void 0) yield* lifecycle.onInitialSpawnEffects(machine.initial);
|
|
107
|
+
const initialSpawnDefectSignal = (cause) => Deferred.succeed(exitDeferred, ActorExit.Defect(cause, "initial-spawn")).pipe(Effect.andThen(Ref.set(stoppedRef, true)), Effect.andThen(Effect.suspend(() => loopFiberRef.current !== void 0 ? Fiber.interrupt(loopFiberRef.current) : Effect.void)), Effect.asVoid);
|
|
108
|
+
yield* runSpawnEffects(machine, machine.initial, initEvent, self, stateScopeRef.current, system, actorId, hooks?.onError, initialSpawnDefectSignal).pipe(Effect.catchCause((cause) => {
|
|
109
|
+
return Effect.gen(function* () {
|
|
110
|
+
yield* Ref.set(stoppedRef, true);
|
|
111
|
+
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
112
|
+
yield* Scope.close(actorScope, Exit.void);
|
|
113
|
+
yield* Deferred.succeed(exitDeferred, ActorExit.Defect(cause, "initial-spawn"));
|
|
114
|
+
return yield* Effect.failCause(cause);
|
|
115
|
+
});
|
|
116
|
+
}));
|
|
117
|
+
if (machine.finalStates.has(machine.initial._tag)) {
|
|
118
|
+
if (lifecycle?.onFinal !== void 0) yield* lifecycle.onFinal(machine.initial);
|
|
101
119
|
yield* Ref.set(stoppedRef, true);
|
|
102
120
|
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
103
121
|
yield* Scope.close(actorScope, Exit.void);
|
|
104
|
-
yield*
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
yield*
|
|
113
|
-
|
|
114
|
-
yield*
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (exit._tag === "Failure" && !Cause.hasInterruptsOnly(exit.cause)) return setExit(ActorExit.Defect(exit.cause, "background")).pipe(Effect.andThen(Ref.set(stoppedRef, true)), Effect.andThen(Fiber.interrupt(loopFiber)));
|
|
126
|
-
return Effect.never;
|
|
127
|
-
})))).pipe(Effect.forkIn(actorScope));
|
|
128
|
-
yield* Effect.forkDetach(Effect.gen(function* () {
|
|
129
|
-
const loopExit = yield* Fiber.await(loopFiber);
|
|
130
|
-
if (loopExit._tag === "Success") yield* Scope.close(actorScope, Exit.void);
|
|
131
|
-
else yield* Scope.close(actorScope, loopExit);
|
|
132
|
-
}));
|
|
122
|
+
yield* setExit(ActorExit.Final(machine.initial));
|
|
123
|
+
yield* Deferred.succeed(startDeferred, void 0);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const augmentedHooks = {
|
|
127
|
+
...hooks,
|
|
128
|
+
onSpawnDefect: (cause) => Deferred.succeed(exitDeferred, ActorExit.Defect(cause, "spawn")).pipe(Effect.andThen(Ref.set(stoppedRef, true)), Effect.andThen(Effect.suspend(() => loopFiberRef.current !== void 0 ? Fiber.interrupt(loopFiberRef.current) : Effect.void)), Effect.asVoid)
|
|
129
|
+
};
|
|
130
|
+
const loopFiber = yield* Effect.forkDetach(runtimeEventLoop(machine, stateRef, eventQueue, stoppedRef, self, stateScopeRef, actorId, system, exitDeferred, augmentedHooks, deferredReplyRef, lifecycle, config.wrapProcess, fork));
|
|
131
|
+
loopFiberRef.current = loopFiber;
|
|
132
|
+
if (backgroundFibers.length > 0) yield* Effect.raceAll(backgroundFibers.map((fiber) => Fiber.await(fiber).pipe(Effect.flatMap((exit) => {
|
|
133
|
+
if (exit._tag === "Failure" && !Cause.hasInterruptsOnly(exit.cause)) return setExit(ActorExit.Defect(exit.cause, "background")).pipe(Effect.andThen(Ref.set(stoppedRef, true)), Effect.andThen(Fiber.interrupt(loopFiber)));
|
|
134
|
+
return Effect.never;
|
|
135
|
+
})))).pipe(Effect.forkIn(actorScope));
|
|
136
|
+
yield* Effect.forkDetach(Effect.gen(function* () {
|
|
137
|
+
const loopExit = yield* Fiber.await(loopFiber);
|
|
138
|
+
if (loopExit._tag === "Success") yield* Scope.close(actorScope, Exit.void);
|
|
139
|
+
else yield* Scope.close(actorScope, loopExit);
|
|
140
|
+
}));
|
|
141
|
+
yield* Deferred.succeed(startDeferred, void 0);
|
|
142
|
+
}).pipe(Effect.catchCause((cause) => Deferred.failCause(startDeferred, cause).pipe(Effect.andThen(Effect.failCause(cause)))));
|
|
133
143
|
const stop = Effect.gen(function* () {
|
|
134
144
|
if (yield* Ref.get(stoppedRef)) return;
|
|
135
145
|
if (lifecycle?.onShutdown !== void 0) yield* lifecycle.onShutdown();
|
|
136
146
|
yield* Ref.set(stoppedRef, true);
|
|
137
|
-
|
|
147
|
+
const loopFiber = loopFiberRef.current;
|
|
148
|
+
if (loopFiber !== void 0) yield* Fiber.interrupt(loopFiber);
|
|
138
149
|
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
139
150
|
yield* Scope.close(actorScope, Exit.void);
|
|
140
151
|
yield* setExit(ActorExit.Stopped);
|
|
@@ -142,7 +153,8 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
142
153
|
if (config.skipFinalizer !== true) yield* Effect.addFinalizer(() => stop);
|
|
143
154
|
return {
|
|
144
155
|
...makeHandle(stateRef, stoppedRef, eventQueue, exitDeferred, actorScope),
|
|
145
|
-
stop
|
|
156
|
+
stop,
|
|
157
|
+
start
|
|
146
158
|
};
|
|
147
159
|
});
|
|
148
160
|
/**
|
|
@@ -184,6 +196,7 @@ const makeHandle = (stateRef, stoppedRef, eventQueue, exitDeferred, actorScope)
|
|
|
184
196
|
stateRef,
|
|
185
197
|
isStopped: Ref.get(stoppedRef),
|
|
186
198
|
stop: Effect.void,
|
|
199
|
+
start: Effect.void,
|
|
187
200
|
_queue: eventQueue,
|
|
188
201
|
_stoppedRef: stoppedRef,
|
|
189
202
|
exitDeferred,
|
package/dist/machine.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { Cause, Duration, Effect, Option, Schema, Scope, ServiceMap } from "effe
|
|
|
10
10
|
|
|
11
11
|
//#region src/machine.d.ts
|
|
12
12
|
declare namespace machine_d_exports {
|
|
13
|
-
export { BackgroundEffect, DeferReplyResult, HandlerContext, Machine, MachineRef, MakeConfig,
|
|
13
|
+
export { BackgroundEffect, DeferReplyResult, Durability, DurabilityCommit, HandlerContext, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, ReplyResult, SpawnEffect, StateEffectHandler, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, TransitionHandler, deferReply, findTransitions, make, materializeMachine, replay, reply, spawn };
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Self reference for sending events back to the machine
|
|
@@ -88,32 +88,39 @@ interface TaskOptions<State, Event, SD extends SlotsDef, A, E1, ES, EF> {
|
|
|
88
88
|
readonly name?: string;
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
|
-
*
|
|
91
|
+
* Recovery resolves the initial state for a generation. Runs during actor.start.
|
|
92
92
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
93
|
+
* For initial start (generation 0): loads persisted state.
|
|
94
|
+
* For supervision restart (generation 1+): reloads state after crash.
|
|
95
95
|
*/
|
|
96
|
-
interface
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
readonly
|
|
101
|
-
|
|
96
|
+
interface Recovery<S> {
|
|
97
|
+
readonly resolve: (ctx: RecoveryContext<S>) => Effect.Effect<Option.Option<S>>;
|
|
98
|
+
}
|
|
99
|
+
interface RecoveryContext<S> {
|
|
100
|
+
readonly actorId: string;
|
|
101
|
+
readonly generation: number;
|
|
102
|
+
readonly machineInitial: S;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Durability saves state after committed transitions. Runs during runtime.
|
|
106
|
+
*/
|
|
107
|
+
interface Durability<S, E> {
|
|
108
|
+
readonly save: (commit: DurabilityCommit<S, E>) => Effect.Effect<void>;
|
|
102
109
|
readonly shouldSave?: (state: S, previousState: S) => boolean;
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
110
|
+
}
|
|
111
|
+
interface DurabilityCommit<S, E> {
|
|
112
|
+
readonly actorId: string;
|
|
113
|
+
readonly generation: number;
|
|
114
|
+
readonly previousState: S;
|
|
115
|
+
readonly nextState: S;
|
|
116
|
+
readonly event: E;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Actor lifecycle configuration.
|
|
120
|
+
*/
|
|
121
|
+
interface Lifecycle<S, E> {
|
|
122
|
+
readonly recovery?: Recovery<S>;
|
|
123
|
+
readonly durability?: Durability<S, E>;
|
|
117
124
|
}
|
|
118
125
|
/**
|
|
119
126
|
* Configuration for `.timeout()` — gen_statem-style state timeouts.
|
|
@@ -335,11 +342,11 @@ declare const make: typeof Machine.make;
|
|
|
335
342
|
* slots: { canRetry: ({ max }) => attempts < max },
|
|
336
343
|
* });
|
|
337
344
|
*
|
|
338
|
-
* // With
|
|
345
|
+
* // With lifecycle (recovery + durability)
|
|
339
346
|
* const actor = yield* Machine.spawn(machine, {
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
* save: (
|
|
347
|
+
* lifecycle: {
|
|
348
|
+
* recovery: { resolve: (ctx) => storage.get("actor-state") },
|
|
349
|
+
* durability: { save: (commit) => storage.set("actor-state", commit.nextState) },
|
|
343
350
|
* },
|
|
344
351
|
* });
|
|
345
352
|
* ```
|
|
@@ -353,7 +360,7 @@ declare const spawn: <S extends {
|
|
|
353
360
|
hydrate?: S;
|
|
354
361
|
slots?: ProvideSlots<SD, any>;
|
|
355
362
|
supervision?: Supervision.Policy;
|
|
356
|
-
|
|
363
|
+
lifecycle?: Lifecycle<S, E>;
|
|
357
364
|
}) => Effect.Effect<ActorRef<S, E>, never, R>;
|
|
358
365
|
declare const replay: {
|
|
359
366
|
<S extends {
|
|
@@ -368,4 +375,4 @@ declare const replay: {
|
|
|
368
375
|
declare const reply: <State, Reply>(state: State, reply: Reply) => ReplyResult<State, Reply>;
|
|
369
376
|
declare const deferReply: <State>(state: State) => DeferReplyResult<State>;
|
|
370
377
|
//#endregion
|
|
371
|
-
export { BackgroundEffect, type DeferReplyResult, HandlerContext, Machine, MachineRef, MakeConfig,
|
|
378
|
+
export { BackgroundEffect, type DeferReplyResult, Durability, DurabilityCommit, HandlerContext, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, type ReplyResult, SpawnEffect, StateEffectHandler, StateHandlerContext, TaskOptions, TimeoutConfig, Transition, TransitionHandler, deferReply, findTransitions, machine_d_exports, make, materializeMachine, replay, reply, spawn };
|