effect-machine 0.22.0 → 0.24.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 +6 -1
- package/dist/actor.d.ts +13 -0
- package/dist/actor.js +26 -21
- package/dist/cluster/entity-machine.js +2 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/inspection.d.ts +1 -19
- package/dist/inspection.js +3 -34
- package/dist/internal/inspection.d.ts +12 -2
- package/dist/internal/inspection.js +22 -4
- package/dist/internal/runtime.js +23 -6
- package/dist/internal/utils.js +2 -1
- package/dist/machine.d.ts +11 -4
- package/dist/machine.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -95,6 +95,10 @@ Effect Machine does not add an action queue or a second context system.
|
|
|
95
95
|
|
|
96
96
|
Effect requirements remain in `R`. A machine cannot start until the application provides every required service. Effectful transition handlers must have `never` in their error channel. Convert expected failures to states or events.
|
|
97
97
|
|
|
98
|
+
Machine-lifetime backgrounds can read `self.state` and `self.latestTransition`. These are the
|
|
99
|
+
actor-owned subscription refs. They stay stable across supervision generations. Treat them as
|
|
100
|
+
read-only and use `SubscriptionRef.get` or `SubscriptionRef.changes` to observe them.
|
|
101
|
+
|
|
98
102
|
Read [the Effect model](./docs/effect-model.md) and [async work ownership](./docs/async-work.md).
|
|
99
103
|
|
|
100
104
|
## Guards and stable state
|
|
@@ -204,7 +208,8 @@ Read [Atom and UI integration](./docs/atom-and-ui.md) and browse [all examples](
|
|
|
204
208
|
- Durability saves committed transitions.
|
|
205
209
|
- Supervision restarts defects within an Effect `Schedule` budget.
|
|
206
210
|
- Inspection reports events, named transition operations, transitions, named guards, tasks, Effects, errors, stops, and actor generations.
|
|
207
|
-
-
|
|
211
|
+
- Typed `inspect` spawn options observe one actor.
|
|
212
|
+
- `actor.system.inspect` lets a late tool observe all actors in one system.
|
|
208
213
|
|
|
209
214
|
Read [Persistence and supervision](./docs/persistence-and-supervision.md) and [Inspection](./docs/inspection.md).
|
|
210
215
|
|
package/dist/actor.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ExtractReply, ReplyTypeBrand } from "./internal/brands.js";
|
|
2
2
|
import { ActorStoppedError, DuplicateActorError, NoReplyError } from "./errors.js";
|
|
3
|
+
import { InspectorService } from "./inspection.js";
|
|
3
4
|
import { ActorExit, Supervision } from "./supervision.js";
|
|
4
5
|
import { Lifecycle, Machine } from "./machine.js";
|
|
5
6
|
import { ProcessEventResult } from "./internal/transition.js";
|
|
@@ -238,11 +239,22 @@ interface ActorSystemService {
|
|
|
238
239
|
* Returns an unsubscribe function.
|
|
239
240
|
*/
|
|
240
241
|
readonly subscribe: (fn: SystemEventListener) => () => void;
|
|
242
|
+
/**
|
|
243
|
+
* Inspect all actors in this system.
|
|
244
|
+
*
|
|
245
|
+
* Registration affects future events only. The returned function removes the inspector.
|
|
246
|
+
*/
|
|
247
|
+
readonly inspect: (inspector: InspectorService<{
|
|
248
|
+
readonly _tag: string;
|
|
249
|
+
}, {
|
|
250
|
+
readonly _tag: string;
|
|
251
|
+
}>) => () => void;
|
|
241
252
|
}
|
|
242
253
|
type SystemSpawnOptions<S, E, Input> = {
|
|
243
254
|
readonly supervision?: Supervision.Policy;
|
|
244
255
|
readonly lifecycle?: Lifecycle<S, E>;
|
|
245
256
|
readonly hydrate?: S;
|
|
257
|
+
readonly inspect?: InspectorService<S, E>;
|
|
246
258
|
} & ([Input] extends [void] ? {
|
|
247
259
|
readonly input?: never;
|
|
248
260
|
} : {
|
|
@@ -278,6 +290,7 @@ declare const createActor: <S extends {
|
|
|
278
290
|
hydrated?: boolean;
|
|
279
291
|
supervision?: Supervision.Policy;
|
|
280
292
|
lifecycle?: Lifecycle<S, E>;
|
|
293
|
+
inspect?: InspectorService<S, E>;
|
|
281
294
|
/** @internal Called by system after each restart — emits ActorRestarted system event */
|
|
282
295
|
onRestart?: (generation: number, exit: ActorExit<unknown>) => Effect.Effect<void>;
|
|
283
296
|
}) => Effect.Effect<ActorRef<S, E, O>, never, R>;
|
package/dist/actor.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ActorStoppedError, DuplicateActorError } from "./errors.js";
|
|
2
2
|
import { resolveTransition, resolveTransitionEffect } from "./internal/transition.js";
|
|
3
|
-
import { emitWithTimestamp, makeInspectionHooks } from "./internal/inspection.js";
|
|
3
|
+
import { emitWithTimestamp, makeInspectionDispatcher, makeInspectionHooks } from "./internal/inspection.js";
|
|
4
4
|
import { Inspector } from "./inspection.js";
|
|
5
5
|
import { ActorExit } from "./supervision.js";
|
|
6
6
|
import { createRuntime } from "./internal/runtime.js";
|
|
@@ -27,6 +27,7 @@ const actorSystemId = (id) => {
|
|
|
27
27
|
if (typeof id === "string") return id;
|
|
28
28
|
return id.id;
|
|
29
29
|
};
|
|
30
|
+
const systemInspectorsBySystem = /* @__PURE__ */ new WeakMap();
|
|
30
31
|
/**
|
|
31
32
|
* ActorSystem service tag
|
|
32
33
|
*/
|
|
@@ -259,6 +260,7 @@ const runSupervisionLoop = (cell, options) => Effect.gen(function* () {
|
|
|
259
260
|
const freshQueue = yield* Queue.unbounded();
|
|
260
261
|
yield* Ref.set(cell.eventQueueRef, freshQueue);
|
|
261
262
|
yield* SubscriptionRef.set(cell.stateRef, restartState);
|
|
263
|
+
yield* SubscriptionRef.set(cell.latestTransitionRef, void 0);
|
|
262
264
|
yield* Ref.set(cell.stoppedRef, false);
|
|
263
265
|
cell.children.clear();
|
|
264
266
|
const newRuntime = yield* options.spawnGeneration(cell.machine);
|
|
@@ -279,20 +281,21 @@ const runSupervisionLoop = (cell, options) => Effect.gen(function* () {
|
|
|
279
281
|
*/
|
|
280
282
|
const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine, options) {
|
|
281
283
|
const lifecycle = options.lifecycle;
|
|
282
|
-
const
|
|
284
|
+
const capturedContext = yield* Effect.context();
|
|
283
285
|
const initial = options.initialState;
|
|
284
286
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.id", id);
|
|
285
287
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state", initial._tag);
|
|
286
288
|
const { system, implicitSystemScope } = yield* resolveActorSystem();
|
|
287
|
-
const
|
|
289
|
+
const ambientInspector = Option.getOrUndefined(yield* Effect.serviceOption(Inspector));
|
|
290
|
+
const localInspector = options.inspect ?? ambientInspector;
|
|
291
|
+
const systemInspectors = systemInspectorsBySystem.get(system) ?? /* @__PURE__ */ new Set();
|
|
292
|
+
const inspectorValue = makeInspectionDispatcher(localInspector, systemInspectors);
|
|
293
|
+
const serviceContext = Context.add(capturedContext, Inspector, inspectorValue);
|
|
288
294
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
289
295
|
const listeners = /* @__PURE__ */ new Set();
|
|
290
296
|
const transitionsPubSub = yield* PubSub.unbounded();
|
|
291
297
|
const generation = { current: 0 };
|
|
292
|
-
const inspectionHooks = (runtimeGeneration) =>
|
|
293
|
-
if (inspectorValue === void 0) return void 0;
|
|
294
|
-
return makeInspectionHooks(id, inspectorValue, () => runtimeGeneration);
|
|
295
|
-
};
|
|
298
|
+
const inspectionHooks = (runtimeGeneration) => makeInspectionHooks(id, inspectorValue, () => runtimeGeneration);
|
|
296
299
|
const stateRef = yield* SubscriptionRef.make(initial);
|
|
297
300
|
const lifecycleRef = yield* SubscriptionRef.make({ _tag: "Created" });
|
|
298
301
|
const latestTransitionRef = yield* SubscriptionRef.make(void 0);
|
|
@@ -322,8 +325,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
322
325
|
/** Build lifecycle hooks for a generation */
|
|
323
326
|
const buildRuntimeLifecycle = (runtimeGeneration) => {
|
|
324
327
|
let stopEmitted = false;
|
|
325
|
-
|
|
326
|
-
if (inspectorValue !== void 0) onEvent = (state, event) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
328
|
+
const onEvent = (state, event) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
327
329
|
type: "@machine.event",
|
|
328
330
|
actorId: id,
|
|
329
331
|
generation: runtimeGeneration,
|
|
@@ -331,8 +333,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
331
333
|
event,
|
|
332
334
|
timestamp
|
|
333
335
|
}));
|
|
334
|
-
|
|
335
|
-
if (inspectorValue !== void 0) onFinal = (state) => Effect.gen(function* () {
|
|
336
|
+
const onFinal = (state) => Effect.gen(function* () {
|
|
336
337
|
stopEmitted = true;
|
|
337
338
|
yield* emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
338
339
|
type: "@machine.stop",
|
|
@@ -342,8 +343,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
342
343
|
timestamp
|
|
343
344
|
}));
|
|
344
345
|
});
|
|
345
|
-
|
|
346
|
-
if (inspectorValue !== void 0) onInitialSpawnEffects = (state) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
346
|
+
const onInitialSpawnEffects = (state) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
347
347
|
type: "@machine.effect",
|
|
348
348
|
actorId: id,
|
|
349
349
|
generation: runtimeGeneration,
|
|
@@ -354,12 +354,6 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
354
354
|
return {
|
|
355
355
|
onEvent,
|
|
356
356
|
onStateChange: (result, event) => Effect.gen(function* () {
|
|
357
|
-
const latest = result.transitions.at(-1);
|
|
358
|
-
if (latest !== void 0) yield* SubscriptionRef.set(latestTransitionRef, {
|
|
359
|
-
fromState: latest.previousState,
|
|
360
|
-
toState: latest.newState,
|
|
361
|
-
event: latest.event
|
|
362
|
-
});
|
|
363
357
|
notifyListeners(listeners, result.newState);
|
|
364
358
|
const durability = lifecycle?.durability;
|
|
365
359
|
if (durability === void 0 || !result.transitioned) return;
|
|
@@ -406,6 +400,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
406
400
|
skipFinalizer: true,
|
|
407
401
|
cellResources: {
|
|
408
402
|
stateRef,
|
|
403
|
+
latestTransitionRef,
|
|
409
404
|
stoppedRef,
|
|
410
405
|
eventQueue: currentQueue
|
|
411
406
|
},
|
|
@@ -488,13 +483,14 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
488
483
|
const withSpawnGate = (yield* Semaphore.make(1)).withPermits(1);
|
|
489
484
|
const eventPubSub = yield* PubSub.unbounded();
|
|
490
485
|
const eventListeners = /* @__PURE__ */ new Set();
|
|
486
|
+
const systemInspectors = /* @__PURE__ */ new Set();
|
|
491
487
|
const emitSystemEvent = (event) => Effect.sync(() => notifySystemListeners(eventListeners, event)).pipe(Effect.andThen(PubSub.publish(eventPubSub, event)), Effect.catchCause(() => Effect.void), Effect.asVoid);
|
|
492
488
|
yield* Effect.addFinalizer(() => {
|
|
493
489
|
const stops = [];
|
|
494
490
|
MutableHashMap.forEach(actorsMap, (actor) => {
|
|
495
491
|
stops.push(actor.stop);
|
|
496
492
|
});
|
|
497
|
-
return Effect.all(stops).pipe(Effect.andThen(PubSub.shutdown(eventPubSub)), Effect.asVoid);
|
|
493
|
+
return Effect.all(stops).pipe(Effect.andThen(Effect.sync(() => systemInspectors.clear())), Effect.andThen(PubSub.shutdown(eventPubSub)), Effect.asVoid);
|
|
498
494
|
});
|
|
499
495
|
/** Check for duplicate ID, register actor, attach scope cleanup if available */
|
|
500
496
|
const registerActor = Effect.fn("effect-machine.actorSystem.register")(function* (id, actor) {
|
|
@@ -558,6 +554,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
558
554
|
hydrated: spawnOptions?.hydrate !== void 0,
|
|
559
555
|
supervision: spawnOptions?.supervision,
|
|
560
556
|
lifecycle: spawnOptions?.lifecycle,
|
|
557
|
+
inspect: spawnOptions?.inspect,
|
|
561
558
|
onRestart
|
|
562
559
|
});
|
|
563
560
|
actorRef = actor;
|
|
@@ -606,7 +603,7 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
606
603
|
yield* actor.stop;
|
|
607
604
|
return true;
|
|
608
605
|
});
|
|
609
|
-
|
|
606
|
+
const system = ActorSystem.of({
|
|
610
607
|
spawn,
|
|
611
608
|
get,
|
|
612
609
|
watch,
|
|
@@ -624,8 +621,16 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
624
621
|
return () => {
|
|
625
622
|
eventListeners.delete(fn);
|
|
626
623
|
};
|
|
624
|
+
},
|
|
625
|
+
inspect: (inspector) => {
|
|
626
|
+
systemInspectors.add(inspector);
|
|
627
|
+
return () => {
|
|
628
|
+
systemInspectors.delete(inspector);
|
|
629
|
+
};
|
|
627
630
|
}
|
|
628
631
|
});
|
|
632
|
+
systemInspectorsBySystem.set(system, systemInspectors);
|
|
633
|
+
return system;
|
|
629
634
|
});
|
|
630
635
|
/**
|
|
631
636
|
* Create an ActorSystem instance. Must be run in a Scope.
|
|
@@ -55,6 +55,7 @@ const EntityMachine = { layer: (entity, machine, ...optionsArgument) => {
|
|
|
55
55
|
const versionRef = yield* Ref.make(persistCtx.initialVersion);
|
|
56
56
|
const computedInitial = initialState ?? machineInitial;
|
|
57
57
|
const stateRef = yield* SubscriptionRef.make(computedInitial);
|
|
58
|
+
const latestTransitionRef = yield* SubscriptionRef.make(void 0);
|
|
58
59
|
const stoppedRef = yield* Ref.make(false);
|
|
59
60
|
const eventQueue = yield* Queue.unbounded();
|
|
60
61
|
let hooks = void 0;
|
|
@@ -65,6 +66,7 @@ const EntityMachine = { layer: (entity, machine, ...optionsArgument) => {
|
|
|
65
66
|
childIdPrefix: `${entityId}/`,
|
|
66
67
|
cellResources: {
|
|
67
68
|
stateRef,
|
|
69
|
+
latestTransitionRef,
|
|
68
70
|
stoppedRef,
|
|
69
71
|
eventQueue
|
|
70
72
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { DeferReplyResult, ReplyResult } from "./internal/utils.js";
|
|
2
2
|
import { Event, MachineEventSchema, MachineStateSchema, ReplyFields, State } from "./schema.js";
|
|
3
3
|
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, NoReplyError, PersistenceError, VersionConflictError } from "./errors.js";
|
|
4
|
+
import { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, GuardEvent, InspectionEvent, Inspector, InspectorHandler, InspectorService, OperationEvent, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
4
5
|
import { ActorExit, DefectPhase, Supervision } from "./supervision.js";
|
|
5
6
|
import { Durability, DurabilityCommit, FinalContext, GuardPredicate, HandlerContext, InputMakeConfig, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, ReplayOptions, SpawnOptions, StateHandlerContext, TaskOptions, TimeoutConfig, machine_d_exports } from "./machine.js";
|
|
6
7
|
import { ProcessEventResult } from "./internal/transition.js";
|
|
7
8
|
import { ActorClient, ActorLifecycle, ActorRef, ActorRefSync, ActorScope, ActorSystem, ActorSystemKey, ActorSystemService, Default, SystemEvent, SystemEventListener, SystemSpawnOptions, TransitionInfo, actorSystemKey } from "./actor.js";
|
|
8
9
|
import { InputTestHarnessOptions, SimulationOptions, SimulationResult, TestHarness, TestHarnessOptions, assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
9
|
-
|
|
10
|
-
export { type ActorClient, ActorExit, type ActorExit as ActorExitType, type ActorLifecycle, type ActorRef, type ActorRefSync, ActorScope, ActorStoppedError, type ActorSystemService as ActorSystem, Default as ActorSystemDefault, ActorSystemKey, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type DefectPhase, type DeferReplyResult, DuplicateActorError, type Durability, type DurabilityCommit, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type FinalContext, type GuardEvent, type GuardPredicate, type HandlerContext, type InputMakeConfig, type InputTestHarnessOptions, type InspectionEvent, type InspectorService as Inspector, type InspectorHandler, type InspectorHub, Inspector as InspectorService, InvalidSchemaError, type Lifecycle, machine_d_exports as Machine, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, NoReplyError, type OperationEvent, PersistenceError, type ProcessEventResult, type Recovery, type RecoveryContext, type ReplayOptions, type ReplyFields, type ReplyResult, type SimulationOptions, type SimulationResult, type SpawnEvent, type SpawnOptions, State, type StateHandlerContext, type StopEvent, Supervision, type SystemEvent, type SystemEventListener, type SystemSpawnOptions, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TimeoutConfig, type TracingInspectorOptions, type TransitionEvent, type TransitionInfo, VersionConflictError, actorSystemKey, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, makeInspectorHub, simulate, tracingInspector };
|
|
10
|
+
export { type ActorClient, ActorExit, type ActorExit as ActorExitType, type ActorLifecycle, type ActorRef, type ActorRefSync, ActorScope, ActorStoppedError, type ActorSystemService as ActorSystem, Default as ActorSystemDefault, ActorSystemKey, ActorSystem as ActorSystemService, type AnyInspectionEvent, AssertionError, type DefectPhase, type DeferReplyResult, DuplicateActorError, type Durability, type DurabilityCommit, type EffectEvent, type ErrorEvent, Event, type EventReceivedEvent, type FinalContext, type GuardEvent, type GuardPredicate, type HandlerContext, type InputMakeConfig, type InputTestHarnessOptions, type InspectionEvent, type InspectorService as Inspector, type InspectorHandler, Inspector as InspectorService, InvalidSchemaError, type Lifecycle, machine_d_exports as Machine, type MachineEventSchema, type MachineRef, type MachineStateSchema, type Machine as MachineType, type MakeConfig, MissingMatchHandlerError, NoReplyError, type OperationEvent, PersistenceError, type ProcessEventResult, type Recovery, type RecoveryContext, type ReplayOptions, type ReplyFields, type ReplyResult, type SimulationOptions, type SimulationResult, type SpawnEvent, type SpawnOptions, State, type StateHandlerContext, type StopEvent, Supervision, type SystemEvent, type SystemEventListener, type SystemSpawnOptions, type TaskEvent, type TaskOptions, type TestHarness, type TestHarnessOptions, type TimeoutConfig, type TracingInspectorOptions, type TransitionEvent, type TransitionInfo, VersionConflictError, actorSystemKey, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, NoReplyError, PersistenceError, VersionConflictError } from "./errors.js";
|
|
2
2
|
import { Event, State } from "./schema.js";
|
|
3
|
-
import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect,
|
|
3
|
+
import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
4
4
|
import { ActorExit, Supervision } from "./supervision.js";
|
|
5
5
|
import { ActorScope, ActorSystem, ActorSystemKey, Default, actorSystemKey } from "./actor.js";
|
|
6
6
|
import { machine_exports } from "./machine.js";
|
|
7
7
|
import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
8
|
-
export { ActorExit, ActorScope, ActorStoppedError, Default as ActorSystemDefault, ActorSystemKey, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, NoReplyError, PersistenceError, State, Supervision, VersionConflictError, actorSystemKey, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect,
|
|
8
|
+
export { ActorExit, ActorScope, ActorStoppedError, Default as ActorSystemDefault, ActorSystemKey, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, NoReplyError, PersistenceError, State, Supervision, VersionConflictError, actorSystemKey, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
package/dist/inspection.d.ts
CHANGED
|
@@ -124,13 +124,6 @@ type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Ef
|
|
|
124
124
|
interface InspectorService<S, E> {
|
|
125
125
|
readonly onInspect: InspectorHandler<S, E>;
|
|
126
126
|
}
|
|
127
|
-
/**
|
|
128
|
-
* Dynamic Inspector fan-out for applications that load inspection consumers after actors start.
|
|
129
|
-
*/
|
|
130
|
-
interface InspectorHub<S, E> {
|
|
131
|
-
readonly inspector: InspectorService<S, E>;
|
|
132
|
-
readonly register: (inspector: InspectorService<S, E>) => () => void;
|
|
133
|
-
}
|
|
134
127
|
declare const Inspector_base: Context.ServiceClass<Inspector, "effect-machine/inspection/Inspector", InspectorService<any, any>>;
|
|
135
128
|
/**
|
|
136
129
|
* Inspector service tag - optional service for machine introspection
|
|
@@ -156,17 +149,6 @@ declare const makeInspectorEffect: <S = {
|
|
|
156
149
|
readonly _tag: string;
|
|
157
150
|
}>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void>) => InspectorService<ResolveType<S>, ResolveType<E>>;
|
|
158
151
|
declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<InspectorService<S, E>>) => InspectorService<S, E>;
|
|
159
|
-
/**
|
|
160
|
-
* Create an Inspector that accepts sinks throughout its lifetime.
|
|
161
|
-
*
|
|
162
|
-
* Provide `hub.inspector` before actor startup. Consumers can then register and unregister sinks
|
|
163
|
-
* without restarting the actor. A sink failure does not affect the actor or other sinks.
|
|
164
|
-
*/
|
|
165
|
-
declare const makeInspectorHub: <S = {
|
|
166
|
-
readonly _tag: string;
|
|
167
|
-
}, E = {
|
|
168
|
-
readonly _tag: string;
|
|
169
|
-
}>() => InspectorHub<ResolveType<S>, ResolveType<E>>;
|
|
170
152
|
interface TracingInspectorOptions<S, E> {
|
|
171
153
|
readonly spanName?: string | ((event: InspectionEvent<S, E>) => string);
|
|
172
154
|
readonly attributes?: (event: InspectionEvent<S, E>) => Readonly<Record<string, string | number | boolean>>;
|
|
@@ -194,4 +176,4 @@ declare const collectingInspector: <S extends {
|
|
|
194
176
|
readonly _tag: string;
|
|
195
177
|
}>(events: InspectionEvent<S, E>[]) => InspectorService<S, E>;
|
|
196
178
|
//#endregion
|
|
197
|
-
export { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, GuardEvent, InspectionEvent, Inspector, InspectorHandler,
|
|
179
|
+
export { AnyInspectionEvent, EffectEvent, ErrorEvent, EventReceivedEvent, GuardEvent, InspectionEvent, Inspector, InspectorHandler, InspectorService, OperationEvent, SpawnEvent, StopEvent, TaskEvent, TracingInspectorOptions, TransitionEvent, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
|
package/dist/inspection.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runInspectors } from "./internal/inspection.js";
|
|
1
2
|
import { Context, Effect, Option } from "effect";
|
|
2
3
|
//#region src/inspection.ts
|
|
3
4
|
/**
|
|
@@ -15,39 +16,7 @@ var Inspector = class extends Context.Service()("effect-machine/inspection/Inspe
|
|
|
15
16
|
*/
|
|
16
17
|
const makeInspector = (onInspect) => ({ onInspect });
|
|
17
18
|
const makeInspectorEffect = (onInspect) => ({ onInspect });
|
|
18
|
-
const
|
|
19
|
-
const result = inspector.onInspect(event);
|
|
20
|
-
if (Effect.isEffect(result)) return result;
|
|
21
|
-
return Effect.void;
|
|
22
|
-
});
|
|
23
|
-
const combineInspectors = (...inspectors) => ({ onInspect: (event) => Effect.forEach(inspectors, (inspector) => inspectionEffect(inspector, event).pipe(Effect.ignoreCause), {
|
|
24
|
-
concurrency: 16,
|
|
25
|
-
discard: true
|
|
26
|
-
}) });
|
|
27
|
-
/**
|
|
28
|
-
* Create an Inspector that accepts sinks throughout its lifetime.
|
|
29
|
-
*
|
|
30
|
-
* Provide `hub.inspector` before actor startup. Consumers can then register and unregister sinks
|
|
31
|
-
* without restarting the actor. A sink failure does not affect the actor or other sinks.
|
|
32
|
-
*/
|
|
33
|
-
const makeInspectorHub = () => {
|
|
34
|
-
const inspectorByRegistration = /* @__PURE__ */ new Map();
|
|
35
|
-
const inspector = { onInspect: (event) => Effect.forEach(Array.from(inspectorByRegistration.values()), (registeredInspector) => inspectionEffect(registeredInspector, event).pipe(Effect.ignoreCause), {
|
|
36
|
-
concurrency: 16,
|
|
37
|
-
discard: true
|
|
38
|
-
}) };
|
|
39
|
-
const register = (registeredInspector) => {
|
|
40
|
-
const registration = Symbol();
|
|
41
|
-
inspectorByRegistration.set(registration, registeredInspector);
|
|
42
|
-
return () => {
|
|
43
|
-
inspectorByRegistration.delete(registration);
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
return {
|
|
47
|
-
inspector,
|
|
48
|
-
register
|
|
49
|
-
};
|
|
50
|
-
};
|
|
19
|
+
const combineInspectors = (...inspectors) => ({ onInspect: (event) => runInspectors(inspectors, event) });
|
|
51
20
|
const inspectionSpanName = (event) => {
|
|
52
21
|
switch (event.type) {
|
|
53
22
|
case "@machine.spawn": return `Machine.inspect ${event.initialState._tag}`;
|
|
@@ -181,4 +150,4 @@ const collectingInspector = (events) => ({ onInspect: (event) => {
|
|
|
181
150
|
events.push(event);
|
|
182
151
|
} });
|
|
183
152
|
//#endregion
|
|
184
|
-
export { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect,
|
|
153
|
+
export { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector };
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { InspectionEvent, InspectorService } from "../inspection.js";
|
|
1
2
|
import { ProcessEventHooks } from "./transition.js";
|
|
2
|
-
import {
|
|
3
|
+
import { Effect } from "effect";
|
|
3
4
|
//#region src/internal/inspection.d.ts
|
|
5
|
+
type Tagged = {
|
|
6
|
+
readonly _tag: string;
|
|
7
|
+
};
|
|
8
|
+
/** Run one inspector without letting its failure affect the machine. */
|
|
9
|
+
declare const runInspector: <S, E>(inspector: InspectorService<S, E>, event: InspectionEvent<S, E>) => Effect.Effect<void, never, never>;
|
|
10
|
+
/** Run inspectors in order and isolate each failure. */
|
|
11
|
+
declare const runInspectors: <S, E>(inspectors: Iterable<InspectorService<S, E>>, event: InspectionEvent<S, E>) => Effect.Effect<void, never, never>;
|
|
12
|
+
/** Build the actor-owned dispatcher for local and system inspection. */
|
|
13
|
+
declare const makeInspectionDispatcher: <S extends Tagged, E extends Tagged>(localInspector: InspectorService<S, E> | undefined, systemInspectors: ReadonlySet<InspectorService<Tagged, Tagged>>) => InspectorService<S, E>;
|
|
4
14
|
/** Adapt the Inspector service to the transition kernel. */
|
|
5
15
|
declare const makeInspectionHooks: <S, E>(actorId: string, inspector: InspectorService<S, E>, getGeneration?: () => number) => ProcessEventHooks<S, E>;
|
|
6
16
|
//#endregion
|
|
7
|
-
export { makeInspectionHooks };
|
|
17
|
+
export { makeInspectionDispatcher, makeInspectionHooks, runInspector, runInspectors };
|
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
import { Cause, Clock, Effect } from "effect";
|
|
2
2
|
//#region src/internal/inspection.ts
|
|
3
|
+
const inspectorActivity = /* @__PURE__ */ new WeakMap();
|
|
4
|
+
/** Run one inspector without letting its failure affect the machine. */
|
|
5
|
+
const runInspector = Effect.fn("effect-machine.runInspector")(function* (inspector, event) {
|
|
6
|
+
const result = yield* Effect.try(() => inspector.onInspect(event)).pipe(Effect.orElseSucceed(() => void 0));
|
|
7
|
+
if (Effect.isEffect(result)) yield* result.pipe(Effect.ignoreCause);
|
|
8
|
+
});
|
|
9
|
+
/** Run inspectors in order and isolate each failure. */
|
|
10
|
+
const runInspectors = Effect.fn("effect-machine.runInspectors")(function* (inspectors, event) {
|
|
11
|
+
for (const inspector of inspectors) yield* runInspector(inspector, event);
|
|
12
|
+
});
|
|
13
|
+
/** Build the actor-owned dispatcher for local and system inspection. */
|
|
14
|
+
const makeInspectionDispatcher = (localInspector, systemInspectors) => {
|
|
15
|
+
const inspector = { onInspect: (event) => Effect.gen(function* () {
|
|
16
|
+
if (localInspector !== void 0) yield* runInspector(localInspector, event);
|
|
17
|
+
for (const systemInspector of systemInspectors) yield* runInspector(systemInspector, event);
|
|
18
|
+
}) };
|
|
19
|
+
inspectorActivity.set(inspector, () => localInspector !== void 0 || systemInspectors.size > 0);
|
|
20
|
+
return inspector;
|
|
21
|
+
};
|
|
3
22
|
/**
|
|
4
23
|
* Emit an inspection event with timestamp from Clock.
|
|
5
24
|
* @internal
|
|
6
25
|
*/
|
|
7
26
|
const emitWithTimestamp = Effect.fn("effect-machine.emitWithTimestamp")(function* (inspector, makeEvent) {
|
|
8
|
-
if (inspector === void 0) return;
|
|
27
|
+
if (inspector === void 0 || inspectorActivity.get(inspector)?.() === false) return;
|
|
9
28
|
const event = makeEvent(yield* Clock.currentTimeMillis);
|
|
10
|
-
|
|
11
|
-
if (Effect.isEffect(result)) yield* result.pipe(Effect.ignoreCause);
|
|
29
|
+
yield* runInspector(inspector, event);
|
|
12
30
|
});
|
|
13
31
|
/** Adapt the Inspector service to the transition kernel. */
|
|
14
32
|
const makeInspectionHooks = (actorId, inspector, getGeneration = () => 0) => ({
|
|
@@ -60,4 +78,4 @@ const makeInspectionHooks = (actorId, inspector, getGeneration = () => 0) => ({
|
|
|
60
78
|
}))
|
|
61
79
|
});
|
|
62
80
|
//#endregion
|
|
63
|
-
export { emitWithTimestamp, makeInspectionHooks };
|
|
81
|
+
export { emitWithTimestamp, makeInspectionDispatcher, makeInspectionHooks, runInspector, runInspectors };
|
package/dist/internal/runtime.js
CHANGED
|
@@ -55,7 +55,7 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
55
55
|
const generation = config.generation ?? 0;
|
|
56
56
|
const services = yield* Effect.context();
|
|
57
57
|
const fork = Effect.runForkWith(services);
|
|
58
|
-
const { stateRef, stoppedRef, eventQueue } = config.cellResources;
|
|
58
|
+
const { stateRef, latestTransitionRef, stoppedRef, eventQueue } = config.cellResources;
|
|
59
59
|
const pendingRequests = /* @__PURE__ */ new Set();
|
|
60
60
|
const exitDeferred = yield* Deferred.make();
|
|
61
61
|
const actorScope = yield* Scope.make();
|
|
@@ -72,6 +72,8 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
72
72
|
let spawn = defaultSpawn;
|
|
73
73
|
if (onChildSpawned !== void 0) spawn = (childId, childMachine) => defaultSpawn(childId, childMachine).pipe(Effect.tap((child) => onChildSpawned(childId, child)));
|
|
74
74
|
const self = {
|
|
75
|
+
state: stateRef,
|
|
76
|
+
latestTransition: latestTransitionRef,
|
|
75
77
|
send: selfSend,
|
|
76
78
|
spawn,
|
|
77
79
|
reply: (value) => Effect.sync(() => {
|
|
@@ -117,6 +119,12 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
117
119
|
else initialResult = initialProcessing;
|
|
118
120
|
if (initialResult.transitioned) {
|
|
119
121
|
yield* SubscriptionRef.set(stateRef, initialResult.newState);
|
|
122
|
+
const latest = initialResult.transitions.at(-1);
|
|
123
|
+
if (latest !== void 0) yield* SubscriptionRef.set(latestTransitionRef, {
|
|
124
|
+
fromState: latest.previousState,
|
|
125
|
+
toState: latest.newState,
|
|
126
|
+
event: latest.event
|
|
127
|
+
});
|
|
120
128
|
if (lifecycle?.onStateChange !== void 0) {
|
|
121
129
|
const stateChange = lifecycle.onStateChange(initialResult, initEvent);
|
|
122
130
|
if (isEffect(stateChange)) yield* stateChange;
|
|
@@ -164,7 +172,7 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
164
172
|
return Effect.void;
|
|
165
173
|
})), Effect.asVoid)
|
|
166
174
|
};
|
|
167
|
-
const loopFiber = yield* runtimeEventLoop(machine, stateRef, eventQueue, pendingRequests, stoppedRef, self, stateScopeRef, actorId, generation, system, exitDeferred, augmentedHooks, deferredReplyRef, lifecycle, fork).pipe(Effect.provide(services), Effect.forkDetach);
|
|
175
|
+
const loopFiber = yield* runtimeEventLoop(machine, stateRef, latestTransitionRef, eventQueue, pendingRequests, stoppedRef, self, stateScopeRef, actorId, generation, system, exitDeferred, augmentedHooks, deferredReplyRef, lifecycle, fork).pipe(Effect.provide(services), Effect.forkDetach);
|
|
168
176
|
loopFiberRef.current = loopFiber;
|
|
169
177
|
if (backgroundFibers.length > 0) yield* Effect.raceAll(backgroundFibers.map((fiber) => Fiber.await(fiber).pipe(Effect.flatMap((exit) => {
|
|
170
178
|
if (exit._tag === "Failure" && !Cause.hasInterruptsOnly(exit.cause)) return setExit(RuntimeExit.Defect(exit.cause, "background")).pipe(Effect.andThen(Ref.set(stoppedRef, true)), Effect.andThen(Fiber.interrupt(loopFiber)));
|
|
@@ -190,7 +198,7 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
190
198
|
}).pipe(Effect.asVoid);
|
|
191
199
|
if (config.skipFinalizer !== true) yield* Effect.addFinalizer(() => stop);
|
|
192
200
|
return {
|
|
193
|
-
...makeHandle(actorId, stateRef, stoppedRef, eventQueue, pendingRequests, exitDeferred),
|
|
201
|
+
...makeHandle(actorId, stateRef, latestTransitionRef, stoppedRef, eventQueue, pendingRequests, exitDeferred),
|
|
194
202
|
stop: stop.pipe(Effect.provide(services)),
|
|
195
203
|
start: start.pipe(Effect.provide(services))
|
|
196
204
|
};
|
|
@@ -199,7 +207,7 @@ const createRuntime = Effect.fn("effect-machine.runtime.create")(function* (mach
|
|
|
199
207
|
* Build the runtime handle.
|
|
200
208
|
* Shared between initial-final and normal paths.
|
|
201
209
|
*/
|
|
202
|
-
const makeHandle = (actorId, stateRef, stoppedRef, eventQueue, pendingRequests, exitDeferred) => {
|
|
210
|
+
const makeHandle = (actorId, stateRef, latestTransitionRef, stoppedRef, eventQueue, pendingRequests, exitDeferred) => {
|
|
203
211
|
const track = (deferred, settle) => {
|
|
204
212
|
pendingRequests.add(settle);
|
|
205
213
|
return Deferred.await(deferred).pipe(Effect.ensuring(Effect.sync(() => pendingRequests.delete(settle))));
|
|
@@ -261,6 +269,7 @@ const makeHandle = (actorId, stateRef, stoppedRef, eventQueue, pendingRequests,
|
|
|
261
269
|
},
|
|
262
270
|
getState: SubscriptionRef.get(stateRef),
|
|
263
271
|
stateRef,
|
|
272
|
+
latestTransitionRef,
|
|
264
273
|
stop: Effect.void,
|
|
265
274
|
start: Effect.void,
|
|
266
275
|
settlePendingRequests: settlePendingRequests(pendingRequests, actorId),
|
|
@@ -272,7 +281,7 @@ const settlePendingRequests = (pendingRequests, actorId) => Effect.gen(function*
|
|
|
272
281
|
for (const settle of pendingRequests) yield* settle(error);
|
|
273
282
|
pendingRequests.clear();
|
|
274
283
|
});
|
|
275
|
-
const runtimeEventLoop = Effect.fn("effect-machine.runtime.eventLoop")(function* (machine, stateRef, eventQueue, pendingRequests, stoppedRef, self, stateScopeRef, actorId, generation, system, exitDeferred, hooks, deferredReplyRef, lifecycle, fork) {
|
|
284
|
+
const runtimeEventLoop = Effect.fn("effect-machine.runtime.eventLoop")(function* (machine, stateRef, latestTransitionRef, eventQueue, pendingRequests, stoppedRef, self, stateScopeRef, actorId, generation, system, exitDeferred, hooks, deferredReplyRef, lifecycle, fork) {
|
|
276
285
|
const forkEffect = fork ?? Effect.runFork;
|
|
277
286
|
/** Set the exit deferred exactly once. */
|
|
278
287
|
const setExit = (exit) => Deferred.succeed(exitDeferred, exit).pipe(Effect.asVoid);
|
|
@@ -320,7 +329,15 @@ const runtimeEventLoop = Effect.fn("effect-machine.runtime.eventLoop")(function*
|
|
|
320
329
|
let result;
|
|
321
330
|
if (isEffect(processing)) result = yield* processing;
|
|
322
331
|
else result = processing;
|
|
323
|
-
if (result.transitioned)
|
|
332
|
+
if (result.transitioned) {
|
|
333
|
+
yield* SubscriptionRef.set(stateRef, result.newState);
|
|
334
|
+
const latest = result.transitions.at(-1);
|
|
335
|
+
if (latest !== void 0) yield* SubscriptionRef.set(latestTransitionRef, {
|
|
336
|
+
fromState: latest.previousState,
|
|
337
|
+
toState: latest.newState,
|
|
338
|
+
event: latest.event
|
|
339
|
+
});
|
|
340
|
+
}
|
|
324
341
|
if (lifecycle?.onStateChange !== void 0 && result.transitioned) {
|
|
325
342
|
const stateChange = lifecycle.onStateChange(result, event);
|
|
326
343
|
if (isEffect(stateChange)) yield* stateChange;
|
package/dist/internal/utils.js
CHANGED
|
@@ -70,7 +70,8 @@ const stubSystem = {
|
|
|
70
70
|
get actors() {
|
|
71
71
|
return /* @__PURE__ */ new Map();
|
|
72
72
|
},
|
|
73
|
-
subscribe: () => () => {}
|
|
73
|
+
subscribe: () => () => {},
|
|
74
|
+
inspect: () => () => {}
|
|
74
75
|
};
|
|
75
76
|
//#endregion
|
|
76
77
|
export { INTERNAL_ENTER_EVENT, INTERNAL_INIT_EVENT, getTag, isDeferReplyResult, isEffect, isReplyResult, makeDeferReply, makeReply, stubSystem };
|
package/dist/machine.d.ts
CHANGED
|
@@ -2,16 +2,21 @@ import { DeferReplyResult, ReplyResult, TransitionResult, makeDeferReply, makeRe
|
|
|
2
2
|
import { BrandedEvent, BrandedState, ExtractReply, TaggedOrConstructor } from "./internal/brands.js";
|
|
3
3
|
import { MachineEventSchema, MachineStateSchema, VariantsUnion } from "./schema.js";
|
|
4
4
|
import { ActorStoppedError, DuplicateActorError } from "./errors.js";
|
|
5
|
+
import { InspectorService } from "./inspection.js";
|
|
5
6
|
import { Supervision } from "./supervision.js";
|
|
6
|
-
import { ActorRef, ActorSystemService } from "./actor.js";
|
|
7
|
-
import { Duration, Effect, Option, Schema, Scope } from "effect";
|
|
7
|
+
import { ActorRef, ActorSystemService, TransitionInfo } from "./actor.js";
|
|
8
|
+
import { Duration, Effect, Option, Schema, Scope, SubscriptionRef } from "effect";
|
|
8
9
|
declare namespace machine_d_exports {
|
|
9
10
|
export { DeferReplyResult, Durability, DurabilityCommit, FinalContext, GuardPredicate, HandlerContext, InputMakeConfig, Lifecycle, Machine, MachineRef, MakeConfig, Recovery, RecoveryContext, ReplayOptions, ReplyResult, SpawnOptions, StateEffectHandler, StateHandlerContext, TaskOptions, TimeoutConfig, TransitionHandler, deferReply, make, replay, reply, run, scoped, spawn };
|
|
10
11
|
}
|
|
11
12
|
/**
|
|
12
13
|
* Self reference for sending events back to the machine
|
|
13
14
|
*/
|
|
14
|
-
interface MachineRef<Event> {
|
|
15
|
+
interface MachineRef<Event, State = never> {
|
|
16
|
+
/** Actor-owned current state. Consumers must treat this ref as read-only. */
|
|
17
|
+
readonly state: SubscriptionRef.SubscriptionRef<State>;
|
|
18
|
+
/** Actor-owned latest accepted transition. Consumers must treat this ref as read-only. */
|
|
19
|
+
readonly latestTransition: SubscriptionRef.SubscriptionRef<TransitionInfo<State, Event> | undefined>;
|
|
15
20
|
readonly send: (event: Event) => Effect.Effect<void>;
|
|
16
21
|
readonly spawn: <S2 extends {
|
|
17
22
|
readonly _tag: string;
|
|
@@ -40,7 +45,7 @@ interface StateHandlerContext<State, Event> {
|
|
|
40
45
|
readonly generation: number;
|
|
41
46
|
readonly state: State;
|
|
42
47
|
readonly event: Event;
|
|
43
|
-
readonly self: MachineRef<Event>;
|
|
48
|
+
readonly self: MachineRef<Event, State>;
|
|
44
49
|
readonly system: ActorSystemService;
|
|
45
50
|
}
|
|
46
51
|
/**
|
|
@@ -325,6 +330,7 @@ type SpawnOptions<S, E, Input> = {
|
|
|
325
330
|
readonly hydrate?: S;
|
|
326
331
|
readonly supervision?: Supervision.Policy;
|
|
327
332
|
readonly lifecycle?: Lifecycle<S, E>;
|
|
333
|
+
readonly inspect?: InspectorService<S, E>;
|
|
328
334
|
} & ([Input] extends [void] ? {
|
|
329
335
|
readonly input?: never;
|
|
330
336
|
} : {
|
|
@@ -339,6 +345,7 @@ type SpawnOptions<S, E, Input> = {
|
|
|
339
345
|
*
|
|
340
346
|
* // With lifecycle (recovery + durability)
|
|
341
347
|
* const actor = yield* Machine.spawn(machine, {
|
|
348
|
+
* inspect: consoleInspector(),
|
|
342
349
|
* lifecycle: {
|
|
343
350
|
* recovery: { resolve: (ctx) => storage.get("actor-state") },
|
|
344
351
|
* durability: { save: (commit) => storage.set("actor-state", commit.nextState) },
|
package/dist/machine.js
CHANGED
|
@@ -443,7 +443,8 @@ const spawnImpl = Effect.fn("effect-machine.spawn")(function* (machine, idOrOpti
|
|
|
443
443
|
machineInitial,
|
|
444
444
|
hydrated: opts?.hydrate !== void 0,
|
|
445
445
|
supervision: opts?.supervision,
|
|
446
|
-
lifecycle: opts?.lifecycle
|
|
446
|
+
lifecycle: opts?.lifecycle,
|
|
447
|
+
inspect: opts?.inspect
|
|
447
448
|
});
|
|
448
449
|
const maybeScope = yield* Effect.serviceOption(ActorScope);
|
|
449
450
|
if (Option.isSome(maybeScope)) yield* Scope.addFinalizer(maybeScope.value, actor.stop);
|
|
@@ -458,6 +459,7 @@ const spawnImpl = Effect.fn("effect-machine.spawn")(function* (machine, idOrOpti
|
|
|
458
459
|
*
|
|
459
460
|
* // With lifecycle (recovery + durability)
|
|
460
461
|
* const actor = yield* Machine.spawn(machine, {
|
|
462
|
+
* inspect: consoleInspector(),
|
|
461
463
|
* lifecycle: {
|
|
462
464
|
* recovery: { resolve: (ctx) => storage.get("actor-state") },
|
|
463
465
|
* durability: { save: (commit) => storage.set("actor-state", commit.nextState) },
|