effect-machine 0.13.0 → 0.15.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 +19 -11
- package/dist/actor.d.ts +18 -6
- package/dist/actor.js +151 -61
- package/dist/cluster/entity-machine.d.ts +1 -1
- package/dist/cluster/entity-machine.js +2 -1
- package/dist/cluster/to-entity.d.ts +1 -1
- package/dist/errors.d.ts +9 -2
- package/dist/errors.js +8 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/internal/runtime.d.ts +21 -2
- package/dist/internal/runtime.js +64 -56
- package/dist/internal/transition.d.ts +9 -9
- package/dist/internal/transition.js +3 -5
- package/dist/machine.d.ts +129 -135
- package/dist/machine.js +97 -112
- package/dist/schema.d.ts +17 -1
- package/dist/schema.js +10 -0
- package/dist/slot.d.ts +112 -86
- package/dist/slot.js +92 -59
- package/dist/testing.d.ts +16 -16
- package/dist/testing.js +3 -3
- package/package.json +3 -3
- package/v3/dist/actor.d.ts +25 -12
- package/v3/dist/actor.js +174 -89
- package/v3/dist/cluster/entity-machine.d.ts +1 -1
- package/v3/dist/cluster/entity-machine.js +1 -0
- package/v3/dist/cluster/to-entity.d.ts +1 -1
- package/v3/dist/errors.d.ts +12 -3
- package/v3/dist/errors.js +10 -4
- package/v3/dist/index.d.ts +6 -6
- package/v3/dist/index.js +2 -2
- package/v3/dist/inspection.d.ts +3 -22
- package/v3/dist/inspection.js +1 -15
- package/v3/dist/internal/brands.d.ts +4 -8
- package/v3/dist/internal/inspection.js +1 -1
- package/v3/dist/internal/runtime.d.ts +27 -8
- package/v3/dist/internal/runtime.js +91 -61
- package/v3/dist/internal/transition.d.ts +10 -10
- package/v3/dist/internal/transition.js +8 -10
- package/v3/dist/internal/utils.js +5 -1
- package/v3/dist/machine.d.ts +160 -120
- package/v3/dist/machine.js +118 -115
- package/v3/dist/schema.d.ts +25 -11
- package/v3/dist/schema.js +18 -5
- package/v3/dist/slot.d.ts +112 -86
- package/v3/dist/slot.js +92 -59
- package/v3/dist/testing.d.ts +16 -16
- package/v3/dist/testing.js +7 -7
package/v3/dist/actor.js
CHANGED
|
@@ -12,7 +12,7 @@ import { Cause, Context, Deferred, Effect, Exit, Fiber, Layer, MutableHashMap, O
|
|
|
12
12
|
* Combines:
|
|
13
13
|
* - ActorRef interface (running actor handle)
|
|
14
14
|
* - ActorSystem service (spawn/stop/get actors)
|
|
15
|
-
* - Actor creation
|
|
15
|
+
* - Actor creation and event loop
|
|
16
16
|
*/
|
|
17
17
|
/**
|
|
18
18
|
* ActorSystem service tag
|
|
@@ -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,
|
|
@@ -163,60 +164,116 @@ const buildActorRefCore = (id, machine, stateRef, eventQueueRef, stoppedRef, lis
|
|
|
163
164
|
children: childrenMap
|
|
164
165
|
};
|
|
165
166
|
};
|
|
167
|
+
/** Build ProcessEventHooks from an inspector */
|
|
168
|
+
const buildInspectionHooks = (actorId, inspector) => ({
|
|
169
|
+
onSpawnEffect: (state) => emitWithTimestamp(inspector, (timestamp) => ({
|
|
170
|
+
type: "@machine.effect",
|
|
171
|
+
actorId,
|
|
172
|
+
effectType: "spawn",
|
|
173
|
+
state,
|
|
174
|
+
timestamp
|
|
175
|
+
})),
|
|
176
|
+
onTransition: (from, to, ev) => emitWithTimestamp(inspector, (timestamp) => ({
|
|
177
|
+
type: "@machine.transition",
|
|
178
|
+
actorId,
|
|
179
|
+
fromState: from,
|
|
180
|
+
toState: to,
|
|
181
|
+
event: ev,
|
|
182
|
+
timestamp
|
|
183
|
+
})),
|
|
184
|
+
onError: (info) => emitWithTimestamp(inspector, (timestamp) => ({
|
|
185
|
+
type: "@machine.error",
|
|
186
|
+
actorId,
|
|
187
|
+
phase: info.phase,
|
|
188
|
+
state: info.state,
|
|
189
|
+
event: info.event,
|
|
190
|
+
error: Cause.pretty(info.cause),
|
|
191
|
+
timestamp
|
|
192
|
+
}))
|
|
193
|
+
});
|
|
194
|
+
/**
|
|
195
|
+
* Resolve actor system from context, creating an implicit one if none exists.
|
|
196
|
+
* @internal
|
|
197
|
+
*/
|
|
198
|
+
const resolveActorSystem = Effect.fn("effect-machine.resolveActorSystem")(function* () {
|
|
199
|
+
const existingSystem = yield* Effect.serviceOption(ActorSystem);
|
|
200
|
+
if (Option.isSome(existingSystem)) return {
|
|
201
|
+
system: existingSystem.value,
|
|
202
|
+
implicitSystemScope: void 0
|
|
203
|
+
};
|
|
204
|
+
const scope = yield* Scope.make();
|
|
205
|
+
return {
|
|
206
|
+
system: yield* make().pipe(Effect.provideService(Scope.Scope, scope)),
|
|
207
|
+
implicitSystemScope: scope
|
|
208
|
+
};
|
|
209
|
+
});
|
|
210
|
+
/**
|
|
211
|
+
* Run the supervision loop for a supervised actor.
|
|
212
|
+
* Observes exit deferred, applies restart policy, resets cell resources on restart.
|
|
213
|
+
* @internal
|
|
214
|
+
*/
|
|
215
|
+
const runSupervisionLoop = (params) => Effect.gen(function* () {
|
|
216
|
+
const driver = yield* Schedule.driver(params.supervision.schedule);
|
|
217
|
+
let generation = 0;
|
|
218
|
+
while (true) {
|
|
219
|
+
const currentRuntime = params.runtimeRef.current;
|
|
220
|
+
if (currentRuntime === void 0) return;
|
|
221
|
+
const generationExit = yield* Deferred.await(currentRuntime.exitDeferred);
|
|
222
|
+
if (generationExit._tag !== "Defect") {
|
|
223
|
+
yield* Deferred.succeed(params.terminalExitDeferred, generationExit);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (params.supervision.shouldRestart !== void 0 && !params.supervision.shouldRestart(generationExit)) {
|
|
227
|
+
yield* Deferred.succeed(params.terminalExitDeferred, generationExit);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if ((yield* driver.next(generationExit).pipe(Effect.exit))._tag === "Failure") {
|
|
231
|
+
yield* Deferred.succeed(params.terminalExitDeferred, generationExit);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
let restartState = params.machine.initial;
|
|
235
|
+
if (params.lifecycle?.recovery !== void 0) {
|
|
236
|
+
const resolved = yield* params.lifecycle.recovery.resolve({
|
|
237
|
+
actorId: params.id,
|
|
238
|
+
generation: generation + 1,
|
|
239
|
+
machineInitial: params.machine.initial
|
|
240
|
+
});
|
|
241
|
+
if (Option.isSome(resolved)) restartState = resolved.value;
|
|
242
|
+
}
|
|
243
|
+
yield* settlePendingReplies(params.pendingReplies, params.id);
|
|
244
|
+
const freshQueue = yield* Queue.unbounded();
|
|
245
|
+
yield* Ref.set(params.eventQueueRef, freshQueue);
|
|
246
|
+
yield* SubscriptionRef.set(params.stateRef, restartState);
|
|
247
|
+
yield* Ref.set(params.stoppedRef, false);
|
|
248
|
+
params.childrenMap.clear();
|
|
249
|
+
const machineForRestart = restartState !== params.machine.initial ? Object.create(params.machine, { initial: {
|
|
250
|
+
value: restartState,
|
|
251
|
+
enumerable: true
|
|
252
|
+
} }) : params.machine;
|
|
253
|
+
const newRuntime = yield* params.spawnGeneration(machineForRestart);
|
|
254
|
+
params.runtimeRef.current = newRuntime;
|
|
255
|
+
yield* newRuntime.start;
|
|
256
|
+
generation++;
|
|
257
|
+
if (params.onRestart !== void 0) yield* params.onRestart(generation, generationExit);
|
|
258
|
+
notifyListeners(params.listeners, restartState);
|
|
259
|
+
}
|
|
260
|
+
});
|
|
166
261
|
/**
|
|
167
262
|
* Create and start an actor for a machine.
|
|
168
|
-
*
|
|
263
|
+
* Delegates to the shared runtime kernel with actor-specific lifecycle hooks.
|
|
169
264
|
*/
|
|
170
265
|
const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machine, options) {
|
|
266
|
+
const lifecycle = options?.lifecycle;
|
|
171
267
|
const initial = options?.initialState ?? machine.initial;
|
|
172
268
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.id", id);
|
|
173
269
|
yield* Effect.annotateCurrentSpan("effect_machine.actor.initial_state", initial._tag);
|
|
174
|
-
const
|
|
175
|
-
let system;
|
|
176
|
-
let implicitSystemScope;
|
|
177
|
-
if (Option.isSome(existingSystem)) system = existingSystem.value;
|
|
178
|
-
else {
|
|
179
|
-
const scope = yield* Scope.make();
|
|
180
|
-
system = yield* make().pipe(Effect.provideService(Scope.Scope, scope));
|
|
181
|
-
implicitSystemScope = scope;
|
|
182
|
-
}
|
|
270
|
+
const { system, implicitSystemScope } = yield* resolveActorSystem();
|
|
183
271
|
const inspectorValue = Option.getOrUndefined(yield* Effect.serviceOption(Inspector));
|
|
184
272
|
const childrenMap = /* @__PURE__ */ new Map();
|
|
185
273
|
const pendingReplies = /* @__PURE__ */ new Set();
|
|
186
274
|
const listeners = /* @__PURE__ */ new Set();
|
|
187
275
|
const transitionsPubSub = yield* PubSub.unbounded();
|
|
188
|
-
|
|
189
|
-
type: "@machine.spawn",
|
|
190
|
-
actorId: id,
|
|
191
|
-
initialState: initial,
|
|
192
|
-
timestamp
|
|
193
|
-
}));
|
|
194
|
-
const hooks = inspectorValue === void 0 ? void 0 : {
|
|
195
|
-
onSpawnEffect: (state) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
196
|
-
type: "@machine.effect",
|
|
197
|
-
actorId: id,
|
|
198
|
-
effectType: "spawn",
|
|
199
|
-
state,
|
|
200
|
-
timestamp
|
|
201
|
-
})),
|
|
202
|
-
onTransition: (from, to, ev) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
203
|
-
type: "@machine.transition",
|
|
204
|
-
actorId: id,
|
|
205
|
-
fromState: from,
|
|
206
|
-
toState: to,
|
|
207
|
-
event: ev,
|
|
208
|
-
timestamp
|
|
209
|
-
})),
|
|
210
|
-
onError: (info) => emitWithTimestamp(inspectorValue, (timestamp) => ({
|
|
211
|
-
type: "@machine.error",
|
|
212
|
-
actorId: id,
|
|
213
|
-
phase: info.phase,
|
|
214
|
-
state: info.state,
|
|
215
|
-
event: info.event,
|
|
216
|
-
error: Cause.pretty(info.cause),
|
|
217
|
-
timestamp
|
|
218
|
-
}))
|
|
219
|
-
};
|
|
276
|
+
const hooks = inspectorValue !== void 0 ? buildInspectionHooks(id, inspectorValue) : void 0;
|
|
220
277
|
const machineWithState = initial !== machine.initial ? Object.create(machine, { initial: {
|
|
221
278
|
value: initial,
|
|
222
279
|
enumerable: true
|
|
@@ -227,6 +284,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
227
284
|
const eventQueueRef = yield* Ref.make(initialQueue);
|
|
228
285
|
const terminalExitDeferred = yield* Deferred.make();
|
|
229
286
|
let stopEmitted = false;
|
|
287
|
+
let generation = 0;
|
|
230
288
|
const runtimeRef = { current: void 0 };
|
|
231
289
|
/** Build lifecycle hooks for a generation */
|
|
232
290
|
const buildLifecycle = () => {
|
|
@@ -239,8 +297,18 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
239
297
|
event,
|
|
240
298
|
timestamp
|
|
241
299
|
})) : void 0,
|
|
242
|
-
onStateChange: (result,
|
|
300
|
+
onStateChange: (result, event) => Effect.gen(function* () {
|
|
243
301
|
notifyListeners(listeners, result.newState);
|
|
302
|
+
if (lifecycle?.durability !== void 0 && result.transitioned) {
|
|
303
|
+
const durability = lifecycle.durability;
|
|
304
|
+
if (durability.shouldSave === void 0 || durability.shouldSave(result.newState, result.previousState)) yield* durability.save({
|
|
305
|
+
actorId: id,
|
|
306
|
+
generation,
|
|
307
|
+
previousState: result.previousState,
|
|
308
|
+
nextState: result.newState,
|
|
309
|
+
event
|
|
310
|
+
});
|
|
311
|
+
}
|
|
244
312
|
yield* Effect.annotateCurrentSpan("effect_machine.transition.matched", true);
|
|
245
313
|
if (result.lifecycleRan) {
|
|
246
314
|
yield* Effect.annotateCurrentSpan("effect_machine.state.from", result.previousState._tag);
|
|
@@ -282,7 +350,7 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
282
350
|
})) : void 0
|
|
283
351
|
};
|
|
284
352
|
};
|
|
285
|
-
/** Create a single runtime generation */
|
|
353
|
+
/** Create a single runtime generation. machineForGen is machineWithState for initial, machine for restarts. */
|
|
286
354
|
const spawnGeneration = (machineForGen) => Ref.get(eventQueueRef).pipe(Effect.flatMap((currentQueue) => createRuntime(machineForGen, system, {
|
|
287
355
|
actorId: id,
|
|
288
356
|
hooks,
|
|
@@ -306,49 +374,62 @@ const createActor = Effect.fn("effect-machine.actor.spawn")(function* (id, machi
|
|
|
306
374
|
}));
|
|
307
375
|
})
|
|
308
376
|
})));
|
|
377
|
+
runtimeRef.current = yield* spawnGeneration(machineWithState);
|
|
309
378
|
const supervision = options?.supervision;
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if (supervision !== void 0) supervisorFiber = yield* Effect.forkDaemon(Effect.gen(function* () {
|
|
314
|
-
const driver = yield* Schedule.driver(supervision.schedule);
|
|
315
|
-
let generation = 0;
|
|
316
|
-
while (true) {
|
|
317
|
-
const currentRuntime = runtimeRef.current;
|
|
318
|
-
if (currentRuntime === void 0) return;
|
|
319
|
-
const generationExit = yield* Deferred.await(currentRuntime.exitDeferred);
|
|
320
|
-
if (generationExit._tag !== "Defect") {
|
|
321
|
-
yield* Deferred.succeed(terminalExitDeferred, generationExit);
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
if (supervision.shouldRestart !== void 0 && !supervision.shouldRestart(generationExit)) {
|
|
325
|
-
yield* Deferred.succeed(terminalExitDeferred, generationExit);
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
if ((yield* driver.next(generationExit).pipe(Effect.exit))._tag === "Failure") {
|
|
329
|
-
yield* Deferred.succeed(terminalExitDeferred, generationExit);
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
yield* settlePendingReplies(pendingReplies, id);
|
|
333
|
-
const freshQueue = yield* Queue.unbounded();
|
|
334
|
-
yield* Ref.set(eventQueueRef, freshQueue);
|
|
335
|
-
yield* SubscriptionRef.set(stateRef, machine.initial);
|
|
336
|
-
yield* Ref.set(stoppedRef, false);
|
|
337
|
-
childrenMap.clear();
|
|
338
|
-
runtimeRef.current = yield* spawnGeneration(machine);
|
|
339
|
-
generation++;
|
|
340
|
-
if (options?.onRestart !== void 0) yield* options.onRestart(generation, generationExit);
|
|
341
|
-
notifyListeners(listeners, machine.initial);
|
|
342
|
-
}
|
|
343
|
-
}));
|
|
344
|
-
else yield* Deferred.await(runtime.exitDeferred).pipe(Effect.tap((exit) => Deferred.succeed(terminalExitDeferred, exit)), Effect.catchAllCause(() => Effect.void), Effect.fork);
|
|
345
|
-
return buildActorRefCore(id, machine, stateRef, eventQueueRef, stoppedRef, listeners, Effect.gen(function* () {
|
|
346
|
-
if (supervisorFiber !== void 0) yield* Fiber.interrupt(supervisorFiber);
|
|
379
|
+
const supervisorFiberRef = { current: void 0 };
|
|
380
|
+
const stop = Effect.gen(function* () {
|
|
381
|
+
if (supervisorFiberRef.current !== void 0) yield* Fiber.interrupt(supervisorFiberRef.current);
|
|
347
382
|
const currentRuntime = runtimeRef.current;
|
|
348
383
|
if (currentRuntime !== void 0) yield* currentRuntime.stop;
|
|
349
384
|
yield* Deferred.succeed(terminalExitDeferred, { _tag: "Stopped" });
|
|
350
385
|
if (implicitSystemScope !== void 0) yield* Scope.close(implicitSystemScope, Exit.void);
|
|
351
|
-
}).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.forkDaemon(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
|
+
onRestart: options?.onRestart
|
|
425
|
+
}));
|
|
426
|
+
else {
|
|
427
|
+
const currentRuntime = runtimeRef.current;
|
|
428
|
+
if (currentRuntime !== void 0) yield* Effect.forkDaemon(Deferred.await(currentRuntime.exitDeferred).pipe(Effect.tap((exit) => Deferred.succeed(terminalExitDeferred, exit))));
|
|
429
|
+
}
|
|
430
|
+
const currentRuntime = runtimeRef.current;
|
|
431
|
+
if (currentRuntime !== void 0) yield* currentRuntime.start;
|
|
432
|
+
}).pipe(Effect.withSpan("effect-machine.actor.start"), Effect.asVoid), system, childrenMap, pendingReplies, transitionsPubSub, terminalExitDeferred);
|
|
352
433
|
});
|
|
353
434
|
/** Fail all pending call/ask Deferreds with ActorStoppedError. Safe to call multiple times. */
|
|
354
435
|
const settlePendingReplies = (pendingReplies, actorId) => Effect.sync(() => {
|
|
@@ -367,14 +448,15 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
367
448
|
const withSpawnGate = (yield* Effect.makeSemaphore(1)).withPermits(1);
|
|
368
449
|
const eventPubSub = yield* PubSub.unbounded();
|
|
369
450
|
const eventListeners = /* @__PURE__ */ new Set();
|
|
370
|
-
const emitSystemEvent = (event) => Effect.sync(() => notifySystemListeners(eventListeners, event)).pipe(Effect.
|
|
451
|
+
const emitSystemEvent = (event) => Effect.sync(() => notifySystemListeners(eventListeners, event)).pipe(Effect.andThen(PubSub.publish(eventPubSub, event)), Effect.catchAllCause(() => Effect.void), Effect.asVoid);
|
|
371
452
|
yield* Effect.addFinalizer(() => {
|
|
372
453
|
const stops = [];
|
|
373
454
|
MutableHashMap.forEach(actorsMap, (actor) => {
|
|
374
455
|
stops.push(actor.stop);
|
|
375
456
|
});
|
|
376
|
-
return Effect.all(stops, { concurrency: "unbounded" }).pipe(Effect.
|
|
457
|
+
return Effect.all(stops, { concurrency: "unbounded" }).pipe(Effect.andThen(PubSub.shutdown(eventPubSub)), Effect.asVoid);
|
|
377
458
|
});
|
|
459
|
+
/** Check for duplicate ID, register actor, attach scope cleanup if available */
|
|
378
460
|
const registerActor = Effect.fn("effect-machine.actorSystem.register")(function* (id, actor) {
|
|
379
461
|
if (MutableHashMap.has(actorsMap, id)) {
|
|
380
462
|
yield* actor.stop;
|
|
@@ -404,10 +486,11 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
404
486
|
});
|
|
405
487
|
const spawnRegular = Effect.fn("effect-machine.actorSystem.spawnRegular")(function* (id, machine, spawnOptions) {
|
|
406
488
|
if (MutableHashMap.has(actorsMap, id)) return yield* new DuplicateActorError({ actorId: id });
|
|
407
|
-
const materialized = materializeMachine(machine, spawnOptions
|
|
489
|
+
const materialized = spawnOptions?.slots !== void 0 ? materializeMachine(machine, spawnOptions.slots) : machine;
|
|
408
490
|
let actorRef;
|
|
409
491
|
const actor = yield* createActor(id, materialized, {
|
|
410
492
|
supervision: spawnOptions?.supervision,
|
|
493
|
+
lifecycle: spawnOptions?.lifecycle,
|
|
411
494
|
onRestart: spawnOptions?.supervision !== void 0 ? (generation, exit) => actorRef !== void 0 ? emitSystemEvent({
|
|
412
495
|
_tag: "ActorRestarted",
|
|
413
496
|
id,
|
|
@@ -417,7 +500,9 @@ const make = Effect.fn("effect-machine.actorSystem.make")(function* () {
|
|
|
417
500
|
}) : Effect.void : void 0
|
|
418
501
|
});
|
|
419
502
|
actorRef = actor;
|
|
420
|
-
|
|
503
|
+
yield* registerActor(id, actor);
|
|
504
|
+
yield* actor.start.pipe(Effect.catchAllCause((cause) => actor.stop.pipe(Effect.andThen(Effect.failCause(cause)))));
|
|
505
|
+
return actor;
|
|
421
506
|
});
|
|
422
507
|
const spawn = (id, machine, options) => withSpawnGate(spawnRegular(id, machine, options));
|
|
423
508
|
const get = Effect.fn("effect-machine.actorSystem.get")(function* (id) {
|
|
@@ -465,6 +550,6 @@ const makeSystem = make;
|
|
|
465
550
|
/**
|
|
466
551
|
* Default ActorSystem layer
|
|
467
552
|
*/
|
|
468
|
-
const Default = Layer.
|
|
553
|
+
const Default = Layer.scoped(ActorSystem, make());
|
|
469
554
|
//#endregion
|
|
470
555
|
export { ActorSystem, Default, buildActorRefCore, createActor, makeSystem, notifyListeners, processEventCore, resolveTransition, runSpawnEffects, settlePendingReplies };
|
|
@@ -68,7 +68,7 @@ declare const EntityMachine: {
|
|
|
68
68
|
readonly _tag: string;
|
|
69
69
|
}, E extends {
|
|
70
70
|
readonly _tag: string;
|
|
71
|
-
}, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any, any
|
|
71
|
+
}, R, EntityType extends string, Rpcs extends Rpc.Any>(entity: Entity.Entity<EntityType, Rpcs>, machine: Machine<S, E, R, any, any, any>, options?: EntityMachineOptions<S, E>) => Layer.Layer<never, never, R>;
|
|
72
72
|
};
|
|
73
73
|
//#endregion
|
|
74
74
|
export { EntityMachine, EntityMachineOptions };
|
|
@@ -50,6 +50,7 @@ const EntityMachine = { layer: (entity, machine, options) => {
|
|
|
50
50
|
hooks: options?.hooks,
|
|
51
51
|
childIdPrefix: `${entityId}/`
|
|
52
52
|
});
|
|
53
|
+
yield* runtime.start;
|
|
53
54
|
if (persistCtx.adapter !== void 0) {
|
|
54
55
|
const { adapter: pAdapter, key } = persistCtx;
|
|
55
56
|
yield* Effect.addFinalizer(() => Effect.gen(function* () {
|
|
@@ -59,6 +59,6 @@ declare const toEntity: <S extends {
|
|
|
59
59
|
readonly _tag: string;
|
|
60
60
|
}, E extends {
|
|
61
61
|
readonly _tag: string;
|
|
62
|
-
}, R>(machine: Machine<S, E, R, any, any, any
|
|
62
|
+
}, R>(machine: Machine<S, E, R, any, any, any>, options: ToEntityOptions) => any;
|
|
63
63
|
//#endregion
|
|
64
64
|
export { EntityRpcs, ToEntityOptions, toEntity };
|
package/v3/dist/errors.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ declare const SlotProvisionError_base: Schema.TaggedErrorClass<SlotProvisionErro
|
|
|
33
33
|
readonly _tag: Schema.tag<"SlotProvisionError">;
|
|
34
34
|
} & {
|
|
35
35
|
slotName: typeof Schema.String;
|
|
36
|
-
slotType: Schema.Literal<["
|
|
36
|
+
slotType: Schema.Literal<["slot"]>;
|
|
37
37
|
}>;
|
|
38
38
|
/** Slot handler not found at runtime (internal error) */
|
|
39
39
|
declare class SlotProvisionError extends SlotProvisionError_base {}
|
|
@@ -43,7 +43,7 @@ declare const ProvisionValidationError_base: Schema.TaggedErrorClass<ProvisionVa
|
|
|
43
43
|
missing: Schema.Array$<typeof Schema.String>;
|
|
44
44
|
extra: Schema.Array$<typeof Schema.String>;
|
|
45
45
|
}>;
|
|
46
|
-
/**
|
|
46
|
+
/** Slot provision validation failed — missing or extra handlers */
|
|
47
47
|
declare class ProvisionValidationError extends ProvisionValidationError_base {}
|
|
48
48
|
declare const AssertionError_base: Schema.TaggedErrorClass<AssertionError, "AssertionError", {
|
|
49
49
|
readonly _tag: Schema.tag<"AssertionError">;
|
|
@@ -74,6 +74,15 @@ declare const PersistenceError_base: Schema.TaggedErrorClass<PersistenceError, "
|
|
|
74
74
|
}>;
|
|
75
75
|
/** Persistence adapter operation failed */
|
|
76
76
|
declare class PersistenceError extends PersistenceError_base {}
|
|
77
|
+
declare const SlotCodecError_base: Schema.TaggedErrorClass<SlotCodecError, "SlotCodecError", {
|
|
78
|
+
readonly _tag: Schema.tag<"SlotCodecError">;
|
|
79
|
+
} & {
|
|
80
|
+
slotName: typeof Schema.String;
|
|
81
|
+
phase: Schema.Literal<["input", "output"]>;
|
|
82
|
+
message: typeof Schema.String;
|
|
83
|
+
}>;
|
|
84
|
+
/** Slot input/output schema validation failed */
|
|
85
|
+
declare class SlotCodecError extends SlotCodecError_base {}
|
|
77
86
|
declare const VersionConflictError_base: Schema.TaggedErrorClass<VersionConflictError, "VersionConflictError", {
|
|
78
87
|
readonly _tag: Schema.tag<"VersionConflictError">;
|
|
79
88
|
} & {
|
|
@@ -83,4 +92,4 @@ declare const VersionConflictError_base: Schema.TaggedErrorClass<VersionConflict
|
|
|
83
92
|
/** Optimistic locking failure — stored version doesn't match expected */
|
|
84
93
|
declare class VersionConflictError extends VersionConflictError_base {}
|
|
85
94
|
//#endregion
|
|
86
|
-
export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError };
|
|
95
|
+
export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
|
package/v3/dist/errors.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Schema } from "effect";
|
|
|
3
3
|
/**
|
|
4
4
|
* Typed error classes for effect-machine.
|
|
5
5
|
*
|
|
6
|
-
* All errors extend Schema.
|
|
6
|
+
* All errors extend Schema.TaggedErrorClass for:
|
|
7
7
|
* - Type-safe catching via Effect.catchTag
|
|
8
8
|
* - Serialization support
|
|
9
9
|
* - Composable error handling
|
|
@@ -21,9 +21,9 @@ var MissingMatchHandlerError = class extends Schema.TaggedError()("MissingMatchH
|
|
|
21
21
|
/** Slot handler not found at runtime (internal error) */
|
|
22
22
|
var SlotProvisionError = class extends Schema.TaggedError()("SlotProvisionError", {
|
|
23
23
|
slotName: Schema.String,
|
|
24
|
-
slotType: Schema.Literal("
|
|
24
|
+
slotType: Schema.Literal("slot")
|
|
25
25
|
}) {};
|
|
26
|
-
/**
|
|
26
|
+
/** Slot provision validation failed — missing or extra handlers */
|
|
27
27
|
var ProvisionValidationError = class extends Schema.TaggedError()("ProvisionValidationError", {
|
|
28
28
|
missing: Schema.Array(Schema.String),
|
|
29
29
|
extra: Schema.Array(Schema.String)
|
|
@@ -39,10 +39,16 @@ var NoReplyError = class extends Schema.TaggedError()("NoReplyError", {
|
|
|
39
39
|
}) {};
|
|
40
40
|
/** Persistence adapter operation failed */
|
|
41
41
|
var PersistenceError = class extends Schema.TaggedError()("PersistenceError", { message: Schema.String }) {};
|
|
42
|
+
/** Slot input/output schema validation failed */
|
|
43
|
+
var SlotCodecError = class extends Schema.TaggedError()("SlotCodecError", {
|
|
44
|
+
slotName: Schema.String,
|
|
45
|
+
phase: Schema.Literal("input", "output"),
|
|
46
|
+
message: Schema.String
|
|
47
|
+
}) {};
|
|
42
48
|
/** Optimistic locking failure — stored version doesn't match expected */
|
|
43
49
|
var VersionConflictError = class extends Schema.TaggedError()("VersionConflictError", {
|
|
44
50
|
expected: Schema.Number,
|
|
45
51
|
actual: Schema.Number
|
|
46
52
|
}) {};
|
|
47
53
|
//#endregion
|
|
48
|
-
export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError };
|
|
54
|
+
export { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError };
|
package/v3/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ReplyResult } from "./internal/utils.js";
|
|
1
|
+
import { DeferReplyResult, ReplyResult } from "./internal/utils.js";
|
|
3
2
|
import { Event, MachineEventSchema, MachineStateSchema, ReplyFields, State } from "./schema.js";
|
|
4
|
-
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError } from "./errors.js";
|
|
5
|
-
import {
|
|
3
|
+
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
|
|
4
|
+
import { HasSlotKeys, MachineContext, ProvideSlots, Slot, SlotCall, SlotCalls, SlotFnDef, SlotHandler, SlotInvocation, SlotRequest, SlotResult, SlotsDef, SlotsSchema } from "./slot.js";
|
|
5
|
+
import { ActorExit, CellPhase, DefectPhase, Supervision } from "./supervision.js";
|
|
6
6
|
import { ProcessEventResult } from "./internal/transition.js";
|
|
7
|
-
import { BackgroundEffect, HandlerContext, Machine, MachineRef, MakeConfig,
|
|
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,
|
|
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 };
|
package/v3/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotProvisionError, VersionConflictError } from "./errors.js";
|
|
1
|
+
import { ActorStoppedError, AssertionError, DuplicateActorError, InvalidSchemaError, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, SlotCodecError, SlotProvisionError, VersionConflictError } from "./errors.js";
|
|
2
2
|
import { Inspector, collectingInspector, combineInspectors, consoleInspector, makeInspector, makeInspectorEffect, tracingInspector } from "./inspection.js";
|
|
3
3
|
import { Slot } from "./slot.js";
|
|
4
4
|
import { machine_exports } from "./machine.js";
|
|
@@ -6,4 +6,4 @@ import { ActorExit, Supervision } from "./supervision.js";
|
|
|
6
6
|
import { ActorSystem, Default } from "./actor.js";
|
|
7
7
|
import { Event, State } from "./schema.js";
|
|
8
8
|
import { assertNeverReaches, assertPath, assertReaches, createTestHarness, simulate } from "./testing.js";
|
|
9
|
-
export { ActorExit, ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, Slot, SlotProvisionError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
|
9
|
+
export { ActorExit, ActorStoppedError, Default as ActorSystemDefault, ActorSystem as ActorSystemService, AssertionError, DuplicateActorError, Event, Inspector as InspectorService, InvalidSchemaError, machine_exports as Machine, MissingMatchHandlerError, MissingSchemaError, NoReplyError, PersistenceError, ProvisionValidationError, Slot, SlotCodecError, SlotProvisionError, State, Supervision, VersionConflictError, assertNeverReaches, assertPath, assertReaches, collectingInspector, combineInspectors, consoleInspector, createTestHarness, makeInspector, makeInspectorEffect, simulate, tracingInspector };
|
package/v3/dist/inspection.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Context, Effect, Schema } from "effect";
|
|
|
4
4
|
/**
|
|
5
5
|
* Resolve a type param: if it's a Schema, extract `.Type`; otherwise use as-is.
|
|
6
6
|
*/
|
|
7
|
-
type ResolveType<T> = T extends Schema.Schema<infer A
|
|
7
|
+
type ResolveType<T> = T extends Schema.Schema<infer A> ? A : T;
|
|
8
8
|
/**
|
|
9
9
|
* Event emitted when an actor is spawned
|
|
10
10
|
*/
|
|
@@ -45,9 +45,6 @@ interface EffectEvent<S> {
|
|
|
45
45
|
readonly state: S;
|
|
46
46
|
readonly timestamp: number;
|
|
47
47
|
}
|
|
48
|
-
/**
|
|
49
|
-
* Event emitted when a task lifecycle phase occurs
|
|
50
|
-
*/
|
|
51
48
|
interface TaskEvent<S> {
|
|
52
49
|
readonly type: "@machine.task";
|
|
53
50
|
readonly actorId: string;
|
|
@@ -93,13 +90,10 @@ type AnyInspectionEvent = InspectionEvent<{
|
|
|
93
90
|
}, {
|
|
94
91
|
readonly _tag: string;
|
|
95
92
|
}>;
|
|
96
|
-
/**
|
|
97
|
-
* Inspector handler — sync callback or Effect-returning callback.
|
|
98
|
-
*/
|
|
99
|
-
type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
|
|
100
93
|
/**
|
|
101
94
|
* Inspector interface for observing machine behavior
|
|
102
95
|
*/
|
|
96
|
+
type InspectorHandler<S, E> = (event: InspectionEvent<S, E>) => void | Effect.Effect<void, never, never>;
|
|
103
97
|
interface Inspector<S, E> {
|
|
104
98
|
readonly onInspect: InspectorHandler<S, E>;
|
|
105
99
|
}
|
|
@@ -109,7 +103,7 @@ interface Inspector<S, E> {
|
|
|
109
103
|
*/
|
|
110
104
|
declare const Inspector: Context.Tag<Inspector<any, any>, Inspector<any, any>>;
|
|
111
105
|
/**
|
|
112
|
-
* Create an inspector from a
|
|
106
|
+
* Create an inspector from a callback function.
|
|
113
107
|
*
|
|
114
108
|
* Type params accept either raw tagged types or Schema constructors:
|
|
115
109
|
* - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
|
|
@@ -121,30 +115,17 @@ declare const makeInspector: <S = {
|
|
|
121
115
|
}, E = {
|
|
122
116
|
readonly _tag: string;
|
|
123
117
|
}>(onInspect: InspectorHandler<ResolveType<S>, ResolveType<E>>) => Inspector<ResolveType<S>, ResolveType<E>>;
|
|
124
|
-
/**
|
|
125
|
-
* Create an inspector from an Effect-returning callback function.
|
|
126
|
-
*/
|
|
127
118
|
declare const makeInspectorEffect: <S = {
|
|
128
119
|
readonly _tag: string;
|
|
129
120
|
}, E = {
|
|
130
121
|
readonly _tag: string;
|
|
131
122
|
}>(onInspect: (event: InspectionEvent<ResolveType<S>, ResolveType<E>>) => Effect.Effect<void, never, never>) => Inspector<ResolveType<S>, ResolveType<E>>;
|
|
132
|
-
/**
|
|
133
|
-
* Combine multiple inspectors into one. All run concurrently per event.
|
|
134
|
-
* Individual inspector failures are swallowed.
|
|
135
|
-
*/
|
|
136
123
|
declare const combineInspectors: <S, E>(...inspectors: ReadonlyArray<Inspector<S, E>>) => Inspector<S, E>;
|
|
137
|
-
/**
|
|
138
|
-
* Options for the tracing inspector.
|
|
139
|
-
*/
|
|
140
124
|
interface TracingInspectorOptions<S, E> {
|
|
141
125
|
readonly spanName?: string | ((event: InspectionEvent<S, E>) => string);
|
|
142
126
|
readonly attributes?: (event: InspectionEvent<S, E>) => Readonly<Record<string, string | number | boolean>>;
|
|
143
127
|
readonly eventName?: (event: InspectionEvent<S, E>) => string;
|
|
144
128
|
}
|
|
145
|
-
/**
|
|
146
|
-
* Inspector that emits OpenTelemetry spans and events for each inspection event.
|
|
147
|
-
*/
|
|
148
129
|
declare const tracingInspector: <S extends {
|
|
149
130
|
readonly _tag: string;
|
|
150
131
|
}, E extends {
|
package/v3/dist/inspection.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Context, Effect, Option } from "effect";
|
|
|
6
6
|
*/
|
|
7
7
|
const Inspector = Context.GenericTag("@effect/machine/Inspector");
|
|
8
8
|
/**
|
|
9
|
-
* Create an inspector from a
|
|
9
|
+
* Create an inspector from a callback function.
|
|
10
10
|
*
|
|
11
11
|
* Type params accept either raw tagged types or Schema constructors:
|
|
12
12
|
* - `makeInspector(cb)` — defaults to `AnyInspectionEvent`
|
|
@@ -14,22 +14,11 @@ const Inspector = Context.GenericTag("@effect/machine/Inspector");
|
|
|
14
14
|
* - `makeInspector<typeof MyState, typeof MyEvent>(cb)` — schema constructors (auto-extracts `.Type`)
|
|
15
15
|
*/
|
|
16
16
|
const makeInspector = (onInspect) => ({ onInspect });
|
|
17
|
-
/**
|
|
18
|
-
* Create an inspector from an Effect-returning callback function.
|
|
19
|
-
*/
|
|
20
17
|
const makeInspectorEffect = (onInspect) => ({ onInspect });
|
|
21
|
-
/**
|
|
22
|
-
* Run an inspector handler, handling both sync and Effect returns.
|
|
23
|
-
* @internal
|
|
24
|
-
*/
|
|
25
18
|
const inspectionEffect = (inspector, event) => {
|
|
26
19
|
const result = inspector.onInspect(event);
|
|
27
20
|
return Effect.isEffect(result) ? result : Effect.void;
|
|
28
21
|
};
|
|
29
|
-
/**
|
|
30
|
-
* Combine multiple inspectors into one. All run concurrently per event.
|
|
31
|
-
* Individual inspector failures are swallowed.
|
|
32
|
-
*/
|
|
33
22
|
const combineInspectors = (...inspectors) => ({ onInspect: (event) => Effect.forEach(inspectors, (inspector) => inspectionEffect(inspector, event).pipe(Effect.catchAllCause(() => Effect.void)), {
|
|
34
23
|
concurrency: "unbounded",
|
|
35
24
|
discard: true
|
|
@@ -99,9 +88,6 @@ const inspectionAttributes = (event) => {
|
|
|
99
88
|
};
|
|
100
89
|
}
|
|
101
90
|
};
|
|
102
|
-
/**
|
|
103
|
-
* Inspector that emits OpenTelemetry spans and events for each inspection event.
|
|
104
|
-
*/
|
|
105
91
|
const tracingInspector = (options) => ({ onInspect: (event) => {
|
|
106
92
|
const spanName = typeof options?.spanName === "function" ? options.spanName(event) : options?.spanName;
|
|
107
93
|
const traceName = options?.eventName?.(event) ?? inspectionTraceName(event);
|