effect-machine 0.9.0 → 0.11.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/README.md +118 -55
- package/dist/actor.d.ts +77 -179
- package/dist/actor.js +161 -113
- package/dist/cluster/entity-machine.js +5 -3
- package/dist/errors.d.ts +12 -1
- package/dist/errors.js +8 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.js +2 -7
- package/dist/internal/transition.d.ts +27 -3
- package/dist/internal/transition.js +38 -9
- package/dist/internal/utils.d.ts +7 -2
- package/dist/internal/utils.js +1 -5
- package/dist/machine.d.ts +94 -35
- package/dist/machine.js +128 -13
- package/dist/testing.js +57 -3
- package/package.json +10 -9
- package/v3/dist/actor.d.ts +210 -0
- package/{dist-v3 → v3/dist}/actor.js +198 -117
- package/{dist-v3 → v3/dist}/cluster/entity-machine.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/entity-machine.js +8 -6
- package/{dist-v3 → v3/dist}/cluster/to-entity.d.ts +1 -1
- package/{dist-v3 → v3/dist}/cluster/to-entity.js +1 -1
- package/v3/dist/errors.d.ts +76 -0
- package/{dist-v3 → v3/dist}/errors.js +9 -2
- package/v3/dist/index.d.ts +9 -0
- package/v3/dist/index.js +8 -0
- package/{dist-v3 → v3/dist}/inspection.d.ts +53 -8
- package/v3/dist/inspection.js +156 -0
- package/{dist-v3 → v3/dist}/internal/brands.d.ts +1 -1
- package/{dist-v3 → v3/dist}/internal/inspection.d.ts +1 -1
- package/v3/dist/internal/inspection.js +20 -0
- package/{dist-v3 → v3/dist}/internal/transition.d.ts +35 -11
- package/{dist-v3 → v3/dist}/internal/transition.js +47 -15
- package/{dist-v3 → v3/dist}/internal/utils.d.ts +9 -4
- package/{dist-v3 → v3/dist}/internal/utils.js +2 -6
- package/{dist-v3 → v3/dist}/machine.d.ts +113 -40
- package/{dist-v3 → v3/dist}/machine.js +191 -15
- package/{dist-v3 → v3/dist}/schema.d.ts +1 -1
- package/{dist-v3 → v3/dist}/schema.js +5 -2
- package/{dist-v3 → v3/dist}/slot.d.ts +4 -3
- package/{dist-v3 → v3/dist}/slot.js +1 -1
- package/{dist-v3 → v3/dist}/testing.d.ts +14 -8
- package/{dist-v3 → v3/dist}/testing.js +60 -6
- package/dist/persistence/adapter.d.ts +0 -135
- package/dist/persistence/adapter.js +0 -25
- package/dist/persistence/adapters/in-memory.d.ts +0 -32
- package/dist/persistence/adapters/in-memory.js +0 -174
- package/dist/persistence/index.d.ts +0 -5
- package/dist/persistence/index.js +0 -5
- package/dist/persistence/persistent-actor.d.ts +0 -50
- package/dist/persistence/persistent-actor.js +0 -368
- package/dist/persistence/persistent-machine.d.ts +0 -105
- package/dist/persistence/persistent-machine.js +0 -22
- package/dist-v3/actor.d.ts +0 -291
- package/dist-v3/errors.d.ts +0 -27
- package/dist-v3/index.d.ts +0 -12
- package/dist-v3/index.js +0 -13
- package/dist-v3/inspection.js +0 -48
- package/dist-v3/internal/inspection.js +0 -13
- package/dist-v3/persistence/adapter.d.ts +0 -125
- package/dist-v3/persistence/adapter.js +0 -25
- package/dist-v3/persistence/adapters/in-memory.d.ts +0 -32
- package/dist-v3/persistence/adapters/in-memory.js +0 -174
- package/dist-v3/persistence/index.d.ts +0 -5
- package/dist-v3/persistence/index.js +0 -5
- package/dist-v3/persistence/persistent-actor.d.ts +0 -49
- package/dist-v3/persistence/persistent-actor.js +0 -365
- package/dist-v3/persistence/persistent-machine.d.ts +0 -105
- package/dist-v3/persistence/persistent-machine.js +0 -22
- /package/{dist-v3 → v3/dist}/_virtual/_rolldown/runtime.js +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.d.ts +0 -0
- /package/{dist-v3 → v3/dist}/cluster/index.js +0 -0
- /package/{dist-v3 → v3/dist}/internal/brands.js +0 -0
package/dist/actor.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { Inspector } from "./inspection.js";
|
|
2
2
|
import { INTERNAL_INIT_EVENT } from "./internal/utils.js";
|
|
3
|
-
import { DuplicateActorError } from "./errors.js";
|
|
4
|
-
import { isPersistentMachine } from "./persistence/persistent-machine.js";
|
|
3
|
+
import { ActorStoppedError, DuplicateActorError, NoReplyError } from "./errors.js";
|
|
5
4
|
import { emitWithTimestamp } from "./internal/inspection.js";
|
|
6
|
-
import { processEventCore, resolveTransition, runSpawnEffects } from "./internal/transition.js";
|
|
7
|
-
import { PersistenceAdapterTag, PersistenceError } from "./persistence/adapter.js";
|
|
8
|
-
import { createPersistentActor, restorePersistentActor } from "./persistence/persistent-actor.js";
|
|
5
|
+
import { processEventCore, resolveTransition, runSpawnEffects, shouldPostpone } from "./internal/transition.js";
|
|
9
6
|
import { Cause, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, Option, PubSub, Queue, Ref, Scope, Semaphore, ServiceMap, Stream, SubscriptionRef } from "effect";
|
|
10
7
|
//#region src/actor.ts
|
|
11
8
|
/**
|
|
@@ -29,14 +26,17 @@ const notifyListeners = (listeners, state) => {
|
|
|
29
26
|
} catch {}
|
|
30
27
|
};
|
|
31
28
|
/**
|
|
32
|
-
* Build core ActorRef methods
|
|
29
|
+
* Build core ActorRef methods.
|
|
33
30
|
*/
|
|
34
|
-
const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listeners, stop, system, childrenMap) => {
|
|
31
|
+
const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listeners, stop, system, childrenMap, pendingReplies, transitionsPubSub) => {
|
|
35
32
|
const send = Effect.fn("effect-machine.actor.send")(function* (event) {
|
|
36
33
|
if (yield* Ref.get(stoppedRef)) return;
|
|
37
|
-
yield* Queue.offer(eventQueue, {
|
|
34
|
+
yield* Queue.offer(eventQueue, {
|
|
35
|
+
_tag: "send",
|
|
36
|
+
event
|
|
37
|
+
});
|
|
38
38
|
});
|
|
39
|
-
const
|
|
39
|
+
const call = Effect.fn("effect-machine.actor.call")(function* (event) {
|
|
40
40
|
if (yield* Ref.get(stoppedRef)) {
|
|
41
41
|
const currentState = yield* SubscriptionRef.get(stateRef);
|
|
42
42
|
return {
|
|
@@ -48,11 +48,30 @@ const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listen
|
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
const reply = yield* Deferred.make();
|
|
51
|
+
pendingReplies.add(reply);
|
|
51
52
|
yield* Queue.offer(eventQueue, {
|
|
53
|
+
_tag: "call",
|
|
52
54
|
event,
|
|
53
55
|
reply
|
|
54
56
|
});
|
|
55
|
-
return yield* Deferred.await(reply)
|
|
57
|
+
return yield* Deferred.await(reply).pipe(Effect.ensuring(Effect.sync(() => pendingReplies.delete(reply))), Effect.catchTag("ActorStoppedError", () => SubscriptionRef.get(stateRef).pipe(Effect.map((currentState) => ({
|
|
58
|
+
newState: currentState,
|
|
59
|
+
previousState: currentState,
|
|
60
|
+
transitioned: false,
|
|
61
|
+
lifecycleRan: false,
|
|
62
|
+
isFinal: machine.finalStates.has(currentState._tag)
|
|
63
|
+
})))));
|
|
64
|
+
});
|
|
65
|
+
const ask = Effect.fn("effect-machine.actor.ask")(function* (event) {
|
|
66
|
+
if (yield* Ref.get(stoppedRef)) return yield* new ActorStoppedError({ actorId: id });
|
|
67
|
+
const reply = yield* Deferred.make();
|
|
68
|
+
pendingReplies.add(reply);
|
|
69
|
+
yield* Queue.offer(eventQueue, {
|
|
70
|
+
_tag: "ask",
|
|
71
|
+
event,
|
|
72
|
+
reply
|
|
73
|
+
});
|
|
74
|
+
return yield* Deferred.await(reply).pipe(Effect.ensuring(Effect.sync(() => pendingReplies.delete(reply))));
|
|
56
75
|
});
|
|
57
76
|
const snapshot = SubscriptionRef.get(stateRef).pipe(Effect.withSpan("effect-machine.actor.snapshot"));
|
|
58
77
|
const matches = Effect.fn("effect-machine.actor.matches")(function* (tag) {
|
|
@@ -88,32 +107,39 @@ const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listen
|
|
|
88
107
|
return {
|
|
89
108
|
id,
|
|
90
109
|
send,
|
|
110
|
+
cast: send,
|
|
111
|
+
call,
|
|
112
|
+
ask,
|
|
91
113
|
state: stateRef,
|
|
92
114
|
stop,
|
|
93
|
-
stopSync: () => Effect.runFork(stop),
|
|
94
115
|
snapshot,
|
|
95
|
-
snapshotSync: () => Effect.runSync(SubscriptionRef.get(stateRef)),
|
|
96
116
|
matches,
|
|
97
|
-
matchesSync: (tag) => Effect.runSync(SubscriptionRef.get(stateRef))._tag === tag,
|
|
98
117
|
can,
|
|
99
|
-
canSync: (event) => {
|
|
100
|
-
return resolveTransition(machine, Effect.runSync(SubscriptionRef.get(stateRef)), event) !== void 0;
|
|
101
|
-
},
|
|
102
118
|
changes: SubscriptionRef.changes(stateRef),
|
|
119
|
+
transitions: transitionsPubSub !== void 0 ? Stream.fromPubSub(transitionsPubSub) : Stream.empty,
|
|
103
120
|
waitFor,
|
|
104
121
|
awaitFinal,
|
|
105
122
|
sendAndWait,
|
|
106
|
-
sendSync: (event) => {
|
|
107
|
-
if (!Effect.runSync(Ref.get(stoppedRef))) Effect.runSync(Queue.offer(eventQueue, { event }));
|
|
108
|
-
},
|
|
109
|
-
dispatch,
|
|
110
|
-
dispatchPromise: (event) => Effect.runPromise(dispatch(event)),
|
|
111
123
|
subscribe: (fn) => {
|
|
112
124
|
listeners.add(fn);
|
|
113
125
|
return () => {
|
|
114
126
|
listeners.delete(fn);
|
|
115
127
|
};
|
|
116
128
|
},
|
|
129
|
+
sync: {
|
|
130
|
+
send: (event) => {
|
|
131
|
+
if (!Effect.runSync(Ref.get(stoppedRef))) Effect.runSync(Queue.offer(eventQueue, {
|
|
132
|
+
_tag: "send",
|
|
133
|
+
event
|
|
134
|
+
}));
|
|
135
|
+
},
|
|
136
|
+
stop: () => Effect.runFork(stop),
|
|
137
|
+
snapshot: () => Effect.runSync(SubscriptionRef.get(stateRef)),
|
|
138
|
+
matches: (tag) => Effect.runSync(SubscriptionRef.get(stateRef))._tag === tag,
|
|
139
|
+
can: (event) => {
|
|
140
|
+
return resolveTransition(machine, Effect.runSync(SubscriptionRef.get(stateRef)), event) !== void 0;
|
|
141
|
+
}
|
|
142
|
+
},
|
|
117
143
|
system,
|
|
118
144
|
children: childrenMap
|
|
119
145
|
};
|
|
@@ -121,7 +147,8 @@ const buildActorRefCore = (id, machine, stateRef, eventQueue, stoppedRef, listen
|
|
|
121
147
|
/**
|
|
122
148
|
* Create and start an actor for a machine
|
|
123
149
|
*/
|
|
124
|
-
const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine) {
|
|
150
|
+
const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine, options) {
|
|
151
|
+
const initial = options?.initialState ?? machine.initial;
|
|
125
152
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.id", id);
|
|
126
153
|
const existingSystem = yield* Effect.serviceOption(ActorSystem);
|
|
127
154
|
let system;
|
|
@@ -136,11 +163,16 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
136
163
|
const eventQueue = yield* Queue.unbounded();
|
|
137
164
|
const stoppedRef = yield* Ref.make(false);
|
|
138
165
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
166
|
+
const selfSend = Effect.fn("effect-machine.actor.self.send")(function* (event) {
|
|
167
|
+
if (yield* Ref.get(stoppedRef)) return;
|
|
168
|
+
yield* Queue.offer(eventQueue, {
|
|
169
|
+
_tag: "send",
|
|
170
|
+
event
|
|
171
|
+
});
|
|
172
|
+
});
|
|
139
173
|
const self = {
|
|
140
|
-
send:
|
|
141
|
-
|
|
142
|
-
yield* Queue.offer(eventQueue, { event });
|
|
143
|
-
}),
|
|
174
|
+
send: selfSend,
|
|
175
|
+
cast: selfSend,
|
|
144
176
|
spawn: (childId, childMachine) => Effect.gen(function* () {
|
|
145
177
|
const child = yield* system.spawn(childId, childMachine).pipe(Effect.provideService(ActorSystem, system));
|
|
146
178
|
childrenMap.set(childId, child);
|
|
@@ -151,20 +183,20 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
151
183
|
return child;
|
|
152
184
|
})
|
|
153
185
|
};
|
|
154
|
-
yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state",
|
|
186
|
+
yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state", initial._tag);
|
|
155
187
|
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
156
188
|
type: "@machine.spawn",
|
|
157
189
|
actorId: id,
|
|
158
|
-
initialState:
|
|
190
|
+
initialState: initial,
|
|
159
191
|
timestamp
|
|
160
192
|
}));
|
|
161
|
-
const stateRef = yield* SubscriptionRef.make(
|
|
193
|
+
const stateRef = yield* SubscriptionRef.make(initial);
|
|
162
194
|
const listeners = /* @__PURE__ */ new Set();
|
|
163
195
|
const backgroundFibers = [];
|
|
164
196
|
const initEvent = { _tag: INTERNAL_INIT_EVENT };
|
|
165
197
|
const ctx = {
|
|
166
198
|
actorId: id,
|
|
167
|
-
state:
|
|
199
|
+
state: initial,
|
|
168
200
|
event: initEvent,
|
|
169
201
|
self,
|
|
170
202
|
system
|
|
@@ -173,7 +205,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
173
205
|
for (const bg of machine.backgroundEffects) {
|
|
174
206
|
const fiber = yield* Effect.forkDetach(bg.handler({
|
|
175
207
|
actorId: id,
|
|
176
|
-
state:
|
|
208
|
+
state: initial,
|
|
177
209
|
event: initEvent,
|
|
178
210
|
self,
|
|
179
211
|
effects: effectSlots,
|
|
@@ -182,21 +214,23 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
182
214
|
backgroundFibers.push(fiber);
|
|
183
215
|
}
|
|
184
216
|
const stateScopeRef = { current: yield* Scope.make() };
|
|
185
|
-
yield* runSpawnEffectsWithInspection(machine,
|
|
186
|
-
if (machine.finalStates.has(
|
|
217
|
+
yield* runSpawnEffectsWithInspection(machine, initial, initEvent, self, stateScopeRef.current, id, inspectorValue, system);
|
|
218
|
+
if (machine.finalStates.has(initial._tag)) {
|
|
187
219
|
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
188
220
|
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
189
221
|
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
190
222
|
type: "@machine.stop",
|
|
191
223
|
actorId: id,
|
|
192
|
-
finalState:
|
|
224
|
+
finalState: initial,
|
|
193
225
|
timestamp
|
|
194
226
|
}));
|
|
195
227
|
yield* Ref.set(stoppedRef, true);
|
|
196
228
|
if (implicitSystemScope !== void 0) yield* Scope.close(implicitSystemScope, Exit.void);
|
|
197
|
-
return buildActorRefCore(id, machine, stateRef, eventQueue, stoppedRef, listeners, Ref.set(stoppedRef, true).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid), system, childrenMap);
|
|
229
|
+
return buildActorRefCore(id, machine, stateRef, eventQueue, stoppedRef, listeners, Ref.set(stoppedRef, true).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid), system, childrenMap, /* @__PURE__ */ new Set());
|
|
198
230
|
}
|
|
199
|
-
const
|
|
231
|
+
const pendingReplies = /* @__PURE__ */ new Set();
|
|
232
|
+
const transitionsPubSub = yield* PubSub.unbounded();
|
|
233
|
+
const loopFiber = yield* Effect.forkDetach(eventLoop(machine, stateRef, eventQueue, stoppedRef, self, listeners, backgroundFibers, stateScopeRef, id, inspectorValue, system, pendingReplies, transitionsPubSub));
|
|
200
234
|
return buildActorRefCore(id, machine, stateRef, eventQueue, stoppedRef, listeners, Effect.gen(function* () {
|
|
201
235
|
const finalState = yield* SubscriptionRef.get(stateRef);
|
|
202
236
|
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
@@ -207,33 +241,115 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
207
241
|
}));
|
|
208
242
|
yield* Ref.set(stoppedRef, true);
|
|
209
243
|
yield* Fiber.interrupt(loopFiber);
|
|
244
|
+
yield* settlePendingReplies(pendingReplies, id);
|
|
210
245
|
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
211
246
|
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
212
247
|
if (implicitSystemScope !== void 0) yield* Scope.close(implicitSystemScope, Exit.void);
|
|
213
|
-
}).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid), system, childrenMap);
|
|
248
|
+
}).pipe(Effect.withSpan("effect-machine.actor.stop"), Effect.asVoid), system, childrenMap, pendingReplies, transitionsPubSub);
|
|
249
|
+
});
|
|
250
|
+
/** Fail all pending call/ask Deferreds with ActorStoppedError. Safe to call multiple times. */
|
|
251
|
+
const settlePendingReplies = (pendingReplies, actorId) => Effect.sync(() => {
|
|
252
|
+
const error = new ActorStoppedError({ actorId });
|
|
253
|
+
for (const deferred of pendingReplies) Effect.runFork(Deferred.fail(deferred, error));
|
|
254
|
+
pendingReplies.clear();
|
|
214
255
|
});
|
|
215
256
|
/**
|
|
216
|
-
* Main event loop for the actor
|
|
257
|
+
* Main event loop for the actor.
|
|
258
|
+
* Includes postpone buffer — events matching postpone rules are buffered
|
|
259
|
+
* and drained after state tag changes (gen_statem semantics).
|
|
217
260
|
*/
|
|
218
|
-
const eventLoop = Effect.fn("effect-machine.actor.eventLoop")(function* (machine, stateRef, eventQueue, stoppedRef, self, listeners, backgroundFibers, stateScopeRef, actorId, inspector, system) {
|
|
219
|
-
|
|
220
|
-
|
|
261
|
+
const eventLoop = Effect.fn("effect-machine.actor.eventLoop")(function* (machine, stateRef, eventQueue, stoppedRef, self, listeners, backgroundFibers, stateScopeRef, actorId, inspector, system, pendingReplies, transitionsPubSub) {
|
|
262
|
+
const postponed = [];
|
|
263
|
+
const hasPostponeRules = machine.postponeRules.length > 0;
|
|
264
|
+
const processQueued = Effect.fn("effect-machine.actor.processQueued")(function* (queued) {
|
|
265
|
+
const event = queued.event;
|
|
221
266
|
const currentState = yield* SubscriptionRef.get(stateRef);
|
|
267
|
+
if (hasPostponeRules && shouldPostpone(machine, currentState._tag, event._tag)) {
|
|
268
|
+
postponed.push(queued);
|
|
269
|
+
if (queued._tag === "call") {
|
|
270
|
+
const postponedResult = {
|
|
271
|
+
newState: currentState,
|
|
272
|
+
previousState: currentState,
|
|
273
|
+
transitioned: false,
|
|
274
|
+
lifecycleRan: false,
|
|
275
|
+
isFinal: false,
|
|
276
|
+
hasReply: false,
|
|
277
|
+
reply: void 0,
|
|
278
|
+
postponed: true
|
|
279
|
+
};
|
|
280
|
+
yield* Deferred.succeed(queued.reply, postponedResult);
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
shouldStop: false,
|
|
284
|
+
stateChanged: false
|
|
285
|
+
};
|
|
286
|
+
}
|
|
222
287
|
const { shouldStop, result } = yield* Effect.withSpan("effect-machine.event.process", { attributes: {
|
|
223
288
|
"effect_machine.actor.id": actorId,
|
|
224
289
|
"effect_machine.state.current": currentState._tag,
|
|
225
290
|
"effect_machine.event.type": event._tag
|
|
226
291
|
} })(processEvent(machine, currentState, event, stateRef, self, listeners, stateScopeRef, actorId, inspector, system));
|
|
227
|
-
|
|
292
|
+
switch (queued._tag) {
|
|
293
|
+
case "call":
|
|
294
|
+
yield* Deferred.succeed(queued.reply, result);
|
|
295
|
+
break;
|
|
296
|
+
case "ask":
|
|
297
|
+
if (result.hasReply) yield* Deferred.succeed(queued.reply, result.reply);
|
|
298
|
+
else yield* Deferred.fail(queued.reply, new NoReplyError({
|
|
299
|
+
actorId,
|
|
300
|
+
eventTag: event._tag
|
|
301
|
+
}));
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
if (result.transitioned) yield* PubSub.publish(transitionsPubSub, {
|
|
305
|
+
fromState: result.previousState,
|
|
306
|
+
toState: result.newState,
|
|
307
|
+
event
|
|
308
|
+
});
|
|
309
|
+
return {
|
|
310
|
+
shouldStop,
|
|
311
|
+
stateChanged: result.lifecycleRan
|
|
312
|
+
};
|
|
313
|
+
});
|
|
314
|
+
while (true) {
|
|
315
|
+
const { shouldStop, stateChanged } = yield* processQueued(yield* Queue.take(eventQueue));
|
|
228
316
|
if (shouldStop) {
|
|
229
317
|
yield* Ref.set(stoppedRef, true);
|
|
318
|
+
settlePostponedBuffer(postponed, pendingReplies, actorId);
|
|
319
|
+
yield* settlePendingReplies(pendingReplies, actorId);
|
|
230
320
|
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
231
321
|
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
232
322
|
return;
|
|
233
323
|
}
|
|
324
|
+
let drainTriggered = stateChanged;
|
|
325
|
+
while (drainTriggered && postponed.length > 0) {
|
|
326
|
+
drainTriggered = false;
|
|
327
|
+
const drained = postponed.splice(0);
|
|
328
|
+
for (const entry of drained) {
|
|
329
|
+
const drain = yield* processQueued(entry);
|
|
330
|
+
if (drain.shouldStop) {
|
|
331
|
+
yield* Ref.set(stoppedRef, true);
|
|
332
|
+
settlePostponedBuffer(postponed, pendingReplies, actorId);
|
|
333
|
+
yield* settlePendingReplies(pendingReplies, actorId);
|
|
334
|
+
yield* Scope.close(stateScopeRef.current, Exit.void);
|
|
335
|
+
yield* Effect.all(backgroundFibers.map(Fiber.interrupt), { concurrency: "unbounded" });
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (drain.stateChanged) drainTriggered = true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
234
341
|
}
|
|
235
342
|
});
|
|
236
343
|
/**
|
|
344
|
+
* Settle all reply-bearing entries in the postpone buffer on shutdown.
|
|
345
|
+
* Call entries already had their Deferred settled with the postponed result
|
|
346
|
+
* (so their pendingReplies entry is already removed). Ask/send entries
|
|
347
|
+
* with Deferreds are settled via the pendingReplies registry.
|
|
348
|
+
*/
|
|
349
|
+
const settlePostponedBuffer = (postponed, _pendingReplies, _actorId) => {
|
|
350
|
+
postponed.length = 0;
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
237
353
|
* Process a single event, returning true if the actor should stop.
|
|
238
354
|
* Wraps processEventCore with actor-specific concerns (inspection, listeners, state ref).
|
|
239
355
|
*/
|
|
@@ -375,25 +491,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
375
491
|
if (MutableHashMap.has(actorsMap, id)) return yield* new DuplicateActorError({ actorId: id });
|
|
376
492
|
return yield* registerActor(id, yield* createActor(id, built._inner));
|
|
377
493
|
});
|
|
378
|
-
const
|
|
379
|
-
if (MutableHashMap.has(actorsMap, id)) return yield* new DuplicateActorError({ actorId: id });
|
|
380
|
-
const adapter = yield* PersistenceAdapterTag;
|
|
381
|
-
const maybeSnapshot = yield* adapter.loadSnapshot(id, persistentMachine.persistence.stateSchema);
|
|
382
|
-
return yield* registerActor(id, yield* createPersistentActor(id, persistentMachine, maybeSnapshot, yield* adapter.loadEvents(id, persistentMachine.persistence.eventSchema, Option.isSome(maybeSnapshot) ? maybeSnapshot.value.version : void 0)));
|
|
383
|
-
});
|
|
384
|
-
const spawnImpl = Effect.fn("effect-machine.actorSystem.spawn")(function* (id, machine) {
|
|
385
|
-
if (isPersistentMachine(machine)) return yield* spawnPersistent(id, machine);
|
|
386
|
-
return yield* spawnRegular(id, machine);
|
|
387
|
-
});
|
|
388
|
-
function spawn(id, machine) {
|
|
389
|
-
return withSpawnGate(spawnImpl(id, machine));
|
|
390
|
-
}
|
|
391
|
-
const restoreImpl = Effect.fn("effect-machine.actorSystem.restore")(function* (id, persistentMachine) {
|
|
392
|
-
const maybeActor = yield* restorePersistentActor(id, persistentMachine);
|
|
393
|
-
if (Option.isSome(maybeActor)) yield* registerActor(id, maybeActor.value);
|
|
394
|
-
return maybeActor;
|
|
395
|
-
});
|
|
396
|
-
const restore = (id, persistentMachine) => withSpawnGate(restoreImpl(id, persistentMachine));
|
|
494
|
+
const spawn = (id, machine) => withSpawnGate(spawnRegular(id, machine));
|
|
397
495
|
const get = Effect.fn("effect-machine.actorSystem.get")(function* (id) {
|
|
398
496
|
return yield* Effect.sync(() => MutableHashMap.get(actorsMap, id));
|
|
399
497
|
});
|
|
@@ -410,55 +508,8 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
410
508
|
yield* actor.stop;
|
|
411
509
|
return true;
|
|
412
510
|
});
|
|
413
|
-
const listPersisted = Effect.fn("effect-machine.actorSystem.listPersisted")(function* () {
|
|
414
|
-
const adapter = yield* PersistenceAdapterTag;
|
|
415
|
-
if (adapter.listActors === void 0) return [];
|
|
416
|
-
return yield* adapter.listActors();
|
|
417
|
-
});
|
|
418
|
-
const restoreMany = Effect.fn("effect-machine.actorSystem.restoreMany")(function* (ids, persistentMachine) {
|
|
419
|
-
const restored = [];
|
|
420
|
-
const failed = [];
|
|
421
|
-
for (const id of ids) {
|
|
422
|
-
if (MutableHashMap.has(actorsMap, id)) continue;
|
|
423
|
-
const result = yield* Effect.result(restore(id, persistentMachine));
|
|
424
|
-
if (result._tag === "Failure") failed.push({
|
|
425
|
-
id,
|
|
426
|
-
error: result.failure
|
|
427
|
-
});
|
|
428
|
-
else if (Option.isSome(result.success)) restored.push(result.success.value);
|
|
429
|
-
else failed.push({
|
|
430
|
-
id,
|
|
431
|
-
error: new PersistenceError({
|
|
432
|
-
operation: "restore",
|
|
433
|
-
actorId: id,
|
|
434
|
-
message: "No persisted state found"
|
|
435
|
-
})
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
return {
|
|
439
|
-
restored,
|
|
440
|
-
failed
|
|
441
|
-
};
|
|
442
|
-
});
|
|
443
|
-
const restoreAll = Effect.fn("effect-machine.actorSystem.restoreAll")(function* (persistentMachine, options) {
|
|
444
|
-
const adapter = yield* PersistenceAdapterTag;
|
|
445
|
-
if (adapter.listActors === void 0) return {
|
|
446
|
-
restored: [],
|
|
447
|
-
failed: []
|
|
448
|
-
};
|
|
449
|
-
const machineType = persistentMachine.persistence.machineType;
|
|
450
|
-
if (machineType === void 0) return yield* new PersistenceError({
|
|
451
|
-
operation: "restoreAll",
|
|
452
|
-
actorId: "*",
|
|
453
|
-
message: "restoreAll requires explicit machineType in persistence config"
|
|
454
|
-
});
|
|
455
|
-
let filtered = (yield* adapter.listActors()).filter((meta) => meta.machineType === machineType);
|
|
456
|
-
if (options?.filter !== void 0) filtered = filtered.filter(options.filter);
|
|
457
|
-
return yield* restoreMany(filtered.map((meta) => meta.id), persistentMachine);
|
|
458
|
-
});
|
|
459
511
|
return ActorSystem.of({
|
|
460
512
|
spawn,
|
|
461
|
-
restore,
|
|
462
513
|
get,
|
|
463
514
|
stop,
|
|
464
515
|
events: Stream.fromPubSub(eventPubSub),
|
|
@@ -474,10 +525,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
474
525
|
return () => {
|
|
475
526
|
eventListeners.delete(fn);
|
|
476
527
|
};
|
|
477
|
-
}
|
|
478
|
-
listPersisted,
|
|
479
|
-
restoreMany,
|
|
480
|
-
restoreAll
|
|
528
|
+
}
|
|
481
529
|
});
|
|
482
530
|
});
|
|
483
531
|
/**
|
|
@@ -485,4 +533,4 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
485
533
|
*/
|
|
486
534
|
const Default = Layer.effect(ActorSystem, make());
|
|
487
535
|
//#endregion
|
|
488
|
-
export { ActorSystem, Default, buildActorRefCore, createActor, notifyListeners, processEventCore, resolveTransition, runSpawnEffects };
|
|
536
|
+
export { ActorSystem, Default, buildActorRefCore, createActor, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
|
|
@@ -54,10 +54,12 @@ const EntityMachine = { layer: (entity, machine, options) => {
|
|
|
54
54
|
if (Option.isNone(existingSystem)) return yield* Effect.die("EntityMachine requires ActorSystem in context");
|
|
55
55
|
const system = existingSystem.value;
|
|
56
56
|
const internalQueue = yield* Queue.unbounded();
|
|
57
|
+
const clusterSend = Effect.fn("effect-machine.cluster.self.send")(function* (event) {
|
|
58
|
+
yield* Queue.offer(internalQueue, event);
|
|
59
|
+
});
|
|
57
60
|
const self = {
|
|
58
|
-
send:
|
|
59
|
-
|
|
60
|
-
}),
|
|
61
|
+
send: clusterSend,
|
|
62
|
+
cast: clusterSend,
|
|
61
63
|
spawn: (childId, childMachine) => system.spawn(childId, childMachine).pipe(Effect.provideService(ActorSystem, system))
|
|
62
64
|
};
|
|
63
65
|
const stateRef = yield* Ref.make(initialState);
|
package/dist/errors.d.ts
CHANGED
|
@@ -42,5 +42,16 @@ declare const AssertionError_base: Schema.ErrorClass<AssertionError, Schema.Tagg
|
|
|
42
42
|
}>, effect_Cause0.YieldableError>;
|
|
43
43
|
/** Assertion failed in testing utilities */
|
|
44
44
|
declare class AssertionError extends AssertionError_base {}
|
|
45
|
+
declare const ActorStoppedError_base: Schema.ErrorClass<ActorStoppedError, Schema.TaggedStruct<"ActorStoppedError", {
|
|
46
|
+
readonly actorId: Schema.String;
|
|
47
|
+
}>, effect_Cause0.YieldableError>;
|
|
48
|
+
/** Actor was stopped while a call/ask was pending */
|
|
49
|
+
declare class ActorStoppedError extends ActorStoppedError_base {}
|
|
50
|
+
declare const NoReplyError_base: Schema.ErrorClass<NoReplyError, Schema.TaggedStruct<"NoReplyError", {
|
|
51
|
+
readonly actorId: Schema.String;
|
|
52
|
+
readonly eventTag: Schema.String;
|
|
53
|
+
}>, effect_Cause0.YieldableError>;
|
|
54
|
+
/** ask() was used but the transition handler did not call reply */
|
|
55
|
+
declare class NoReplyError extends NoReplyError_base {}
|
|
45
56
|
//#endregion
|
|
46
|
-
export { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError };
|
|
57
|
+
export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError };
|
package/dist/errors.js
CHANGED
|
@@ -32,5 +32,12 @@ var ProvisionValidationError = class extends Schema.TaggedErrorClass()("Provisio
|
|
|
32
32
|
}) {};
|
|
33
33
|
/** Assertion failed in testing utilities */
|
|
34
34
|
var AssertionError = class extends Schema.TaggedErrorClass()("AssertionError", { message: Schema.String }) {};
|
|
35
|
+
/** Actor was stopped while a call/ask was pending */
|
|
36
|
+
var ActorStoppedError = class extends Schema.TaggedErrorClass()("ActorStoppedError", { actorId: Schema.String }) {};
|
|
37
|
+
/** ask() was used but the transition handler did not call reply */
|
|
38
|
+
var NoReplyError = class extends Schema.TaggedErrorClass()("NoReplyError", {
|
|
39
|
+
actorId: Schema.String,
|
|
40
|
+
eventTag: Schema.String
|
|
41
|
+
}) {};
|
|
35
42
|
//#endregion
|
|
36
|
-
export { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError };
|
|
43
|
+
export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { EffectHandlers, EffectSlot, EffectSlots, EffectsDef, EffectsSchema, GuardHandlers, GuardSlot, GuardSlots, GuardsDef, GuardsSchema, MachineContext, Slot } from "./slot.js";
|
|
2
2
|
import { Event, MachineEventSchema, MachineStateSchema, State } from "./schema.js";
|
|
3
|
-
import {
|
|
4
|
-
import { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
3
|
+
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
5
4
|
import { ProcessEventResult } from "./internal/transition.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { InMemoryPersistenceAdapter, makeInMemoryPersistenceAdapter } from "./persistence/adapters/in-memory.js";
|
|
9
|
-
import { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, PersistOptions, ProvideHandlers, SpawnEffect, StateHandlerContext, TaskOptions, Transition, machine_d_exports } from "./machine.js";
|
|
10
|
-
import { ActorRef, ActorSystem, Default, SystemEvent, SystemEventListener } from "./actor.js";
|
|
5
|
+
import { BackgroundEffect, BuiltMachine, HandlerContext, Machine, MachineRef, MakeConfig, ProvideHandlers, SpawnEffect, StateHandlerContext, TaskOptions, Transition, machine_d_exports } from "./machine.js";
|
|
6
|
+
import { ActorRef, ActorRefSync, ActorSystem, Default, SystemEvent, SystemEventListener, TransitionInfo } from "./actor.js";
|
|
11
7
|
import { SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
12
8
|
import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, InspectionEvent, Inspector, InspectorHandler, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
13
|
-
export { type
|
|
9
|
+
export { type ActorRef, type ActorRefSync, ActorStoppedError, type ActorSystem, Default as ActorSystemDefault, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type BackgroundEffect, type BuiltMachine, DuplicateActorError, type EffectEvent, type EffectSlots, type EffectsDef, type EffectsSchema, type ErrorEvent, Event, type EventReceivedEvent, type GuardHandlers, type GuardSlot, type GuardSlots, type GuardsDef, type GuardsSchema, type HandlerContext, 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, type ProcessEventResult, type ProvideHandlers, ProvisionValidationError, type SimulationResult, Slot, type EffectHandlers as SlotEffectHandlers, type EffectSlot as SlotEffectSlot, SlotProvisionError, type SpawnEffect, type SpawnEvent, State, type StateHandlerContext, type StopEvent, type SystemEvent, type SystemEventListener, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TracingInspectorOptions, type Transition, type TransitionEvent, type TransitionInfo, UnprovidedSlotsError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
2
|
-
import { AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
3
|
-
import { isPersistentMachine } from "./persistence/persistent-machine.js";
|
|
2
|
+
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, SlotProvisionError, UnprovidedSlotsError } from "./errors.js";
|
|
4
3
|
import { Slot } from "./slot.js";
|
|
5
4
|
import { machine_exports } from "./machine.js";
|
|
6
|
-
import { PersistenceAdapterTag, PersistenceError, VersionConflictError } from "./persistence/adapter.js";
|
|
7
|
-
import { createPersistentActor, restorePersistentActor } from "./persistence/persistent-actor.js";
|
|
8
5
|
import { ActorSystem, Default } from "./actor.js";
|
|
9
6
|
import { Event, State } from "./schema.js";
|
|
10
7
|
import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
11
|
-
|
|
12
|
-
import "./persistence/index.js";
|
|
13
|
-
export { Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, InMemoryPersistenceAdapter, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, PersistenceAdapterTag, PersistenceError, ProvisionValidationError, Slot, SlotProvisionError, State, UnprovidedSlotsError, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createPersistentActor, createTestHarness, isPersistentMachine, makeInMemoryPersistenceAdapter, makeInspector, makeInspectorEffect, restorePersistentActor, simulate, tracingInspector };
|
|
8
|
+
export { ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, ProvisionValidationError, Slot, SlotProvisionError, State, UnprovidedSlotsError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
|
@@ -21,7 +21,7 @@ interface TransitionExecutionResult<S> {
|
|
|
21
21
|
*
|
|
22
22
|
* Used by:
|
|
23
23
|
* - executeTransition (actor event loop, testing)
|
|
24
|
-
* -
|
|
24
|
+
* - Machine.replay (event sourcing restore)
|
|
25
25
|
*
|
|
26
26
|
* @internal
|
|
27
27
|
*/
|
|
@@ -29,7 +29,11 @@ declare const runTransitionHandler: <S extends {
|
|
|
29
29
|
readonly _tag: string;
|
|
30
30
|
}, E extends {
|
|
31
31
|
readonly _tag: string;
|
|
32
|
-
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, transition: Transition<S, E, GD, EFD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<
|
|
32
|
+
}, R, GD extends GuardsDef, EFD extends EffectsDef>(machine: Machine<S, E, R, Record<string, never>, Record<string, never>, GD, EFD>, transition: Transition<S, E, GD, EFD, R>, state: S, event: E, self: MachineRef<E>, system: ActorSystem, actorId: string) => Effect.Effect<{
|
|
33
|
+
newState: S;
|
|
34
|
+
hasReply: boolean;
|
|
35
|
+
reply: unknown;
|
|
36
|
+
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
|
|
33
37
|
/**
|
|
34
38
|
* Execute a transition for a given state and event.
|
|
35
39
|
* Handles transition resolution, handler invocation, and guard/effect slot creation.
|
|
@@ -49,6 +53,8 @@ declare const executeTransition: <S extends {
|
|
|
49
53
|
newState: S;
|
|
50
54
|
transitioned: boolean;
|
|
51
55
|
reenter: boolean;
|
|
56
|
+
hasReply: boolean;
|
|
57
|
+
reply: unknown;
|
|
52
58
|
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>>>;
|
|
53
59
|
/**
|
|
54
60
|
* Optional hooks for event processing inspection/tracing.
|
|
@@ -84,7 +90,22 @@ interface ProcessEventResult<S> {
|
|
|
84
90
|
readonly lifecycleRan: boolean;
|
|
85
91
|
/** Whether new state is final */
|
|
86
92
|
readonly isFinal: boolean;
|
|
93
|
+
/** Whether the handler provided a reply (structural, not value-based) */
|
|
94
|
+
readonly hasReply: boolean;
|
|
95
|
+
/** Domain reply value from handler (used by ask). Only meaningful when hasReply is true. */
|
|
96
|
+
readonly reply?: unknown;
|
|
97
|
+
/** Whether the event was postponed (buffered for retry after next state change) */
|
|
98
|
+
readonly postponed: boolean;
|
|
87
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Check if an event should be postponed in the current state.
|
|
102
|
+
* @internal
|
|
103
|
+
*/
|
|
104
|
+
declare const shouldPostpone: <S extends {
|
|
105
|
+
readonly _tag: string;
|
|
106
|
+
}, E extends {
|
|
107
|
+
readonly _tag: string;
|
|
108
|
+
}, R>(machine: Machine<S, E, R, any, any, any, any>, stateTag: string, eventTag: string) => boolean;
|
|
88
109
|
/**
|
|
89
110
|
* Process a single event through the machine.
|
|
90
111
|
*
|
|
@@ -109,6 +130,9 @@ declare const processEventCore: <S extends {
|
|
|
109
130
|
transitioned: boolean;
|
|
110
131
|
lifecycleRan: boolean;
|
|
111
132
|
isFinal: boolean;
|
|
133
|
+
hasReply: boolean;
|
|
134
|
+
reply: unknown;
|
|
135
|
+
postponed: boolean;
|
|
112
136
|
}, never, Exclude<R, MachineContext<S, E, MachineRef<E>>> | Exclude<Exclude<R, MachineContext<S, E, MachineRef<E>>>, Scope.Scope>>;
|
|
113
137
|
/**
|
|
114
138
|
* Run spawn effects for a state (forked into state scope, auto-cancelled on state exit).
|
|
@@ -157,4 +181,4 @@ declare const findSpawnEffects: <S extends {
|
|
|
157
181
|
readonly _tag: string;
|
|
158
182
|
}, R, GD extends GuardsDef = Record<string, never>, EFD extends EffectsDef = Record<string, never>>(machine: Machine<S, E, R, any, any, GD, EFD>, stateTag: string) => ReadonlyArray<SpawnEffect<S, E, EFD, R>>;
|
|
159
183
|
//#endregion
|
|
160
|
-
export { ProcessEventError, ProcessEventHooks, ProcessEventResult, TransitionExecutionResult, executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler };
|
|
184
|
+
export { ProcessEventError, ProcessEventHooks, ProcessEventResult, TransitionExecutionResult, executeTransition, findSpawnEffects, findTransitions, invalidateIndex, processEventCore, resolveTransition, runSpawnEffects, runTransitionHandler, shouldPostpone };
|