@typeonce/effect-machine 0.12.0 → 0.14.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 +130 -30
- package/dist/Machine.d.ts +722 -262
- package/dist/Machine.d.ts.map +1 -1
- package/dist/Machine.js +130 -62
- package/dist/Machine.js.map +1 -1
- package/dist/internal/machine/atom.d.ts +1 -0
- package/dist/internal/machine/atom.d.ts.map +1 -1
- package/dist/internal/machine/atom.js +23 -0
- package/dist/internal/machine/atom.js.map +1 -1
- package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
- package/dist/internal/machine/commandRuntime.js +2 -5
- package/dist/internal/machine/commandRuntime.js.map +1 -1
- package/dist/internal/machine/configuration.d.ts +5 -0
- package/dist/internal/machine/configuration.d.ts.map +1 -1
- package/dist/internal/machine/configuration.js +6 -2
- package/dist/internal/machine/configuration.js.map +1 -1
- package/dist/internal/machine/executionPlan.d.ts +1 -0
- package/dist/internal/machine/executionPlan.d.ts.map +1 -1
- package/dist/internal/machine/executionPlan.js +57 -24
- package/dist/internal/machine/executionPlan.js.map +1 -1
- package/dist/internal/machine/initialization.d.ts +5 -0
- package/dist/internal/machine/initialization.d.ts.map +1 -0
- package/dist/internal/machine/initialization.js +61 -0
- package/dist/internal/machine/initialization.js.map +1 -0
- package/dist/internal/machine/inspectionRuntime.d.ts +25 -0
- package/dist/internal/machine/inspectionRuntime.d.ts.map +1 -0
- package/dist/internal/machine/inspectionRuntime.js +79 -0
- package/dist/internal/machine/inspectionRuntime.js.map +1 -0
- package/dist/internal/machine/invocation.d.ts +2 -1
- package/dist/internal/machine/invocation.d.ts.map +1 -1
- package/dist/internal/machine/invocation.js +17 -10
- package/dist/internal/machine/invocation.js.map +1 -1
- package/dist/internal/machine/machine.d.ts +4 -3
- package/dist/internal/machine/machine.d.ts.map +1 -1
- package/dist/internal/machine/machine.js +327 -32
- package/dist/internal/machine/machine.js.map +1 -1
- package/dist/internal/machine/planner.d.ts +28 -0
- package/dist/internal/machine/planner.d.ts.map +1 -1
- package/dist/internal/machine/planner.js +132 -51
- package/dist/internal/machine/planner.js.map +1 -1
- package/dist/internal/machine/process.d.ts.map +1 -1
- package/dist/internal/machine/process.js +4 -2
- package/dist/internal/machine/process.js.map +1 -1
- package/dist/internal/machine/runtime.d.ts +27 -3
- package/dist/internal/machine/runtime.d.ts.map +1 -1
- package/dist/internal/machine/runtime.js +440 -64
- package/dist/internal/machine/runtime.js.map +1 -1
- package/dist/internal/machine/symbols.d.ts +2 -0
- package/dist/internal/machine/symbols.d.ts.map +1 -1
- package/dist/internal/machine/symbols.js +2 -0
- package/dist/internal/machine/symbols.js.map +1 -1
- package/dist/internal/machine/topology.d.ts +25 -0
- package/dist/internal/machine/topology.d.ts.map +1 -1
- package/dist/internal/machine/topology.js +26 -10
- package/dist/internal/machine/topology.js.map +1 -1
- package/dist/internal/testing/machine/exploration.d.ts.map +1 -1
- package/dist/internal/testing/machine/exploration.js +11 -2
- package/dist/internal/testing/machine/exploration.js.map +1 -1
- package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
- package/dist/internal/testing/machine/finiteModel.js +75 -69
- package/dist/internal/testing/machine/finiteModel.js.map +1 -1
- package/dist/internal/testing/machine/transitionCoverage.d.ts +20 -0
- package/dist/internal/testing/machine/transitionCoverage.d.ts.map +1 -0
- package/dist/internal/testing/machine/transitionCoverage.js +80 -0
- package/dist/internal/testing/machine/transitionCoverage.js.map +1 -0
- package/dist/internal/testing/machine/verification.d.ts.map +1 -1
- package/dist/internal/testing/machine/verification.js +171 -33
- package/dist/internal/testing/machine/verification.js.map +1 -1
- package/dist/testing/MachineTest.d.ts +97 -22
- package/dist/testing/MachineTest.d.ts.map +1 -1
- package/dist/testing/MachineTest.js +58 -16
- package/dist/testing/MachineTest.js.map +1 -1
- package/dist/unstable/cluster/ClusterMachine.d.ts +4 -1
- package/dist/unstable/cluster/ClusterMachine.d.ts.map +1 -1
- package/dist/unstable/cluster/ClusterMachine.js +4 -1
- package/dist/unstable/cluster/ClusterMachine.js.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.d.ts +21 -3
- package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
- package/dist/unstable/reactivity/AtomMachine.js +21 -3
- package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
- package/docs/agent-guide.md +240 -65
- package/package.json +5 -5
- package/src/Machine.ts +1240 -495
- package/src/internal/machine/atom.ts +26 -0
- package/src/internal/machine/commandRuntime.ts +2 -9
- package/src/internal/machine/configuration.ts +28 -3
- package/src/internal/machine/executionPlan.ts +72 -24
- package/src/internal/machine/initialization.ts +73 -0
- package/src/internal/machine/inspectionRuntime.ts +102 -0
- package/src/internal/machine/invocation.ts +37 -12
- package/src/internal/machine/machine.ts +438 -39
- package/src/internal/machine/planner.ts +180 -55
- package/src/internal/machine/process.ts +4 -2
- package/src/internal/machine/runtime.ts +661 -89
- package/src/internal/machine/symbols.ts +3 -0
- package/src/internal/machine/topology.ts +65 -12
- package/src/internal/testing/machine/exploration.ts +10 -2
- package/src/internal/testing/machine/finiteModel.ts +114 -80
- package/src/internal/testing/machine/transitionCoverage.ts +116 -0
- package/src/internal/testing/machine/verification.ts +216 -58
- package/src/testing/MachineTest.ts +118 -28
- package/src/unstable/cluster/ClusterMachine.ts +4 -1
- package/src/unstable/reactivity/AtomMachine.ts +24 -3
|
@@ -18,8 +18,9 @@ import * as Scope from "effect/Scope"
|
|
|
18
18
|
import * as Stream from "effect/Stream"
|
|
19
19
|
import * as SynchronizedRef from "effect/SynchronizedRef"
|
|
20
20
|
import type * as Take from "effect/Take"
|
|
21
|
-
import type { MachineTarget } from "../../Machine.js"
|
|
21
|
+
import type { Inspection, Machine as MachineDefinition, MachineTarget } from "../../Machine.js"
|
|
22
22
|
import { ChildAlreadyExistsError, StoppedError } from "./errors.js"
|
|
23
|
+
import * as InspectionRuntime from "./inspectionRuntime.js"
|
|
23
24
|
|
|
24
25
|
type ChildDescriptor = {
|
|
25
26
|
readonly id: string
|
|
@@ -69,7 +70,8 @@ const AcknowledgedMessageTypeId: unique symbol = Symbol("effect/Machine/Acknowle
|
|
|
69
70
|
export interface AcknowledgedMessage<Event> {
|
|
70
71
|
readonly [AcknowledgedMessageTypeId]: true
|
|
71
72
|
readonly event: Event
|
|
72
|
-
readonly deferred
|
|
73
|
+
readonly deferred?: Deferred.Deferred<AcknowledgedDelivery<unknown>, unknown>
|
|
74
|
+
readonly inspection?: InspectedDelivery
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
/** @internal */
|
|
@@ -90,7 +92,10 @@ const succeedAcknowledgedMessage = <State>(
|
|
|
90
92
|
delivery: AcknowledgedDelivery<State>
|
|
91
93
|
): void => {
|
|
92
94
|
if (message !== undefined && isAcknowledgedMessage(message)) {
|
|
93
|
-
|
|
95
|
+
if (message.deferred !== undefined) {
|
|
96
|
+
Deferred.doneUnsafe(message.deferred, Effect.succeed(delivery as AcknowledgedDelivery<unknown>))
|
|
97
|
+
}
|
|
98
|
+
message.inspection?.complete(delivery as AcknowledgedDelivery<unknown>)
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
|
|
@@ -99,16 +104,32 @@ const failAcknowledgedMessage = (
|
|
|
99
104
|
cause: Cause.Cause<unknown>
|
|
100
105
|
): void => {
|
|
101
106
|
if (message !== undefined && isAcknowledgedMessage(message)) {
|
|
102
|
-
Deferred.doneUnsafe(message.deferred, Effect.failCause(cause))
|
|
107
|
+
if (message.deferred !== undefined) Deferred.doneUnsafe(message.deferred, Effect.failCause(cause))
|
|
103
108
|
}
|
|
104
109
|
}
|
|
105
110
|
|
|
106
111
|
const stopAcknowledgedMessage = (message: ProcessMessage<unknown> | undefined): void => {
|
|
107
112
|
if (message !== undefined && isAcknowledgedMessage(message)) {
|
|
108
|
-
Deferred.doneUnsafe(message.deferred, Effect.fail(new StoppedError()))
|
|
113
|
+
if (message.deferred !== undefined) Deferred.doneUnsafe(message.deferred, Effect.fail(new StoppedError()))
|
|
109
114
|
}
|
|
110
115
|
}
|
|
111
116
|
|
|
117
|
+
interface InspectedDelivery {
|
|
118
|
+
readonly deliveryId: number
|
|
119
|
+
readonly macrostepId: number
|
|
120
|
+
readonly source: Inspection.Subject | undefined
|
|
121
|
+
readonly event: unknown
|
|
122
|
+
readonly causedBy: Inspection.Causation | undefined
|
|
123
|
+
readonly complete: (delivery: AcknowledgedDelivery<unknown>) => void
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
type InspectedOffer<Event> = (
|
|
127
|
+
event: Event,
|
|
128
|
+
source: Inspection.Subject | undefined,
|
|
129
|
+
causedBy: Inspection.Causation | undefined,
|
|
130
|
+
deferred?: Deferred.Deferred<AcknowledgedDelivery<unknown>, unknown>
|
|
131
|
+
) => Effect.Effect<void, StoppedError>
|
|
132
|
+
|
|
112
133
|
type ChildObservation = Option.Option<MachineRef<any, any, any, any>>
|
|
113
134
|
type ChildObservationBatch = [ChildObservation, ...Array<ChildObservation>]
|
|
114
135
|
|
|
@@ -295,6 +316,10 @@ export interface MachineRef<out State, in Event, out Error = never, out Output =
|
|
|
295
316
|
readonly join: Effect.Effect<Output, Error | StoppedError>
|
|
296
317
|
readonly stop: Effect.Effect<void>
|
|
297
318
|
readonly send: (event: Event) => Effect.Effect<void, StoppedError>
|
|
319
|
+
/** @internal */
|
|
320
|
+
readonly inspectionSubject?: Inspection.Subject
|
|
321
|
+
/** @internal */
|
|
322
|
+
readonly sendInspected?: ProcessAddress<Event>["sendInspected"]
|
|
298
323
|
readonly [acknowledgedSend]?: (
|
|
299
324
|
event: Event
|
|
300
325
|
) => Effect.Effect<AcknowledgedDelivery<State>, Error | StoppedError>
|
|
@@ -315,19 +340,36 @@ export interface PreparedProcess<
|
|
|
315
340
|
readonly sessionId: string
|
|
316
341
|
readonly changes: Stream.Stream<RuntimeSnapshot<State, Error, Output>, StartError>
|
|
317
342
|
readonly emissions: Stream.Stream<Emitted>
|
|
343
|
+
readonly inspection: Stream.Stream<Inspection.Event>
|
|
318
344
|
readonly start: Effect.Effect<MachineRef<State, Event, Error, Output, Emitted>, StartError, StartRequirements>
|
|
319
345
|
}
|
|
320
346
|
|
|
321
347
|
interface ProcessAddress<in Event> {
|
|
322
348
|
readonly id: string
|
|
323
349
|
readonly sessionId: string
|
|
350
|
+
readonly inspectionSubject?: Inspection.Subject
|
|
324
351
|
readonly stop: Effect.Effect<void>
|
|
325
352
|
readonly send: (event: Event) => Effect.Effect<void, StoppedError>
|
|
353
|
+
readonly sendInspected?: (
|
|
354
|
+
event: Event,
|
|
355
|
+
source: Inspection.Subject | undefined,
|
|
356
|
+
causedBy: Inspection.Causation | undefined
|
|
357
|
+
) => Effect.Effect<void, StoppedError>
|
|
326
358
|
}
|
|
327
359
|
|
|
328
|
-
const
|
|
360
|
+
const isMachineTarget = (value: unknown): value is MachineTarget<unknown> =>
|
|
329
361
|
typeof value === "object" && value !== null && "send" in value && typeof value.send === "function"
|
|
330
362
|
|
|
363
|
+
const sendMachineTarget = (
|
|
364
|
+
target: MachineTarget<unknown>,
|
|
365
|
+
event: unknown,
|
|
366
|
+
source: Inspection.Subject | undefined,
|
|
367
|
+
causedBy: Inspection.Causation | undefined
|
|
368
|
+
): Effect.Effect<void, StoppedError> =>
|
|
369
|
+
"inspectionSubject" in target && "sendInspected" in target && typeof target.sendInspected === "function"
|
|
370
|
+
? target.sendInspected(event, source, causedBy)
|
|
371
|
+
: target.send(event)
|
|
372
|
+
|
|
331
373
|
export interface ProcessScope<Event> {
|
|
332
374
|
readonly self: ProcessAddress<Event>
|
|
333
375
|
readonly parent: ProcessAddress<unknown> | undefined
|
|
@@ -341,6 +383,11 @@ export interface ProcessScope<Event> {
|
|
|
341
383
|
readonly stopChild: (child: ChildSelector) => Effect.Effect<void>
|
|
342
384
|
/** @internal */
|
|
343
385
|
readonly failCause: (cause: Cause.Cause<unknown>) => Effect.Effect<void>
|
|
386
|
+
/** @internal */
|
|
387
|
+
readonly inspectInitial: (
|
|
388
|
+
initialEntryPaths: ReadonlyArray<string>,
|
|
389
|
+
microsteps?: ReadonlyArray<unknown>
|
|
390
|
+
) => void
|
|
344
391
|
}
|
|
345
392
|
|
|
346
393
|
export interface ProcessContext<State, Event> extends ProcessScope<Event> {
|
|
@@ -493,6 +540,11 @@ export interface ProcessLogic<
|
|
|
493
540
|
> {
|
|
494
541
|
/** @internal */
|
|
495
542
|
readonly execution?: ProcessExecution<State, Event, Error, Requirements, Output, InitialError>
|
|
543
|
+
/** @internal */
|
|
544
|
+
readonly inspection?: {
|
|
545
|
+
readonly kind: Inspection.Subject["kind"]
|
|
546
|
+
readonly definition?: MachineDefinition.Any
|
|
547
|
+
}
|
|
496
548
|
initial(scope: ProcessScope<Event>): Effect.Effect<State, InitialError, Requirements>
|
|
497
549
|
run(context: ProcessContext<State, Event>): Effect.Effect<Output, Error, Requirements>
|
|
498
550
|
}
|
|
@@ -613,6 +665,7 @@ export const watch = <State, Event, Error = never, Output = never>(
|
|
|
613
665
|
|
|
614
666
|
interface ProcessRuntime {
|
|
615
667
|
readonly nextSessionId: Effect.Effect<string>
|
|
668
|
+
inspection?: InspectionRuntime.Runtime
|
|
616
669
|
}
|
|
617
670
|
|
|
618
671
|
const makeProcessRuntime: Effect.Effect<ProcessRuntime> = Effect.sync(() => {
|
|
@@ -622,6 +675,85 @@ const makeProcessRuntime: Effect.Effect<ProcessRuntime> = Effect.sync(() => {
|
|
|
622
675
|
}
|
|
623
676
|
})
|
|
624
677
|
|
|
678
|
+
const inspectionSubject = (
|
|
679
|
+
logic: ProcessLogic<any, any, any, any, any, any>,
|
|
680
|
+
id: string,
|
|
681
|
+
sessionId: string
|
|
682
|
+
): Inspection.Subject => ({
|
|
683
|
+
id,
|
|
684
|
+
sessionId,
|
|
685
|
+
kind: logic.inspection?.kind ?? "Logic"
|
|
686
|
+
})
|
|
687
|
+
|
|
688
|
+
const messageCausation = (
|
|
689
|
+
message: ProcessMessage<unknown> | undefined,
|
|
690
|
+
initializing: boolean
|
|
691
|
+
): Inspection.Causation | undefined =>
|
|
692
|
+
initializing
|
|
693
|
+
? { _tag: "Initialization" }
|
|
694
|
+
: message !== undefined && isAcknowledgedMessage(message) && message.inspection !== undefined
|
|
695
|
+
? { _tag: "Macrostep", macrostepId: message.inspection.macrostepId }
|
|
696
|
+
: undefined
|
|
697
|
+
|
|
698
|
+
const makeInspectedMessage = <Event>(
|
|
699
|
+
inspection: InspectionRuntime.Runtime,
|
|
700
|
+
subject: Inspection.Subject,
|
|
701
|
+
event: Event,
|
|
702
|
+
source: Inspection.Subject | undefined,
|
|
703
|
+
causedBy: Inspection.Causation | undefined,
|
|
704
|
+
deferred?: Deferred.Deferred<AcknowledgedDelivery<unknown>, unknown>
|
|
705
|
+
): AcknowledgedMessage<Event> => {
|
|
706
|
+
const deliveryId = inspection.nextDeliveryId()
|
|
707
|
+
const macrostepId = inspection.nextMacrostepId()
|
|
708
|
+
const inspected: InspectedDelivery = {
|
|
709
|
+
deliveryId,
|
|
710
|
+
macrostepId,
|
|
711
|
+
source,
|
|
712
|
+
event,
|
|
713
|
+
causedBy,
|
|
714
|
+
complete: (delivery) => {
|
|
715
|
+
const microsteps = InspectionRuntime.microsteps(delivery.plan)
|
|
716
|
+
inspection.publishUnsafe({
|
|
717
|
+
_tag: "EventProcessed",
|
|
718
|
+
subject,
|
|
719
|
+
macrostepId,
|
|
720
|
+
deliveryId,
|
|
721
|
+
source,
|
|
722
|
+
event,
|
|
723
|
+
before: { status: "active", state: delivery.before },
|
|
724
|
+
after: { status: "active", state: delivery.after },
|
|
725
|
+
handled: microsteps.some((microstep) => microstep.transitions.length > 0),
|
|
726
|
+
configurationChanged: microsteps.some((microstep) => microstep.changed),
|
|
727
|
+
microsteps
|
|
728
|
+
})
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return {
|
|
732
|
+
[AcknowledgedMessageTypeId]: true,
|
|
733
|
+
event,
|
|
734
|
+
...(deferred === undefined ? undefined : { deferred }),
|
|
735
|
+
inspection: inspected
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
const publishInspectedSent = (
|
|
740
|
+
inspection: InspectionRuntime.Runtime,
|
|
741
|
+
subject: Inspection.Subject,
|
|
742
|
+
message: ProcessMessage<unknown>
|
|
743
|
+
): void => {
|
|
744
|
+
if (!isAcknowledgedMessage(message) || message.inspection === undefined) return
|
|
745
|
+
const delivery = message.inspection
|
|
746
|
+
inspection.publishUnsafe({
|
|
747
|
+
_tag: "EventSent",
|
|
748
|
+
subject,
|
|
749
|
+
deliveryId: delivery.deliveryId,
|
|
750
|
+
source: delivery.source,
|
|
751
|
+
target: InspectionRuntime.endpoint(subject),
|
|
752
|
+
event: delivery.event,
|
|
753
|
+
causedBy: delivery.causedBy
|
|
754
|
+
})
|
|
755
|
+
}
|
|
756
|
+
|
|
625
757
|
interface StartInternalOptions {
|
|
626
758
|
readonly detached?: boolean
|
|
627
759
|
readonly id?: string
|
|
@@ -642,6 +774,14 @@ interface StartInternalOptions {
|
|
|
642
774
|
readonly parent?: ProcessAddress<unknown>
|
|
643
775
|
readonly runtime: ProcessRuntime
|
|
644
776
|
readonly sendParent?: (event: unknown) => Effect.Effect<void, StoppedError>
|
|
777
|
+
readonly origin?: Inspection.Origin
|
|
778
|
+
readonly activity?: {
|
|
779
|
+
readonly id: string
|
|
780
|
+
readonly owner: Inspection.Subject
|
|
781
|
+
readonly ownerPath: string
|
|
782
|
+
readonly kind: Inspection.Activity["kind"]
|
|
783
|
+
}
|
|
784
|
+
readonly inspectionRoot?: boolean
|
|
645
785
|
}
|
|
646
786
|
|
|
647
787
|
/** @internal */
|
|
@@ -653,7 +793,8 @@ export interface OwnedChildSpawnOptions {
|
|
|
653
793
|
readonly descriptor?: ChildDescriptor
|
|
654
794
|
readonly onOutcome: (
|
|
655
795
|
isCurrent: () => boolean,
|
|
656
|
-
outcome: RuntimeOutcome<any, any, any
|
|
796
|
+
outcome: RuntimeOutcome<any, any, any>,
|
|
797
|
+
activitySessionId: string | undefined
|
|
657
798
|
) => Effect.Effect<void>
|
|
658
799
|
readonly onSnapshot?: (
|
|
659
800
|
isCurrent: () => boolean,
|
|
@@ -663,6 +804,7 @@ export interface OwnedChildSpawnOptions {
|
|
|
663
804
|
isCurrent: () => boolean,
|
|
664
805
|
event: unknown
|
|
665
806
|
) => Effect.Effect<void, StoppedError>
|
|
807
|
+
readonly activityKind?: Inspection.Activity["kind"]
|
|
666
808
|
}
|
|
667
809
|
|
|
668
810
|
/** @internal */
|
|
@@ -684,7 +826,12 @@ interface ChildRuntime {
|
|
|
684
826
|
readonly changes: <ChildState, ChildEvent, ChildError, ChildOutput>(
|
|
685
827
|
child: ChildSelector
|
|
686
828
|
) => Stream.Stream<Option.Option<MachineRef<ChildState, ChildEvent, ChildError, ChildOutput>>>
|
|
687
|
-
readonly sendTo: (
|
|
829
|
+
readonly sendTo: (
|
|
830
|
+
child: ChildSelector,
|
|
831
|
+
event: unknown,
|
|
832
|
+
source?: Inspection.Subject,
|
|
833
|
+
causedBy?: Inspection.Causation
|
|
834
|
+
) => Effect.Effect<void, StoppedError>
|
|
688
835
|
readonly stop: (child: ChildSelector) => Effect.Effect<void>
|
|
689
836
|
readonly owned: OwnedChildRuntime
|
|
690
837
|
}
|
|
@@ -737,13 +884,15 @@ class OwnedChildRuntimeImpl implements OwnedChildRuntime {
|
|
|
737
884
|
})
|
|
738
885
|
const parent: ProcessAddress<unknown> = {
|
|
739
886
|
...this.self,
|
|
740
|
-
send: (event) => options.sendParent(isCurrent, event)
|
|
887
|
+
send: (event) => options.sendParent(isCurrent, event),
|
|
888
|
+
sendInspected: (event, source, causedBy) =>
|
|
889
|
+
isCurrent() ? sendMachineTarget(this.self, event, source, causedBy) : Effect.void
|
|
741
890
|
}
|
|
742
891
|
const startOptions: StartInternalOptions = {
|
|
743
892
|
detached: true,
|
|
744
893
|
id: options.id,
|
|
745
894
|
sendParent: (event) => options.sendParent(isCurrent, event),
|
|
746
|
-
onOutcome: (outcome) => options.onOutcome(isCurrent, outcome),
|
|
895
|
+
onOutcome: (outcome) => options.onOutcome(isCurrent, outcome, startedChild?.sessionId),
|
|
747
896
|
...(options.onSnapshot === undefined
|
|
748
897
|
? undefined
|
|
749
898
|
: { onSnapshot: (snapshot) => options.onSnapshot!(isCurrent, snapshot) }),
|
|
@@ -754,7 +903,19 @@ class OwnedChildRuntimeImpl implements OwnedChildRuntime {
|
|
|
754
903
|
onStopSync: () => unregisterChild(this.registry, options.id, token),
|
|
755
904
|
skipStoppedOutcome: true,
|
|
756
905
|
parent,
|
|
757
|
-
runtime: this.runtime
|
|
906
|
+
runtime: this.runtime,
|
|
907
|
+
origin: { _tag: "Invoke", ownerPath: options.path, invokeId: options.duplicateId },
|
|
908
|
+
...(options.activityKind === undefined || this.runtime.inspection === undefined ||
|
|
909
|
+
this.self.inspectionSubject === undefined
|
|
910
|
+
? undefined
|
|
911
|
+
: {
|
|
912
|
+
activity: {
|
|
913
|
+
id: options.duplicateId,
|
|
914
|
+
owner: this.self.inspectionSubject,
|
|
915
|
+
ownerPath: options.path,
|
|
916
|
+
kind: options.activityKind
|
|
917
|
+
}
|
|
918
|
+
})
|
|
758
919
|
}
|
|
759
920
|
const execution = logic.execution
|
|
760
921
|
const synchronous = this.services !== undefined && options.onSnapshot === undefined &&
|
|
@@ -816,6 +977,8 @@ class OwnedChildRuntimeImpl implements OwnedChildRuntime {
|
|
|
816
977
|
|
|
817
978
|
const noChildChanges = Stream.succeed(Option.none()).pipe(Stream.concat(Stream.never))
|
|
818
979
|
const noParentSend = (_event: unknown): Effect.Effect<void, StoppedError> => Effect.void
|
|
980
|
+
const noInspectInitial = (_paths: ReadonlyArray<string>, _microsteps?: ReadonlyArray<unknown>): void => {}
|
|
981
|
+
const noCausation = (): Inspection.Causation | undefined => undefined
|
|
819
982
|
const EmissionsClosed: unique symbol = Symbol("effect/Machine/EmissionsClosed")
|
|
820
983
|
|
|
821
984
|
type LazyEmissions = PubSub.PubSub<unknown> | typeof EmissionsClosed | undefined
|
|
@@ -996,7 +1159,12 @@ const makeChildRuntimeSync = (
|
|
|
996
1159
|
)
|
|
997
1160
|
}
|
|
998
1161
|
|
|
999
|
-
const sendTo = (
|
|
1162
|
+
const sendTo = (
|
|
1163
|
+
child: ChildSelector,
|
|
1164
|
+
event: unknown,
|
|
1165
|
+
source?: Inspection.Subject,
|
|
1166
|
+
causedBy?: Inspection.Causation
|
|
1167
|
+
): Effect.Effect<void, StoppedError> => {
|
|
1000
1168
|
const id = typeof child === "string" ? child : child.id
|
|
1001
1169
|
return Effect.suspend(() => {
|
|
1002
1170
|
if (registry.closed) {
|
|
@@ -1004,7 +1172,7 @@ const makeChildRuntimeSync = (
|
|
|
1004
1172
|
}
|
|
1005
1173
|
const entry = registry.children.get(id)
|
|
1006
1174
|
return entry !== undefined && matchesChild(entry, child)
|
|
1007
|
-
? entry.ref
|
|
1175
|
+
? sendMachineTarget(entry.ref, event, source, causedBy)
|
|
1008
1176
|
: Effect.void
|
|
1009
1177
|
})
|
|
1010
1178
|
}
|
|
@@ -1100,7 +1268,8 @@ const makeChildRuntimeSync = (
|
|
|
1100
1268
|
),
|
|
1101
1269
|
onStop: unregister(key, token),
|
|
1102
1270
|
parent: self,
|
|
1103
|
-
runtime
|
|
1271
|
+
runtime,
|
|
1272
|
+
origin: { _tag: "Spawn", address: spawnOptions?.id }
|
|
1104
1273
|
}).pipe(
|
|
1105
1274
|
Effect.onExit((exit) =>
|
|
1106
1275
|
Exit.isFailure(exit)
|
|
@@ -1172,6 +1341,13 @@ const startGenericInternal: <
|
|
|
1172
1341
|
|
|
1173
1342
|
const sessionId = options.sessionId ?? (yield* runtime.nextSessionId)
|
|
1174
1343
|
const id = requestedId ?? sessionId
|
|
1344
|
+
const inspector = runtime.inspection
|
|
1345
|
+
const subject = inspector === undefined ? undefined : inspectionSubject(logic, id, sessionId)
|
|
1346
|
+
const activity: Inspection.Activity | undefined = inspector === undefined || options.activity === undefined
|
|
1347
|
+
? undefined
|
|
1348
|
+
: { ...options.activity, sessionId }
|
|
1349
|
+
let initialEntryPaths: ReadonlyArray<string> | undefined
|
|
1350
|
+
let initialMicrosteps: ReadonlyArray<unknown> | undefined
|
|
1175
1351
|
const queue = yield* Queue.unbounded<ProcessMessage<Event>>()
|
|
1176
1352
|
const emissions = options.emissions ?? makeEmissionRuntime()
|
|
1177
1353
|
const termination = yield* Deferred.make<ProcessTermination>()
|
|
@@ -1180,6 +1356,26 @@ const startGenericInternal: <
|
|
|
1180
1356
|
let initializing = true
|
|
1181
1357
|
let inFlightMessage: ProcessMessage<Event> | undefined
|
|
1182
1358
|
const requestStop = Deferred.succeed(termination, { _tag: "Stopped" }).pipe(Effect.asVoid)
|
|
1359
|
+
const offerDirect = (message: ProcessMessage<Event>): Effect.Effect<void, StoppedError> =>
|
|
1360
|
+
Queue.offer(queue, message).pipe(
|
|
1361
|
+
Effect.flatMap((accepted) => accepted ? Effect.void : Effect.fail(new StoppedError()))
|
|
1362
|
+
)
|
|
1363
|
+
const offerInspected: InspectedOffer<Event> | undefined = inspector === undefined ? undefined : (
|
|
1364
|
+
event,
|
|
1365
|
+
source,
|
|
1366
|
+
causedBy,
|
|
1367
|
+
deferred?: Deferred.Deferred<AcknowledgedDelivery<unknown>, unknown>
|
|
1368
|
+
) =>
|
|
1369
|
+
Effect.suspend(() => {
|
|
1370
|
+
const message: ProcessMessage<Event> = inspector.isActive()
|
|
1371
|
+
? makeInspectedMessage(inspector, subject!, event, source, causedBy, deferred)
|
|
1372
|
+
: deferred === undefined
|
|
1373
|
+
? event
|
|
1374
|
+
: { [AcknowledgedMessageTypeId]: true as const, event, deferred }
|
|
1375
|
+
return offerDirect(message).pipe(
|
|
1376
|
+
Effect.tap(() => Effect.sync(() => publishInspectedSent(inspector, subject!, message)))
|
|
1377
|
+
)
|
|
1378
|
+
})
|
|
1183
1379
|
const self: ProcessAddress<Event> = {
|
|
1184
1380
|
id,
|
|
1185
1381
|
sessionId,
|
|
@@ -1193,10 +1389,12 @@ const startGenericInternal: <
|
|
|
1193
1389
|
? requestStop
|
|
1194
1390
|
: requestStop.pipe(Effect.andThen(Effect.never))
|
|
1195
1391
|
),
|
|
1196
|
-
send:
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1392
|
+
send: inspector === undefined
|
|
1393
|
+
? (event) => offerDirect(event)
|
|
1394
|
+
: (event) => offerInspected!(event, undefined, undefined),
|
|
1395
|
+
...(inspector === undefined
|
|
1396
|
+
? undefined
|
|
1397
|
+
: { inspectionSubject: subject!, sendInspected: offerInspected! })
|
|
1200
1398
|
}
|
|
1201
1399
|
const sendAcknowledged:
|
|
1202
1400
|
| ((event: Event) => Effect.Effect<AcknowledgedDelivery<State>, Error | StoppedError>)
|
|
@@ -1205,19 +1403,12 @@ const startGenericInternal: <
|
|
|
1205
1403
|
: (event) =>
|
|
1206
1404
|
Effect.uninterruptibleMask((restore) =>
|
|
1207
1405
|
Deferred.make<AcknowledgedDelivery<unknown>, unknown>().pipe(
|
|
1208
|
-
Effect.flatMap((deferred) =>
|
|
1209
|
-
|
|
1210
|
-
[AcknowledgedMessageTypeId]: true as const,
|
|
1211
|
-
event,
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
Effect.flatMap((accepted) =>
|
|
1215
|
-
accepted
|
|
1216
|
-
? restore(Deferred.await(deferred))
|
|
1217
|
-
: Effect.fail(new StoppedError())
|
|
1218
|
-
)
|
|
1219
|
-
)
|
|
1220
|
-
),
|
|
1406
|
+
Effect.flatMap((deferred) => {
|
|
1407
|
+
const offered = inspector === undefined
|
|
1408
|
+
? offerDirect({ [AcknowledgedMessageTypeId]: true as const, event, deferred })
|
|
1409
|
+
: offerInspected!(event, undefined, undefined, deferred)
|
|
1410
|
+
return offered.pipe(Effect.andThen(restore(Deferred.await(deferred))))
|
|
1411
|
+
}),
|
|
1221
1412
|
Effect.map((delivery) => delivery as AcknowledgedDelivery<State>)
|
|
1222
1413
|
)
|
|
1223
1414
|
) as Effect.Effect<AcknowledgedDelivery<State>, Error | StoppedError>
|
|
@@ -1242,29 +1433,87 @@ const startGenericInternal: <
|
|
|
1242
1433
|
stop: stopChild
|
|
1243
1434
|
} = yield* makeChildRuntime(self, runtime))
|
|
1244
1435
|
}
|
|
1245
|
-
const cleanupStartupFailure = <A, E>(exit: Exit.Exit<A, E>): Effect.Effect<void> =>
|
|
1246
|
-
Exit.
|
|
1247
|
-
|
|
1248
|
-
|
|
1436
|
+
const cleanupStartupFailure = <A, E>(exit: Exit.Exit<A, E>): Effect.Effect<void> => {
|
|
1437
|
+
if (Exit.isSuccess(exit)) return Effect.void
|
|
1438
|
+
if (inspector !== undefined) {
|
|
1439
|
+
inspector.publishUnsafe(
|
|
1440
|
+
activity === undefined
|
|
1441
|
+
? { _tag: "StartFailed", subject: subject!, cause: exit.cause }
|
|
1442
|
+
: { _tag: "ActivityStopped", subject: activity.owner, activity, exit }
|
|
1443
|
+
)
|
|
1444
|
+
}
|
|
1445
|
+
return closeChildren(exit).pipe(
|
|
1446
|
+
Effect.andThen(emissions.close()),
|
|
1447
|
+
Effect.andThen(options.inspectionRoot === true && inspector !== undefined ? inspector.close : Effect.void)
|
|
1448
|
+
)
|
|
1449
|
+
}
|
|
1249
1450
|
const cleanup = onStopSync === undefined ? onStop ?? Effect.void : Effect.sync(onStopSync)
|
|
1250
|
-
const
|
|
1451
|
+
const currentCausation = inspector === undefined
|
|
1452
|
+
? noCausation
|
|
1453
|
+
: (): Inspection.Causation | undefined => messageCausation(inFlightMessage, initializing)
|
|
1454
|
+
const sendParent = overrideSendParent ?? (parent === undefined
|
|
1455
|
+
? noParentSend
|
|
1456
|
+
: inspector === undefined
|
|
1457
|
+
? parent.send
|
|
1458
|
+
: (event) => sendMachineTarget(parent, event, subject, currentCausation()))
|
|
1459
|
+
const emit = inspector === undefined
|
|
1460
|
+
? emissions.emit
|
|
1461
|
+
: (event: unknown) =>
|
|
1462
|
+
emissions.emit(event).pipe(
|
|
1463
|
+
Effect.tap(() =>
|
|
1464
|
+
Effect.sync(() =>
|
|
1465
|
+
inspector.publishUnsafe({
|
|
1466
|
+
_tag: "Emitted",
|
|
1467
|
+
subject: subject!,
|
|
1468
|
+
emission: event,
|
|
1469
|
+
causedBy: currentCausation()
|
|
1470
|
+
})
|
|
1471
|
+
)
|
|
1472
|
+
)
|
|
1473
|
+
)
|
|
1474
|
+
const sendToTarget: ProcessScope<Event>["sendTo"] = inspector === undefined
|
|
1475
|
+
? ((target: unknown, event: unknown) =>
|
|
1476
|
+
isMachineTarget(target) ? target.send(event) : sendTo(target as ChildSelector, event)) as ProcessScope<
|
|
1477
|
+
Event
|
|
1478
|
+
>["sendTo"]
|
|
1479
|
+
: ((target: unknown, event: unknown) =>
|
|
1480
|
+
isMachineTarget(target)
|
|
1481
|
+
? sendMachineTarget(target, event, subject, currentCausation())
|
|
1482
|
+
: sendTo(target as ChildSelector, event, subject, currentCausation())) as ProcessScope<Event>["sendTo"]
|
|
1251
1483
|
|
|
1252
1484
|
const scope: ProcessScope<Event> = {
|
|
1253
1485
|
self,
|
|
1254
1486
|
parent,
|
|
1255
1487
|
spawn,
|
|
1256
1488
|
sendParent,
|
|
1257
|
-
emit
|
|
1258
|
-
sendTo:
|
|
1259
|
-
isProcessAddress(target) ? target.send(event) : sendTo(target as ChildSelector, event)) as ProcessScope<
|
|
1260
|
-
Event
|
|
1261
|
-
>["sendTo"],
|
|
1489
|
+
emit,
|
|
1490
|
+
sendTo: sendToTarget,
|
|
1262
1491
|
stopChild,
|
|
1263
1492
|
failCause: (cause) =>
|
|
1264
1493
|
Deferred.succeed(termination, {
|
|
1265
1494
|
_tag: "Failure",
|
|
1266
1495
|
cause: cause as Cause.Cause<Error>
|
|
1267
|
-
}).pipe(Effect.asVoid)
|
|
1496
|
+
}).pipe(Effect.asVoid),
|
|
1497
|
+
inspectInitial: inspector === undefined
|
|
1498
|
+
? noInspectInitial
|
|
1499
|
+
: (paths, microsteps = []) => {
|
|
1500
|
+
initialEntryPaths = paths
|
|
1501
|
+
initialMicrosteps = microsteps
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
if (inspector !== undefined) {
|
|
1506
|
+
inspector.publishUnsafe(
|
|
1507
|
+
activity === undefined
|
|
1508
|
+
? {
|
|
1509
|
+
_tag: "Created",
|
|
1510
|
+
subject: subject!,
|
|
1511
|
+
parent: parent?.inspectionSubject,
|
|
1512
|
+
origin: options.origin ?? { _tag: "Root" },
|
|
1513
|
+
definition: logic.inspection?.definition
|
|
1514
|
+
}
|
|
1515
|
+
: { _tag: "ActivityStarted", subject: activity.owner, activity }
|
|
1516
|
+
)
|
|
1268
1517
|
}
|
|
1269
1518
|
|
|
1270
1519
|
const initial = yield* logic.initial(scope).pipe(
|
|
@@ -1282,6 +1531,15 @@ const startGenericInternal: <
|
|
|
1282
1531
|
state: initial
|
|
1283
1532
|
}
|
|
1284
1533
|
})
|
|
1534
|
+
if (activity === undefined) {
|
|
1535
|
+
inspector?.publishUnsafe({
|
|
1536
|
+
_tag: "Initialized",
|
|
1537
|
+
subject: subject!,
|
|
1538
|
+
snapshot: { status: "active", state: initial },
|
|
1539
|
+
initialEntryPaths: initialEntryPaths ?? [],
|
|
1540
|
+
microsteps: InspectionRuntime.microsteps({ microsteps: initialMicrosteps ?? [] })
|
|
1541
|
+
})
|
|
1542
|
+
}
|
|
1285
1543
|
const publishSnapshot: (
|
|
1286
1544
|
snapshot: VersionedSnapshot<State, Error, Output>
|
|
1287
1545
|
) => Effect.Effect<VersionedSnapshot<State, Error, Output>> = onSnapshot === undefined
|
|
@@ -1296,9 +1554,7 @@ const startGenericInternal: <
|
|
|
1296
1554
|
const runtimeSnapshot = snapshot.snapshot
|
|
1297
1555
|
return runtimeSnapshot.status !== "active"
|
|
1298
1556
|
? publish
|
|
1299
|
-
: publish.pipe(Effect.tap(() =>
|
|
1300
|
-
notifyActiveSnapshot(onSnapshot, runtimeSnapshot)
|
|
1301
|
-
))
|
|
1557
|
+
: publish.pipe(Effect.tap(() => notifyActiveSnapshot(onSnapshot, runtimeSnapshot)))
|
|
1302
1558
|
}
|
|
1303
1559
|
|
|
1304
1560
|
const completeChanges = (
|
|
@@ -1402,7 +1658,7 @@ const startGenericInternal: <
|
|
|
1402
1658
|
Effect.asVoid
|
|
1403
1659
|
)
|
|
1404
1660
|
|
|
1405
|
-
const
|
|
1661
|
+
const setActiveStateDirect = (state: State) =>
|
|
1406
1662
|
updateSnapshot((snapshot) =>
|
|
1407
1663
|
Effect.succeed(
|
|
1408
1664
|
snapshot.status === "active"
|
|
@@ -1414,6 +1670,40 @@ const startGenericInternal: <
|
|
|
1414
1670
|
)
|
|
1415
1671
|
).pipe(Effect.asVoid)
|
|
1416
1672
|
|
|
1673
|
+
const setActiveState = inspector === undefined ?
|
|
1674
|
+
setActiveStateDirect :
|
|
1675
|
+
(state: State) =>
|
|
1676
|
+
SynchronizedRef.get(current).pipe(
|
|
1677
|
+
Effect.flatMap((before) =>
|
|
1678
|
+
updateSnapshot((snapshot) =>
|
|
1679
|
+
Effect.succeed(
|
|
1680
|
+
snapshot.status === "active"
|
|
1681
|
+
? {
|
|
1682
|
+
status: "active",
|
|
1683
|
+
state
|
|
1684
|
+
}
|
|
1685
|
+
: undefined
|
|
1686
|
+
)
|
|
1687
|
+
).pipe(
|
|
1688
|
+
Effect.tap((after) =>
|
|
1689
|
+
Effect.sync(() => {
|
|
1690
|
+
if (logic.inspection?.kind === "Machine" || after === undefined) return
|
|
1691
|
+
inspector.publishUnsafe({
|
|
1692
|
+
_tag: "StateChanged",
|
|
1693
|
+
subject: subject!,
|
|
1694
|
+
before: before.snapshot.state,
|
|
1695
|
+
after: state,
|
|
1696
|
+
causedByDeliveryId: inFlightMessage !== undefined && isAcknowledgedMessage(inFlightMessage)
|
|
1697
|
+
? inFlightMessage.inspection?.deliveryId
|
|
1698
|
+
: undefined
|
|
1699
|
+
})
|
|
1700
|
+
})
|
|
1701
|
+
)
|
|
1702
|
+
)
|
|
1703
|
+
),
|
|
1704
|
+
Effect.asVoid
|
|
1705
|
+
)
|
|
1706
|
+
|
|
1417
1707
|
const terminalizeWith = (
|
|
1418
1708
|
snapshot: RuntimeSnapshot<State, Error, Output>,
|
|
1419
1709
|
exit: Exit.Exit<unknown, unknown>,
|
|
@@ -1426,6 +1716,22 @@ const startGenericInternal: <
|
|
|
1426
1716
|
Effect.exit,
|
|
1427
1717
|
Effect.asVoid
|
|
1428
1718
|
)
|
|
1719
|
+
const closeEmissionsAndInspect = inspector === undefined
|
|
1720
|
+
? emissions.close()
|
|
1721
|
+
: emissions.close().pipe(
|
|
1722
|
+
Effect.andThen(Effect.sync(() =>
|
|
1723
|
+
inspector.publishUnsafe(
|
|
1724
|
+
activity === undefined
|
|
1725
|
+
? { _tag: "Terminated", subject: subject!, snapshot }
|
|
1726
|
+
: {
|
|
1727
|
+
_tag: "ActivityStopped",
|
|
1728
|
+
subject: activity.owner,
|
|
1729
|
+
activity,
|
|
1730
|
+
exit: snapshot.status === "stopped" ? Exit.interrupt() : exit
|
|
1731
|
+
}
|
|
1732
|
+
)
|
|
1733
|
+
))
|
|
1734
|
+
)
|
|
1429
1735
|
return Effect.uninterruptible(
|
|
1430
1736
|
Effect.sync(() => {
|
|
1431
1737
|
while (true) {
|
|
@@ -1437,7 +1743,7 @@ const startGenericInternal: <
|
|
|
1437
1743
|
Effect.andThen(Queue.shutdown(queue)),
|
|
1438
1744
|
Effect.andThen(closeChildren(exit)),
|
|
1439
1745
|
Effect.andThen(setAndPublishSnapshot(snapshot)),
|
|
1440
|
-
Effect.andThen(
|
|
1746
|
+
Effect.andThen(closeEmissionsAndInspect),
|
|
1441
1747
|
Effect.andThen(Effect.sync(() => {
|
|
1442
1748
|
if (Exit.isFailure(exit)) {
|
|
1443
1749
|
failAcknowledgedMessage(inFlightMessage, exit.cause)
|
|
@@ -1448,6 +1754,7 @@ const startGenericInternal: <
|
|
|
1448
1754
|
})),
|
|
1449
1755
|
Effect.andThen(notifyOutcome),
|
|
1450
1756
|
Effect.andThen(cleanup),
|
|
1757
|
+
Effect.andThen(options.inspectionRoot === true && inspector !== undefined ? inspector.close : Effect.void),
|
|
1451
1758
|
Effect.andThen(completeDone)
|
|
1452
1759
|
)
|
|
1453
1760
|
)
|
|
@@ -1530,25 +1837,79 @@ const startGenericInternal: <
|
|
|
1530
1837
|
inFlightMessage = undefined
|
|
1531
1838
|
}
|
|
1532
1839
|
}
|
|
1840
|
+
const receive = inspector === undefined || logic.execution?._tag === "Compiled"
|
|
1841
|
+
? Queue.take(queue).pipe(Effect.map(messageEvent))
|
|
1842
|
+
: Queue.take(queue).pipe(
|
|
1843
|
+
Effect.tap((message) =>
|
|
1844
|
+
Effect.sync(() => {
|
|
1845
|
+
inFlightMessage = message
|
|
1846
|
+
})
|
|
1847
|
+
),
|
|
1848
|
+
Effect.map(messageEvent)
|
|
1849
|
+
)
|
|
1850
|
+
const poll = inspector === undefined || logic.execution?._tag === "Compiled"
|
|
1851
|
+
? Queue.poll(queue).pipe(Effect.map(Option.map(messageEvent)))
|
|
1852
|
+
: Queue.poll(queue).pipe(
|
|
1853
|
+
Effect.tap((message) =>
|
|
1854
|
+
Effect.sync(() => {
|
|
1855
|
+
if (Option.isSome(message)) inFlightMessage = message.value
|
|
1856
|
+
})
|
|
1857
|
+
),
|
|
1858
|
+
Effect.map(Option.map(messageEvent))
|
|
1859
|
+
)
|
|
1860
|
+
const updateStateDirect = <E2, R2>(f: (state: State) => Effect.Effect<State, E2, R2>) =>
|
|
1861
|
+
updateSnapshot((snapshot) =>
|
|
1862
|
+
snapshot.status === "active"
|
|
1863
|
+
? f(snapshot.state).pipe(
|
|
1864
|
+
Effect.map((state) => ({
|
|
1865
|
+
status: "active" as const,
|
|
1866
|
+
state
|
|
1867
|
+
}))
|
|
1868
|
+
)
|
|
1869
|
+
: Effect.succeed(undefined)
|
|
1870
|
+
).pipe(Effect.asVoid)
|
|
1871
|
+
const updateState: ProcessContext<State, Event>["updateState"] = inspector === undefined
|
|
1872
|
+
? updateStateDirect
|
|
1873
|
+
: (f) =>
|
|
1874
|
+
SynchronizedRef.get(current).pipe(
|
|
1875
|
+
Effect.flatMap((before) =>
|
|
1876
|
+
updateSnapshot((snapshot) =>
|
|
1877
|
+
snapshot.status === "active"
|
|
1878
|
+
? f(snapshot.state).pipe(
|
|
1879
|
+
Effect.map((state) => ({
|
|
1880
|
+
status: "active" as const,
|
|
1881
|
+
state
|
|
1882
|
+
}))
|
|
1883
|
+
)
|
|
1884
|
+
: Effect.succeed(undefined)
|
|
1885
|
+
).pipe(
|
|
1886
|
+
Effect.tap((after) =>
|
|
1887
|
+
Effect.sync(() => {
|
|
1888
|
+
if (logic.inspection?.kind === "Machine" || after?.status !== "active") return
|
|
1889
|
+
inspector.publishUnsafe({
|
|
1890
|
+
_tag: "StateChanged",
|
|
1891
|
+
subject: subject!,
|
|
1892
|
+
before: before.snapshot.state,
|
|
1893
|
+
after: after.state,
|
|
1894
|
+
causedByDeliveryId: inFlightMessage !== undefined && isAcknowledgedMessage(inFlightMessage)
|
|
1895
|
+
? inFlightMessage.inspection?.deliveryId
|
|
1896
|
+
: undefined
|
|
1897
|
+
})
|
|
1898
|
+
})
|
|
1899
|
+
)
|
|
1900
|
+
)
|
|
1901
|
+
),
|
|
1902
|
+
Effect.asVoid
|
|
1903
|
+
)
|
|
1533
1904
|
const context: ProcessContext<State, Event> = {
|
|
1534
1905
|
...scope,
|
|
1535
1906
|
...(logic.execution?._tag === "Compiled" && !logic.execution.childless ? { ownedChildren } : undefined),
|
|
1536
1907
|
...acknowledgedContext,
|
|
1537
|
-
receive
|
|
1538
|
-
poll
|
|
1908
|
+
receive,
|
|
1909
|
+
poll,
|
|
1539
1910
|
state: SynchronizedRef.get(current).pipe(Effect.map((current) => current.snapshot.state)),
|
|
1540
1911
|
setState: setActiveState,
|
|
1541
|
-
updateState
|
|
1542
|
-
updateSnapshot((snapshot) =>
|
|
1543
|
-
snapshot.status === "active"
|
|
1544
|
-
? f(snapshot.state).pipe(
|
|
1545
|
-
Effect.map((state) => ({
|
|
1546
|
-
status: "active" as const,
|
|
1547
|
-
state
|
|
1548
|
-
}))
|
|
1549
|
-
)
|
|
1550
|
-
: Effect.succeed(undefined)
|
|
1551
|
-
).pipe(Effect.asVoid)
|
|
1912
|
+
updateState
|
|
1552
1913
|
}
|
|
1553
1914
|
|
|
1554
1915
|
const getOrCreateChanges = SynchronizedRef.modifyEffect(
|
|
@@ -1591,6 +1952,9 @@ const startGenericInternal: <
|
|
|
1591
1952
|
const ref: MachineRef<State, Event, Error, Output> = {
|
|
1592
1953
|
id,
|
|
1593
1954
|
sessionId,
|
|
1955
|
+
...(inspector === undefined
|
|
1956
|
+
? undefined
|
|
1957
|
+
: { inspectionSubject: subject!, sendInspected: offerInspected! }),
|
|
1594
1958
|
state: SynchronizedRef.get(current).pipe(Effect.map((current) => current.snapshot.state)),
|
|
1595
1959
|
snapshot: SynchronizedRef.get(current).pipe(Effect.map((current) => current.snapshot)),
|
|
1596
1960
|
changes: changesStream,
|
|
@@ -1715,7 +2079,15 @@ type CompiledRunState = "Initializing" | "Idle" | "Draining"
|
|
|
1715
2079
|
class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
1716
2080
|
readonly id: string
|
|
1717
2081
|
readonly sessionId: string
|
|
1718
|
-
readonly
|
|
2082
|
+
readonly inspectionSubject?: Inspection.Subject
|
|
2083
|
+
readonly send: (event: unknown) => Effect.Effect<void, StoppedError>
|
|
2084
|
+
sendInspected(
|
|
2085
|
+
event: unknown,
|
|
2086
|
+
source: Inspection.Subject | undefined,
|
|
2087
|
+
causedBy: Inspection.Causation | undefined
|
|
2088
|
+
): Effect.Effect<void, StoppedError> {
|
|
2089
|
+
return this.offerEvent(event, source, causedBy)
|
|
2090
|
+
}
|
|
1719
2091
|
[acknowledgedSend](
|
|
1720
2092
|
event: unknown
|
|
1721
2093
|
): Effect.Effect<AcknowledgedDelivery<unknown>, unknown | StoppedError> {
|
|
@@ -1750,6 +2122,10 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1750
2122
|
private inFlightMessage: ProcessMessage<unknown> | undefined
|
|
1751
2123
|
private readonly externalEmissions: EmissionRuntime | undefined
|
|
1752
2124
|
private emissionsPubSub: LazyEmissions
|
|
2125
|
+
private readonly activity?: Inspection.Activity
|
|
2126
|
+
private initialEntryPaths?: ReadonlyArray<string>
|
|
2127
|
+
private initialMicrosteps?: ReadonlyArray<unknown>
|
|
2128
|
+
private initializing?: boolean
|
|
1753
2129
|
|
|
1754
2130
|
constructor(
|
|
1755
2131
|
private readonly logic: ProcessLogic<any, any, any, any, any, any>,
|
|
@@ -1759,26 +2135,106 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1759
2135
|
) {
|
|
1760
2136
|
this.sessionId = sessionId
|
|
1761
2137
|
this.id = options.id ?? sessionId
|
|
2138
|
+
const inspector = options.runtime.inspection
|
|
2139
|
+
if (inspector !== undefined) {
|
|
2140
|
+
this.inspectionSubject = inspectionSubject(logic, this.id, sessionId)
|
|
2141
|
+
this.initializing = true
|
|
2142
|
+
if (options.activity !== undefined) this.activity = { ...options.activity, sessionId }
|
|
2143
|
+
}
|
|
1762
2144
|
this.externalEmissions = options.emissions
|
|
1763
|
-
this.send =
|
|
2145
|
+
this.send = inspector === undefined
|
|
2146
|
+
? (event) => this.offerMessage(event)
|
|
2147
|
+
: (event) => this.offerEvent(event, undefined, undefined)
|
|
1764
2148
|
this.address = {
|
|
1765
2149
|
id: this.id,
|
|
1766
2150
|
sessionId,
|
|
1767
2151
|
stop: Effect.suspend(() => this.stopFromProcess()),
|
|
1768
|
-
send: this.send
|
|
2152
|
+
send: this.send,
|
|
2153
|
+
...(inspector === undefined
|
|
2154
|
+
? undefined
|
|
2155
|
+
: {
|
|
2156
|
+
inspectionSubject: this.inspectionSubject!,
|
|
2157
|
+
sendInspected: (
|
|
2158
|
+
event: unknown,
|
|
2159
|
+
source: Inspection.Subject | undefined,
|
|
2160
|
+
causedBy: Inspection.Causation | undefined
|
|
2161
|
+
) => this.offerEvent(event, source, causedBy)
|
|
2162
|
+
})
|
|
1769
2163
|
}
|
|
1770
2164
|
}
|
|
1771
2165
|
|
|
2166
|
+
private get inspector(): InspectionRuntime.Runtime | undefined {
|
|
2167
|
+
return this.options.runtime.inspection
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
private causation(): Inspection.Causation | undefined {
|
|
2171
|
+
return messageCausation(this.inFlightMessage, this.initializing === true)
|
|
2172
|
+
}
|
|
2173
|
+
|
|
2174
|
+
private publishCreated(): void {
|
|
2175
|
+
const inspector = this.inspector
|
|
2176
|
+
const subject = this.inspectionSubject
|
|
2177
|
+
if (inspector === undefined || subject === undefined) return
|
|
2178
|
+
inspector.publishUnsafe(
|
|
2179
|
+
this.activity === undefined
|
|
2180
|
+
? {
|
|
2181
|
+
_tag: "Created",
|
|
2182
|
+
subject,
|
|
2183
|
+
parent: this.options.parent?.inspectionSubject,
|
|
2184
|
+
origin: this.options.origin ?? { _tag: "Root" },
|
|
2185
|
+
definition: this.logic.inspection?.definition
|
|
2186
|
+
}
|
|
2187
|
+
: { _tag: "ActivityStarted", subject: this.activity.owner, activity: this.activity }
|
|
2188
|
+
)
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
private publishInitialized(state: unknown): void {
|
|
2192
|
+
this.initializing = false
|
|
2193
|
+
if (this.activity !== undefined) return
|
|
2194
|
+
const inspector = this.inspector
|
|
2195
|
+
const subject = this.inspectionSubject
|
|
2196
|
+
if (inspector === undefined || subject === undefined) return
|
|
2197
|
+
inspector.publishUnsafe({
|
|
2198
|
+
_tag: "Initialized",
|
|
2199
|
+
subject,
|
|
2200
|
+
snapshot: { status: "active", state },
|
|
2201
|
+
initialEntryPaths: this.initialEntryPaths ?? [],
|
|
2202
|
+
microsteps: InspectionRuntime.microsteps({ microsteps: this.initialMicrosteps ?? [] })
|
|
2203
|
+
})
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
private publishStartFailed(cause: Cause.Cause<unknown>): void {
|
|
2207
|
+
this.initializing = false
|
|
2208
|
+
const inspector = this.inspector
|
|
2209
|
+
const subject = this.inspectionSubject
|
|
2210
|
+
if (inspector === undefined || subject === undefined) return
|
|
2211
|
+
inspector.publishUnsafe(
|
|
2212
|
+
this.activity === undefined
|
|
2213
|
+
? { _tag: "StartFailed", subject, cause }
|
|
2214
|
+
: {
|
|
2215
|
+
_tag: "ActivityStopped",
|
|
2216
|
+
subject: this.activity.owner,
|
|
2217
|
+
activity: this.activity,
|
|
2218
|
+
exit: Exit.failCause(cause)
|
|
2219
|
+
}
|
|
2220
|
+
)
|
|
2221
|
+
}
|
|
2222
|
+
|
|
1772
2223
|
private get execution(): CompiledProcessExecution<any, any, any, any, any, any> {
|
|
1773
2224
|
return this.logic.execution as CompiledProcessExecution<any, any, any, any, any, any>
|
|
1774
2225
|
}
|
|
1775
2226
|
|
|
1776
2227
|
initializeCompiledSync(): Effect.Effect<MachineRef<any, any, any, any>, unknown> {
|
|
2228
|
+
this.publishCreated()
|
|
1777
2229
|
if (!this.execution.childless) {
|
|
1778
2230
|
this.childRuntime = makeChildRuntimeSync(this.address, this.options.runtime, this.services)
|
|
1779
2231
|
}
|
|
1780
2232
|
const parent = this.options.parent
|
|
1781
|
-
const sendParent = this.options.sendParent ?? (parent === undefined
|
|
2233
|
+
const sendParent = this.options.sendParent ?? (parent === undefined
|
|
2234
|
+
? noParentSend
|
|
2235
|
+
: this.inspector === undefined
|
|
2236
|
+
? parent.send
|
|
2237
|
+
: (event: unknown) => sendMachineTarget(parent, event, this.inspectionSubject, this.causation()))
|
|
1782
2238
|
this.processScope = {
|
|
1783
2239
|
self: this.address,
|
|
1784
2240
|
parent,
|
|
@@ -1786,11 +2242,24 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1786
2242
|
sendParent,
|
|
1787
2243
|
emit: (event) => this.emitEvent(event),
|
|
1788
2244
|
sendTo: ((target: unknown, event: unknown) =>
|
|
1789
|
-
|
|
1790
|
-
?
|
|
1791
|
-
|
|
2245
|
+
isMachineTarget(target)
|
|
2246
|
+
? this.inspector === undefined
|
|
2247
|
+
? target.send(event)
|
|
2248
|
+
: sendMachineTarget(target, event, this.inspectionSubject, this.causation())
|
|
2249
|
+
: this.childRuntime.sendTo(
|
|
2250
|
+
target as ChildSelector,
|
|
2251
|
+
event,
|
|
2252
|
+
this.inspectionSubject,
|
|
2253
|
+
this.causation()
|
|
2254
|
+
)) as ProcessScope<unknown>["sendTo"],
|
|
1792
2255
|
stopChild: this.childRuntime.stop,
|
|
1793
|
-
failCause: (cause: Cause.Cause<unknown>) => this.failCause(cause)
|
|
2256
|
+
failCause: (cause: Cause.Cause<unknown>) => this.failCause(cause),
|
|
2257
|
+
inspectInitial: this.inspector === undefined
|
|
2258
|
+
? noInspectInitial
|
|
2259
|
+
: (paths, microsteps = []) => {
|
|
2260
|
+
this.initialEntryPaths = paths
|
|
2261
|
+
this.initialMicrosteps = microsteps
|
|
2262
|
+
}
|
|
1794
2263
|
}
|
|
1795
2264
|
const compiledInitial = this.execution.initialSync!
|
|
1796
2265
|
let initialized: CompiledInitialized
|
|
@@ -1798,6 +2267,7 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1798
2267
|
initialized = compiledInitial(this.processScope)
|
|
1799
2268
|
} catch (error) {
|
|
1800
2269
|
this.runState = "Idle"
|
|
2270
|
+
this.publishStartFailed(Cause.fail(error))
|
|
1801
2271
|
return Effect.fail(error)
|
|
1802
2272
|
}
|
|
1803
2273
|
this.runState = "Idle"
|
|
@@ -1807,6 +2277,7 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1807
2277
|
changes: undefined,
|
|
1808
2278
|
snapshot: { status: "active", state: initialized.state }
|
|
1809
2279
|
}
|
|
2280
|
+
this.publishInitialized(initialized.state)
|
|
1810
2281
|
this.compiledContext = new CompiledProcessContextImpl(this.processScope, this.childRuntime.owned, this)
|
|
1811
2282
|
if ("executionState" in initialized) {
|
|
1812
2283
|
this.compiledContext.executionState = initialized.executionState
|
|
@@ -1831,11 +2302,16 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1831
2302
|
initialize(): Effect.Effect<MachineRef<any, any, any, any>, unknown, any> {
|
|
1832
2303
|
const self = this
|
|
1833
2304
|
return Effect.gen(function*() {
|
|
2305
|
+
self.publishCreated()
|
|
1834
2306
|
if (!self.execution.childless) {
|
|
1835
2307
|
self.childRuntime = yield* makeChildRuntime(self.address, self.options.runtime, self.services)
|
|
1836
2308
|
}
|
|
1837
2309
|
const parent = self.options.parent
|
|
1838
|
-
const sendParent = self.options.sendParent ?? (parent === undefined
|
|
2310
|
+
const sendParent = self.options.sendParent ?? (parent === undefined
|
|
2311
|
+
? noParentSend
|
|
2312
|
+
: self.inspector === undefined
|
|
2313
|
+
? parent.send
|
|
2314
|
+
: (event: unknown) => sendMachineTarget(parent, event, self.inspectionSubject, self.causation()))
|
|
1839
2315
|
self.processScope = {
|
|
1840
2316
|
self: self.address,
|
|
1841
2317
|
parent,
|
|
@@ -1843,11 +2319,24 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1843
2319
|
sendParent,
|
|
1844
2320
|
emit: (event) => self.emitEvent(event),
|
|
1845
2321
|
sendTo: ((target: unknown, event: unknown) =>
|
|
1846
|
-
|
|
1847
|
-
?
|
|
1848
|
-
|
|
2322
|
+
isMachineTarget(target)
|
|
2323
|
+
? self.inspector === undefined
|
|
2324
|
+
? target.send(event)
|
|
2325
|
+
: sendMachineTarget(target, event, self.inspectionSubject, self.causation())
|
|
2326
|
+
: self.childRuntime.sendTo(
|
|
2327
|
+
target as ChildSelector,
|
|
2328
|
+
event,
|
|
2329
|
+
self.inspectionSubject,
|
|
2330
|
+
self.causation()
|
|
2331
|
+
)) as ProcessScope<unknown>["sendTo"],
|
|
1849
2332
|
stopChild: self.childRuntime.stop,
|
|
1850
|
-
failCause: (cause: Cause.Cause<unknown>) => self.failCause(cause)
|
|
2333
|
+
failCause: (cause: Cause.Cause<unknown>) => self.failCause(cause),
|
|
2334
|
+
inspectInitial: self.inspector === undefined
|
|
2335
|
+
? noInspectInitial
|
|
2336
|
+
: (paths, microsteps = []) => {
|
|
2337
|
+
self.initialEntryPaths = paths
|
|
2338
|
+
self.initialMicrosteps = microsteps
|
|
2339
|
+
}
|
|
1851
2340
|
}
|
|
1852
2341
|
|
|
1853
2342
|
const cleanupStartupFailure = <A, E>(exit: Exit.Exit<A, E>): Effect.Effect<void> =>
|
|
@@ -1867,7 +2356,10 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1867
2356
|
)
|
|
1868
2357
|
: compiledInitial(self.processScope)
|
|
1869
2358
|
const initialized = yield* initializeEffect.pipe(
|
|
1870
|
-
Effect.onExit(
|
|
2359
|
+
Effect.onExit((exit) => {
|
|
2360
|
+
if (Exit.isFailure(exit)) self.publishStartFailed(exit.cause)
|
|
2361
|
+
return cleanupStartupFailure(exit)
|
|
2362
|
+
}),
|
|
1871
2363
|
Effect.ensuring(Effect.sync(() => {
|
|
1872
2364
|
self.runState = "Idle"
|
|
1873
2365
|
}))
|
|
@@ -1879,6 +2371,7 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
1879
2371
|
changes: undefined,
|
|
1880
2372
|
snapshot: { status: "active", state: initial }
|
|
1881
2373
|
}
|
|
2374
|
+
self.publishInitialized(initial)
|
|
1882
2375
|
if (self.execution.drain._tag === "Process") {
|
|
1883
2376
|
self.processContext = {
|
|
1884
2377
|
...self.processScope,
|
|
@@ -2022,11 +2515,7 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
2022
2515
|
return Effect.uninterruptibleMask((restore) =>
|
|
2023
2516
|
Deferred.make<AcknowledgedDelivery<unknown>, unknown>().pipe(
|
|
2024
2517
|
Effect.flatMap((deferred) =>
|
|
2025
|
-
this.
|
|
2026
|
-
[AcknowledgedMessageTypeId]: true as const,
|
|
2027
|
-
event,
|
|
2028
|
-
deferred
|
|
2029
|
-
}).pipe(
|
|
2518
|
+
this.offerEvent(event, undefined, undefined, deferred).pipe(
|
|
2030
2519
|
Effect.andThen(restore(Deferred.await(deferred)))
|
|
2031
2520
|
)
|
|
2032
2521
|
)
|
|
@@ -2034,6 +2523,31 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
2034
2523
|
)
|
|
2035
2524
|
}
|
|
2036
2525
|
|
|
2526
|
+
private offerEvent(
|
|
2527
|
+
event: unknown,
|
|
2528
|
+
source: Inspection.Subject | undefined,
|
|
2529
|
+
causedBy: Inspection.Causation | undefined,
|
|
2530
|
+
deferred?: Deferred.Deferred<AcknowledgedDelivery<unknown>, unknown>
|
|
2531
|
+
): Effect.Effect<void, StoppedError> {
|
|
2532
|
+
return Effect.suspend(() => {
|
|
2533
|
+
const inspector = this.inspector
|
|
2534
|
+
const subject = this.inspectionSubject
|
|
2535
|
+
const message: ProcessMessage<unknown> = inspector?.isActive() === true && subject !== undefined
|
|
2536
|
+
? makeInspectedMessage(
|
|
2537
|
+
inspector,
|
|
2538
|
+
subject,
|
|
2539
|
+
event,
|
|
2540
|
+
source,
|
|
2541
|
+
causedBy,
|
|
2542
|
+
deferred
|
|
2543
|
+
)
|
|
2544
|
+
: deferred === undefined
|
|
2545
|
+
? event
|
|
2546
|
+
: { [AcknowledgedMessageTypeId]: true as const, event, deferred }
|
|
2547
|
+
return this.offerMessage(message)
|
|
2548
|
+
})
|
|
2549
|
+
}
|
|
2550
|
+
|
|
2037
2551
|
private offerMessage(message: ProcessMessage<unknown>): Effect.Effect<void, StoppedError> {
|
|
2038
2552
|
return Effect.uninterruptible(
|
|
2039
2553
|
Effect.suspend(() => {
|
|
@@ -2041,6 +2555,9 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
2041
2555
|
return Effect.fail(new StoppedError())
|
|
2042
2556
|
}
|
|
2043
2557
|
offerCompactMailbox(this.mailbox, message)
|
|
2558
|
+
const inspector = this.inspector
|
|
2559
|
+
const subject = this.inspectionSubject
|
|
2560
|
+
if (inspector !== undefined && subject !== undefined) publishInspectedSent(inspector, subject, message)
|
|
2044
2561
|
this.offerRevision += 1
|
|
2045
2562
|
if (this.runState === "Draining") {
|
|
2046
2563
|
return Effect.void
|
|
@@ -2096,6 +2613,7 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
2096
2613
|
this.lifecycle !== "Active" ||
|
|
2097
2614
|
(this.options.onOutcome !== undefined && this.options.skipStoppedOutcome !== true) ||
|
|
2098
2615
|
this.options.onStop !== undefined ||
|
|
2616
|
+
this.inspector !== undefined ||
|
|
2099
2617
|
this.current.changes !== undefined ||
|
|
2100
2618
|
this.current.terminalizing || this.current.snapshot.status !== "active"
|
|
2101
2619
|
) {
|
|
@@ -2245,13 +2763,31 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
2245
2763
|
Effect.exit,
|
|
2246
2764
|
Effect.asVoid
|
|
2247
2765
|
)
|
|
2766
|
+
const inspector = this.inspector
|
|
2767
|
+
const subject = this.inspectionSubject
|
|
2768
|
+
const closeEmissionsAndInspect = inspector === undefined || subject === undefined
|
|
2769
|
+
? this.closeEmissions()
|
|
2770
|
+
: this.closeEmissions().pipe(
|
|
2771
|
+
Effect.andThen(Effect.sync(() =>
|
|
2772
|
+
inspector.publishUnsafe(
|
|
2773
|
+
this.activity === undefined
|
|
2774
|
+
? { _tag: "Terminated", subject, snapshot }
|
|
2775
|
+
: {
|
|
2776
|
+
_tag: "ActivityStopped",
|
|
2777
|
+
subject: this.activity.owner,
|
|
2778
|
+
activity: this.activity,
|
|
2779
|
+
exit: snapshot.status === "stopped" ? Exit.interrupt() : exit
|
|
2780
|
+
}
|
|
2781
|
+
)
|
|
2782
|
+
))
|
|
2783
|
+
)
|
|
2248
2784
|
return Effect.uninterruptible(
|
|
2249
2785
|
Effect.sync(() => {
|
|
2250
2786
|
closeCompactMailbox(this.mailbox)
|
|
2251
2787
|
}).pipe(
|
|
2252
2788
|
Effect.andThen(this.childRuntime.close(exit)),
|
|
2253
2789
|
Effect.andThen(this.setAndPublishSnapshot(snapshot)),
|
|
2254
|
-
Effect.andThen(
|
|
2790
|
+
Effect.andThen(closeEmissionsAndInspect),
|
|
2255
2791
|
Effect.andThen(Effect.sync(() => {
|
|
2256
2792
|
if (requested._tag === "Failure") {
|
|
2257
2793
|
failAcknowledgedMessage(this.inFlightMessage, requested.cause)
|
|
@@ -2262,6 +2798,11 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
2262
2798
|
})),
|
|
2263
2799
|
Effect.andThen(notifyOutcome),
|
|
2264
2800
|
Effect.andThen(this.options.onStop ?? Effect.void),
|
|
2801
|
+
Effect.andThen(
|
|
2802
|
+
this.options.inspectionRoot === true && this.inspector !== undefined
|
|
2803
|
+
? this.inspector.close
|
|
2804
|
+
: Effect.void
|
|
2805
|
+
),
|
|
2265
2806
|
Effect.andThen(Effect.sync(() => {
|
|
2266
2807
|
this.options.onStopSync?.()
|
|
2267
2808
|
this.runState = "Idle"
|
|
@@ -2301,12 +2842,26 @@ class CompiledProcess implements MachineRef<any, any, any, any> {
|
|
|
2301
2842
|
}
|
|
2302
2843
|
|
|
2303
2844
|
private emitEvent(event: unknown): Effect.Effect<void> {
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2845
|
+
const publish = this.externalEmissions !== undefined ?
|
|
2846
|
+
this.externalEmissions.emit(event) :
|
|
2847
|
+
Effect.suspend(() =>
|
|
2848
|
+
this.emissionsPubSub === undefined || this.emissionsPubSub === EmissionsClosed
|
|
2849
|
+
? Effect.void
|
|
2850
|
+
: PubSub.publish(this.emissionsPubSub, event).pipe(Effect.asVoid)
|
|
2851
|
+
)
|
|
2852
|
+
const inspector = this.inspector
|
|
2853
|
+
const subject = this.inspectionSubject
|
|
2854
|
+
if (inspector === undefined || subject === undefined) return publish
|
|
2855
|
+
return publish.pipe(Effect.tap(() =>
|
|
2856
|
+
Effect.sync(() =>
|
|
2857
|
+
inspector.publishUnsafe({
|
|
2858
|
+
_tag: "Emitted",
|
|
2859
|
+
subject,
|
|
2860
|
+
emission: event,
|
|
2861
|
+
causedBy: this.causation()
|
|
2862
|
+
})
|
|
2863
|
+
)
|
|
2864
|
+
))
|
|
2310
2865
|
}
|
|
2311
2866
|
|
|
2312
2867
|
shutdownEmissions(): Effect.Effect<void> {
|
|
@@ -2570,7 +3125,17 @@ const startCompactCompiledInternal: typeof startGenericInternal = Effect.fnUntra
|
|
|
2570
3125
|
? process.initializeCompiledSync()
|
|
2571
3126
|
: process.initialize()
|
|
2572
3127
|
return yield* initialize.pipe(
|
|
2573
|
-
Effect.onExit((exit) =>
|
|
3128
|
+
Effect.onExit((exit) =>
|
|
3129
|
+
Exit.isFailure(exit)
|
|
3130
|
+
? process.shutdownEmissions().pipe(
|
|
3131
|
+
Effect.andThen(
|
|
3132
|
+
options.inspectionRoot === true && options.runtime.inspection !== undefined
|
|
3133
|
+
? options.runtime.inspection.close
|
|
3134
|
+
: Effect.void
|
|
3135
|
+
)
|
|
3136
|
+
)
|
|
3137
|
+
: Effect.void
|
|
3138
|
+
)
|
|
2574
3139
|
)
|
|
2575
3140
|
}) as typeof startGenericInternal
|
|
2576
3141
|
|
|
@@ -2689,6 +3254,8 @@ const prepareProcessWithStrategy = Effect.fnUntraced(function*<
|
|
|
2689
3254
|
) {
|
|
2690
3255
|
const runtime = yield* makeProcessRuntime
|
|
2691
3256
|
const sessionId = yield* runtime.nextSessionId
|
|
3257
|
+
const inspection = yield* InspectionRuntime.make(sessionId)
|
|
3258
|
+
runtime.inspection = inspection
|
|
2692
3259
|
const emissions = makeEmissionRuntime()
|
|
2693
3260
|
const started = yield* Deferred.make<MachineRef<State, Event, Error, Output, Emitted>, InitialError>()
|
|
2694
3261
|
const internalOptions: StartInternalOptions = options === undefined
|
|
@@ -2696,14 +3263,18 @@ const prepareProcessWithStrategy = Effect.fnUntraced(function*<
|
|
|
2696
3263
|
detached: true,
|
|
2697
3264
|
emissions,
|
|
2698
3265
|
runtime,
|
|
2699
|
-
sessionId
|
|
3266
|
+
sessionId,
|
|
3267
|
+
inspectionRoot: true,
|
|
3268
|
+
origin: { _tag: "Root" }
|
|
2700
3269
|
}
|
|
2701
3270
|
: {
|
|
2702
3271
|
...options,
|
|
2703
3272
|
detached: true,
|
|
2704
3273
|
emissions,
|
|
2705
3274
|
runtime,
|
|
2706
|
-
sessionId
|
|
3275
|
+
sessionId,
|
|
3276
|
+
inspectionRoot: true,
|
|
3277
|
+
origin: { _tag: "Root" }
|
|
2707
3278
|
}
|
|
2708
3279
|
const initialize = strategy === "generic"
|
|
2709
3280
|
? startGenericInternal(logic, internalOptions)
|
|
@@ -2724,6 +3295,7 @@ const prepareProcessWithStrategy = Effect.fnUntraced(function*<
|
|
|
2724
3295
|
Deferred.await(started).pipe(Effect.map((ref) => ref.changes))
|
|
2725
3296
|
),
|
|
2726
3297
|
emissions: emissions.stream as Stream.Stream<Emitted>,
|
|
3298
|
+
inspection: inspection.stream,
|
|
2727
3299
|
start
|
|
2728
3300
|
}
|
|
2729
3301
|
})
|