@logixjs/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Action-BkRHy2vg.d.cts +10 -0
- package/dist/Action-mqVvtEHt.d.ts +10 -0
- package/dist/Action.cjs +57 -0
- package/dist/Action.cjs.map +1 -0
- package/dist/Action.d.cts +2 -0
- package/dist/Action.d.ts +2 -0
- package/dist/Action.js +9 -0
- package/dist/Action.js.map +1 -0
- package/dist/Actions-AsQ07yTP.d.cts +22 -0
- package/dist/Actions-AsQ07yTP.d.ts +22 -0
- package/dist/Actions.cjs +19 -0
- package/dist/Actions.cjs.map +1 -0
- package/dist/Actions.d.cts +2 -0
- package/dist/Actions.d.ts +2 -0
- package/dist/Actions.js +2 -0
- package/dist/Actions.js.map +1 -0
- package/dist/Bound-BN1DQ_lM.d.ts +23 -0
- package/dist/Bound-BPIfH9SS.d.cts +23 -0
- package/dist/Bound.cjs +1532 -0
- package/dist/Bound.cjs.map +1 -0
- package/dist/Bound.d.cts +7 -0
- package/dist/Bound.d.ts +7 -0
- package/dist/Bound.js +25 -0
- package/dist/Bound.js.map +1 -0
- package/dist/Debug-B5q5Bkzx.d.ts +320 -0
- package/dist/Debug-Bq8Sqjcr.d.cts +320 -0
- package/dist/Debug.cjs +1821 -0
- package/dist/Debug.cjs.map +1 -0
- package/dist/Debug.d.cts +13 -0
- package/dist/Debug.d.ts +13 -0
- package/dist/Debug.js +76 -0
- package/dist/Debug.js.map +1 -0
- package/dist/EffectOp.cjs +169 -0
- package/dist/EffectOp.cjs.map +1 -0
- package/dist/EffectOp.d.cts +118 -0
- package/dist/EffectOp.d.ts +118 -0
- package/dist/EffectOp.js +28 -0
- package/dist/EffectOp.js.map +1 -0
- package/dist/Env-DuJ6JrU2.d.cts +10 -0
- package/dist/Env-DuJ6JrU2.d.ts +10 -0
- package/dist/Env.cjs +60 -0
- package/dist/Env.cjs.map +1 -0
- package/dist/Env.d.cts +1 -0
- package/dist/Env.d.ts +1 -0
- package/dist/Env.js +11 -0
- package/dist/Env.js.map +1 -0
- package/dist/Flow-1fZT8MpX.d.cts +152 -0
- package/dist/Flow-BhpjE22E.d.ts +152 -0
- package/dist/Flow.cjs +504 -0
- package/dist/Flow.cjs.map +1 -0
- package/dist/Flow.d.cts +8 -0
- package/dist/Flow.d.ts +8 -0
- package/dist/Flow.js +15 -0
- package/dist/Flow.js.map +1 -0
- package/dist/Handle-D8D1zPb_.d.cts +30 -0
- package/dist/Handle-D_cLW1Z3.d.ts +30 -0
- package/dist/Handle.cjs +42 -0
- package/dist/Handle.cjs.map +1 -0
- package/dist/Handle.d.cts +7 -0
- package/dist/Handle.d.ts +7 -0
- package/dist/Handle.js +10 -0
- package/dist/Handle.js.map +1 -0
- package/dist/Kernel-8kC-jOda.d.cts +171 -0
- package/dist/Kernel-CnGE1Fyk.d.ts +171 -0
- package/dist/Kernel.cjs +284 -0
- package/dist/Kernel.cjs.map +1 -0
- package/dist/Kernel.d.cts +14 -0
- package/dist/Kernel.d.ts +14 -0
- package/dist/Kernel.js +36 -0
- package/dist/Kernel.js.map +1 -0
- package/dist/Link-Db7975nU.d.ts +45 -0
- package/dist/Link-fX8x1eCK.d.cts +45 -0
- package/dist/Link.cjs +542 -0
- package/dist/Link.cjs.map +1 -0
- package/dist/Link.d.cts +7 -0
- package/dist/Link.d.ts +7 -0
- package/dist/Link.js +35 -0
- package/dist/Link.js.map +1 -0
- package/dist/Logic-BRjEMr-W.d.ts +38 -0
- package/dist/Logic-DRh4sDZj.d.cts +38 -0
- package/dist/Logic.cjs +37 -0
- package/dist/Logic.cjs.map +1 -0
- package/dist/Logic.d.cts +7 -0
- package/dist/Logic.d.ts +7 -0
- package/dist/Logic.js +10 -0
- package/dist/Logic.js.map +1 -0
- package/dist/MatchBuilder-0QOc-nlU.d.ts +14 -0
- package/dist/MatchBuilder-CJk5oCkR.d.cts +14 -0
- package/dist/MatchBuilder.cjs +85 -0
- package/dist/MatchBuilder.cjs.map +1 -0
- package/dist/MatchBuilder.d.cts +8 -0
- package/dist/MatchBuilder.d.ts +8 -0
- package/dist/MatchBuilder.js +11 -0
- package/dist/MatchBuilder.js.map +1 -0
- package/dist/Middleware.cjs +411 -0
- package/dist/Middleware.cjs.map +1 -0
- package/dist/Middleware.d.cts +88 -0
- package/dist/Middleware.d.ts +88 -0
- package/dist/Middleware.js +27 -0
- package/dist/Middleware.js.map +1 -0
- package/dist/Module-B_0xRDMR.d.cts +203 -0
- package/dist/Module-DnzluX2J.d.ts +203 -0
- package/dist/Module.cjs +13512 -0
- package/dist/Module.cjs.map +1 -0
- package/dist/Module.d.cts +8 -0
- package/dist/Module.d.ts +8 -0
- package/dist/Module.js +53 -0
- package/dist/Module.js.map +1 -0
- package/dist/ModuleTag-C8FHY_sY.d.ts +93 -0
- package/dist/ModuleTag-EGbgBMpZ.d.cts +93 -0
- package/dist/ModuleTag.cjs +12231 -0
- package/dist/ModuleTag.cjs.map +1 -0
- package/dist/ModuleTag.d.cts +8 -0
- package/dist/ModuleTag.d.ts +8 -0
- package/dist/ModuleTag.js +39 -0
- package/dist/ModuleTag.js.map +1 -0
- package/dist/Observability-COqEvp2C.d.cts +713 -0
- package/dist/Observability-cY4kLn0S.d.ts +713 -0
- package/dist/Observability.cjs +5865 -0
- package/dist/Observability.cjs.map +1 -0
- package/dist/Observability.d.cts +9 -0
- package/dist/Observability.d.ts +9 -0
- package/dist/Observability.js +41 -0
- package/dist/Observability.js.map +1 -0
- package/dist/Platform-C49Pv956.d.cts +21 -0
- package/dist/Platform-C49Pv956.d.ts +21 -0
- package/dist/Platform-CHX8o-U4.d.ts +51 -0
- package/dist/Platform-CVlv0xLQ.d.cts +51 -0
- package/dist/Platform.cjs +58 -0
- package/dist/Platform.cjs.map +1 -0
- package/dist/Platform.d.cts +4 -0
- package/dist/Platform.d.ts +4 -0
- package/dist/Platform.js +15 -0
- package/dist/Platform.js.map +1 -0
- package/dist/Process-CM9xbMdP.d.ts +92 -0
- package/dist/Process-mL8fHDSB.d.cts +92 -0
- package/dist/Process.cjs +575 -0
- package/dist/Process.cjs.map +1 -0
- package/dist/Process.d.cts +8 -0
- package/dist/Process.d.ts +8 -0
- package/dist/Process.js +42 -0
- package/dist/Process.js.map +1 -0
- package/dist/ReadQuery-BlMwhe-F.d.ts +30 -0
- package/dist/ReadQuery-CL5XlXts.d.cts +30 -0
- package/dist/ReadQuery-SinbStGF.d.cts +38 -0
- package/dist/ReadQuery-SinbStGF.d.ts +38 -0
- package/dist/ReadQuery.cjs +377 -0
- package/dist/ReadQuery.cjs.map +1 -0
- package/dist/ReadQuery.d.cts +2 -0
- package/dist/ReadQuery.d.ts +2 -0
- package/dist/ReadQuery.js +14 -0
- package/dist/ReadQuery.js.map +1 -0
- package/dist/Reflection-CQnKwPXj.d.ts +182 -0
- package/dist/Reflection-Kabo1mlU.d.cts +182 -0
- package/dist/Reflection.cjs +2954 -0
- package/dist/Reflection.cjs.map +1 -0
- package/dist/Reflection.d.cts +17 -0
- package/dist/Reflection.d.ts +17 -0
- package/dist/Reflection.js +40 -0
- package/dist/Reflection.js.map +1 -0
- package/dist/Resource-Dy1xD_DG.d.cts +75 -0
- package/dist/Resource-Dy1xD_DG.d.ts +75 -0
- package/dist/Resource.cjs +166 -0
- package/dist/Resource.cjs.map +1 -0
- package/dist/Resource.d.cts +3 -0
- package/dist/Resource.d.ts +3 -0
- package/dist/Resource.js +21 -0
- package/dist/Resource.js.map +1 -0
- package/dist/Root-7ADUMk4t.d.cts +29 -0
- package/dist/Root-7ADUMk4t.d.ts +29 -0
- package/dist/Root.cjs +125 -0
- package/dist/Root.cjs.map +1 -0
- package/dist/Root.d.cts +4 -0
- package/dist/Root.d.ts +4 -0
- package/dist/Root.js +12 -0
- package/dist/Root.js.map +1 -0
- package/dist/Runtime-B-aL-f29.d.cts +274 -0
- package/dist/Runtime-CtyzZG4i.d.ts +274 -0
- package/dist/Runtime.cjs +5740 -0
- package/dist/Runtime.cjs.map +1 -0
- package/dist/Runtime.d.cts +19 -0
- package/dist/Runtime.d.ts +19 -0
- package/dist/Runtime.js +62 -0
- package/dist/Runtime.js.map +1 -0
- package/dist/ScopeRegistry-D1owDNSm.d.cts +61 -0
- package/dist/ScopeRegistry-D1owDNSm.d.ts +61 -0
- package/dist/ScopeRegistry.cjs +152 -0
- package/dist/ScopeRegistry.cjs.map +1 -0
- package/dist/ScopeRegistry.d.cts +2 -0
- package/dist/ScopeRegistry.d.ts +2 -0
- package/dist/ScopeRegistry.js +16 -0
- package/dist/ScopeRegistry.js.map +1 -0
- package/dist/State-CU50R26M.d.cts +19 -0
- package/dist/State-CU50R26M.d.ts +19 -0
- package/dist/State.cjs +19 -0
- package/dist/State.cjs.map +1 -0
- package/dist/State.d.cts +2 -0
- package/dist/State.d.ts +2 -0
- package/dist/State.js +2 -0
- package/dist/State.js.map +1 -0
- package/dist/StateTrait-BGsZghTz.d.ts +122 -0
- package/dist/StateTrait-OWhbj12c.d.cts +122 -0
- package/dist/StateTrait.cjs +2737 -0
- package/dist/StateTrait.cjs.map +1 -0
- package/dist/StateTrait.d.cts +9 -0
- package/dist/StateTrait.d.ts +9 -0
- package/dist/StateTrait.js +39 -0
- package/dist/StateTrait.js.map +1 -0
- package/dist/TraitLifecycle-CwV5WPFX.d.cts +88 -0
- package/dist/TraitLifecycle-LdIWmKlg.d.ts +88 -0
- package/dist/TraitLifecycle.cjs +581 -0
- package/dist/TraitLifecycle.cjs.map +1 -0
- package/dist/TraitLifecycle.d.cts +8 -0
- package/dist/TraitLifecycle.d.ts +8 -0
- package/dist/TraitLifecycle.js +24 -0
- package/dist/TraitLifecycle.js.map +1 -0
- package/dist/action-DiMDD_0v.d.cts +35 -0
- package/dist/action-DiMDD_0v.d.ts +35 -0
- package/dist/chunk-24VULZ7A.js +76 -0
- package/dist/chunk-24VULZ7A.js.map +1 -0
- package/dist/chunk-3IYZ5IGG.js +17 -0
- package/dist/chunk-3IYZ5IGG.js.map +1 -0
- package/dist/chunk-3QMIVH35.js +43 -0
- package/dist/chunk-3QMIVH35.js.map +1 -0
- package/dist/chunk-3RMKLXHX.js +83 -0
- package/dist/chunk-3RMKLXHX.js.map +1 -0
- package/dist/chunk-3TMODYZV.js +111 -0
- package/dist/chunk-3TMODYZV.js.map +1 -0
- package/dist/chunk-3VG5TWQR.js +27 -0
- package/dist/chunk-3VG5TWQR.js.map +1 -0
- package/dist/chunk-4CQAV7YB.js +37 -0
- package/dist/chunk-4CQAV7YB.js.map +1 -0
- package/dist/chunk-4SO6JMZL.js +7 -0
- package/dist/chunk-4SO6JMZL.js.map +1 -0
- package/dist/chunk-66ALHVEX.js +40 -0
- package/dist/chunk-66ALHVEX.js.map +1 -0
- package/dist/chunk-76WT3HOR.js +397 -0
- package/dist/chunk-76WT3HOR.js.map +1 -0
- package/dist/chunk-ANLBCBDC.js +285 -0
- package/dist/chunk-ANLBCBDC.js.map +1 -0
- package/dist/chunk-AUIR5O6W.js +75 -0
- package/dist/chunk-AUIR5O6W.js.map +1 -0
- package/dist/chunk-BABLDP24.js +445 -0
- package/dist/chunk-BABLDP24.js.map +1 -0
- package/dist/chunk-BE3HW4FY.js +1099 -0
- package/dist/chunk-BE3HW4FY.js.map +1 -0
- package/dist/chunk-BZ2SHDN2.js +54 -0
- package/dist/chunk-BZ2SHDN2.js.map +1 -0
- package/dist/chunk-CW6T36TN.js +393 -0
- package/dist/chunk-CW6T36TN.js.map +1 -0
- package/dist/chunk-DFNM3WX2.js +632 -0
- package/dist/chunk-DFNM3WX2.js.map +1 -0
- package/dist/chunk-DMBALCE2.js +1034 -0
- package/dist/chunk-DMBALCE2.js.map +1 -0
- package/dist/chunk-EGK3KN7B.js +406 -0
- package/dist/chunk-EGK3KN7B.js.map +1 -0
- package/dist/chunk-EY4NZKDR.js +19 -0
- package/dist/chunk-EY4NZKDR.js.map +1 -0
- package/dist/chunk-G5ZBFPNU.js +23 -0
- package/dist/chunk-G5ZBFPNU.js.map +1 -0
- package/dist/chunk-GMPEOUP2.js +31 -0
- package/dist/chunk-GMPEOUP2.js.map +1 -0
- package/dist/chunk-IHVBV5C2.js +279 -0
- package/dist/chunk-IHVBV5C2.js.map +1 -0
- package/dist/chunk-IPF7E66P.js +23 -0
- package/dist/chunk-IPF7E66P.js.map +1 -0
- package/dist/chunk-JCXGZRMU.js +204 -0
- package/dist/chunk-JCXGZRMU.js.map +1 -0
- package/dist/chunk-JGIWG6SR.js +6359 -0
- package/dist/chunk-JGIWG6SR.js.map +1 -0
- package/dist/chunk-JWOYLO27.js +241 -0
- package/dist/chunk-JWOYLO27.js.map +1 -0
- package/dist/chunk-KIXAU3GM.js +137 -0
- package/dist/chunk-KIXAU3GM.js.map +1 -0
- package/dist/chunk-KL5ACTCT.js +8 -0
- package/dist/chunk-KL5ACTCT.js.map +1 -0
- package/dist/chunk-KP7MUZNX.js +83 -0
- package/dist/chunk-KP7MUZNX.js.map +1 -0
- package/dist/chunk-LEU6UA5J.js +1 -0
- package/dist/chunk-LEU6UA5J.js.map +1 -0
- package/dist/chunk-M2RGJPXX.js +35 -0
- package/dist/chunk-M2RGJPXX.js.map +1 -0
- package/dist/chunk-M3BFQ7HK.js +13 -0
- package/dist/chunk-M3BFQ7HK.js.map +1 -0
- package/dist/chunk-M3WTHJHJ.js +1051 -0
- package/dist/chunk-M3WTHJHJ.js.map +1 -0
- package/dist/chunk-M7IYCTJV.js +79 -0
- package/dist/chunk-M7IYCTJV.js.map +1 -0
- package/dist/chunk-NBD3KUOZ.js +838 -0
- package/dist/chunk-NBD3KUOZ.js.map +1 -0
- package/dist/chunk-NQZ2OSGR.js +151 -0
- package/dist/chunk-NQZ2OSGR.js.map +1 -0
- package/dist/chunk-NZJKFF45.js +106 -0
- package/dist/chunk-NZJKFF45.js.map +1 -0
- package/dist/chunk-OFADUJWJ.js +175 -0
- package/dist/chunk-OFADUJWJ.js.map +1 -0
- package/dist/chunk-OGWBVHB3.js +461 -0
- package/dist/chunk-OGWBVHB3.js.map +1 -0
- package/dist/chunk-PAYXCY6A.js +1696 -0
- package/dist/chunk-PAYXCY6A.js.map +1 -0
- package/dist/chunk-PYOE4VSI.js +1924 -0
- package/dist/chunk-PYOE4VSI.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/chunk-QCHIQWAJ.js +21 -0
- package/dist/chunk-QCHIQWAJ.js.map +1 -0
- package/dist/chunk-QMM6O4CD.js +71 -0
- package/dist/chunk-QMM6O4CD.js.map +1 -0
- package/dist/chunk-RNFE3ML2.js +22 -0
- package/dist/chunk-RNFE3ML2.js.map +1 -0
- package/dist/chunk-TAAPQVZN.js +23 -0
- package/dist/chunk-TAAPQVZN.js.map +1 -0
- package/dist/chunk-THATMZXD.js +21 -0
- package/dist/chunk-THATMZXD.js.map +1 -0
- package/dist/chunk-TKZ7MEIA.js +27 -0
- package/dist/chunk-TKZ7MEIA.js.map +1 -0
- package/dist/chunk-TQOBJYDP.js +7 -0
- package/dist/chunk-TQOBJYDP.js.map +1 -0
- package/dist/chunk-VZB726PE.js +93 -0
- package/dist/chunk-VZB726PE.js.map +1 -0
- package/dist/chunk-W3TEWHLO.js +568 -0
- package/dist/chunk-W3TEWHLO.js.map +1 -0
- package/dist/chunk-YS3AZQ2G.js +52 -0
- package/dist/chunk-YS3AZQ2G.js.map +1 -0
- package/dist/chunk-ZDTRWK5F.js +40 -0
- package/dist/chunk-ZDTRWK5F.js.map +1 -0
- package/dist/chunk-ZFLHVFUC.js +192 -0
- package/dist/chunk-ZFLHVFUC.js.map +1 -0
- package/dist/chunk-ZFY7U2FR.js +133 -0
- package/dist/chunk-ZFY7U2FR.js.map +1 -0
- package/dist/chunk-ZGDVUPTM.js +270 -0
- package/dist/chunk-ZGDVUPTM.js.map +1 -0
- package/dist/index.cjs +19700 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +195 -0
- package/dist/index.d.ts +195 -0
- package/dist/index.js +286 -0
- package/dist/index.js.map +1 -0
- package/dist/ir-BMP7yxJJ.d.cts +39 -0
- package/dist/ir-DUOz6H-5.d.ts +39 -0
- package/dist/module-B8CBqIZ_.d.cts +1191 -0
- package/dist/module-k7m3txak.d.ts +1191 -0
- package/dist/protocol-g_1897M2.d.cts +127 -0
- package/dist/protocol-g_1897M2.d.ts +127 -0
- package/package.json +162 -0
|
@@ -0,0 +1,1696 @@
|
|
|
1
|
+
import {
|
|
2
|
+
shouldNoopInSyncTransactionFiber
|
|
3
|
+
} from "./chunk-ZFLHVFUC.js";
|
|
4
|
+
import {
|
|
5
|
+
getRuntimeInternals
|
|
6
|
+
} from "./chunk-3RMKLXHX.js";
|
|
7
|
+
import {
|
|
8
|
+
isDevEnv
|
|
9
|
+
} from "./chunk-3QMIVH35.js";
|
|
10
|
+
import {
|
|
11
|
+
currentDiagnosticsLevel,
|
|
12
|
+
record,
|
|
13
|
+
toRuntimeDebugEventRef,
|
|
14
|
+
toSerializableErrorSummary
|
|
15
|
+
} from "./chunk-DMBALCE2.js";
|
|
16
|
+
import {
|
|
17
|
+
makeEvidenceSink
|
|
18
|
+
} from "./chunk-OFADUJWJ.js";
|
|
19
|
+
import {
|
|
20
|
+
projectJsonValue
|
|
21
|
+
} from "./chunk-JWOYLO27.js";
|
|
22
|
+
|
|
23
|
+
// src/internal/runtime/core/process/meta.ts
|
|
24
|
+
var PROCESS_META = /* @__PURE__ */ Symbol.for("@logixjs/core/processMeta");
|
|
25
|
+
var defineHidden = (target, key, value) => {
|
|
26
|
+
Object.defineProperty(target, key, {
|
|
27
|
+
value,
|
|
28
|
+
enumerable: false,
|
|
29
|
+
configurable: true,
|
|
30
|
+
writable: false
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
var getMeta = (effect) => effect[PROCESS_META];
|
|
34
|
+
var getDefinition = (effect) => getMeta(effect)?.definition;
|
|
35
|
+
var attachMeta = (effect, meta) => {
|
|
36
|
+
defineHidden(effect, PROCESS_META, meta);
|
|
37
|
+
return effect;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/internal/observability/evidenceCollector.ts
|
|
41
|
+
import { Context, Effect, FiberRef, Layer } from "effect";
|
|
42
|
+
var EvidenceCollectorTagImpl = class extends Context.Tag("@logixjs/core/EvidenceCollector")() {
|
|
43
|
+
};
|
|
44
|
+
var EvidenceCollectorTag = EvidenceCollectorTagImpl;
|
|
45
|
+
var evidenceCollectorLayer = (collector) => Layer.succeed(EvidenceCollectorTag, collector);
|
|
46
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
47
|
+
var makeEvidenceCollector = (session) => {
|
|
48
|
+
const sink = makeEvidenceSink(session);
|
|
49
|
+
const convergeStaticIrByDigest = /* @__PURE__ */ new Map();
|
|
50
|
+
let kernelImplementationRef;
|
|
51
|
+
let runtimeServicesEvidence;
|
|
52
|
+
const exportBudget = {
|
|
53
|
+
dropped: 0,
|
|
54
|
+
oversized: 0,
|
|
55
|
+
nonSerializable: 0
|
|
56
|
+
};
|
|
57
|
+
const debugSink = {
|
|
58
|
+
record: (event) => Effect.gen(function* () {
|
|
59
|
+
const level = yield* FiberRef.get(currentDiagnosticsLevel);
|
|
60
|
+
const instanceIdRaw = event.instanceId;
|
|
61
|
+
const instanceId = typeof instanceIdRaw === "string" && instanceIdRaw.length > 0 ? instanceIdRaw : "unknown";
|
|
62
|
+
const eventSeq = level === "off" ? void 0 : session.local.nextSeq("eventSeq", instanceId);
|
|
63
|
+
const ref = toRuntimeDebugEventRef(event, {
|
|
64
|
+
diagnosticsLevel: level,
|
|
65
|
+
eventSeq,
|
|
66
|
+
onMetaProjection: ({ stats }) => {
|
|
67
|
+
exportBudget.dropped += stats.dropped;
|
|
68
|
+
exportBudget.oversized += stats.oversized;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
if (!ref) return;
|
|
72
|
+
const projected = projectJsonValue(ref);
|
|
73
|
+
exportBudget.dropped += projected.stats.dropped;
|
|
74
|
+
exportBudget.oversized += projected.stats.oversized;
|
|
75
|
+
exportBudget.nonSerializable += projected.stats.nonSerializable;
|
|
76
|
+
sink.record("debug:event", projected.value, {
|
|
77
|
+
timestamp: ref.timestamp
|
|
78
|
+
});
|
|
79
|
+
})
|
|
80
|
+
};
|
|
81
|
+
const registerConvergeStaticIr = (staticIr) => {
|
|
82
|
+
if (!isRecord(staticIr)) return;
|
|
83
|
+
const digest = staticIr.staticIrDigest;
|
|
84
|
+
if (typeof digest !== "string" || digest.length === 0) return;
|
|
85
|
+
const projected = projectJsonValue(staticIr);
|
|
86
|
+
exportBudget.dropped += projected.stats.dropped;
|
|
87
|
+
exportBudget.oversized += projected.stats.oversized;
|
|
88
|
+
exportBudget.nonSerializable += projected.stats.nonSerializable;
|
|
89
|
+
convergeStaticIrByDigest.set(digest, projected.value);
|
|
90
|
+
};
|
|
91
|
+
const setKernelImplementationRef = (ref) => {
|
|
92
|
+
const projected = projectJsonValue(ref);
|
|
93
|
+
exportBudget.dropped += projected.stats.dropped;
|
|
94
|
+
exportBudget.oversized += projected.stats.oversized;
|
|
95
|
+
exportBudget.nonSerializable += projected.stats.nonSerializable;
|
|
96
|
+
kernelImplementationRef = projected.value;
|
|
97
|
+
};
|
|
98
|
+
const setRuntimeServicesEvidence = (evidence) => {
|
|
99
|
+
const projected = projectJsonValue(evidence);
|
|
100
|
+
exportBudget.dropped += projected.stats.dropped;
|
|
101
|
+
exportBudget.oversized += projected.stats.oversized;
|
|
102
|
+
exportBudget.nonSerializable += projected.stats.nonSerializable;
|
|
103
|
+
runtimeServicesEvidence = projected.value;
|
|
104
|
+
};
|
|
105
|
+
const exportEvidencePackage = (options) => {
|
|
106
|
+
const convergeSummary = convergeStaticIrByDigest.size > 0 ? {
|
|
107
|
+
staticIrByDigest: Object.fromEntries(convergeStaticIrByDigest)
|
|
108
|
+
} : void 0;
|
|
109
|
+
const runtimeSummary = kernelImplementationRef != null || runtimeServicesEvidence != null ? {
|
|
110
|
+
...kernelImplementationRef != null ? { kernelImplementationRef } : {},
|
|
111
|
+
...runtimeServicesEvidence != null ? { services: runtimeServicesEvidence } : {}
|
|
112
|
+
} : void 0;
|
|
113
|
+
const summary = convergeSummary != null || runtimeSummary != null ? {
|
|
114
|
+
...convergeSummary != null ? { converge: convergeSummary } : {},
|
|
115
|
+
...runtimeSummary != null ? { runtime: runtimeSummary } : {}
|
|
116
|
+
} : void 0;
|
|
117
|
+
return sink.export({
|
|
118
|
+
maxEvents: options?.maxEvents,
|
|
119
|
+
summary
|
|
120
|
+
});
|
|
121
|
+
};
|
|
122
|
+
const clear = () => {
|
|
123
|
+
sink.clear();
|
|
124
|
+
convergeStaticIrByDigest.clear();
|
|
125
|
+
kernelImplementationRef = void 0;
|
|
126
|
+
runtimeServicesEvidence = void 0;
|
|
127
|
+
exportBudget.dropped = 0;
|
|
128
|
+
exportBudget.oversized = 0;
|
|
129
|
+
exportBudget.nonSerializable = 0;
|
|
130
|
+
};
|
|
131
|
+
return {
|
|
132
|
+
session,
|
|
133
|
+
debugSink,
|
|
134
|
+
registerConvergeStaticIr,
|
|
135
|
+
setKernelImplementationRef,
|
|
136
|
+
setRuntimeServicesEvidence,
|
|
137
|
+
exportEvidencePackage,
|
|
138
|
+
clear
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// src/internal/runtime/core/process/ProcessRuntime.ts
|
|
143
|
+
import {
|
|
144
|
+
Cause,
|
|
145
|
+
Context as Context2,
|
|
146
|
+
Deferred,
|
|
147
|
+
Duration,
|
|
148
|
+
Effect as Effect3,
|
|
149
|
+
Fiber as Fiber2,
|
|
150
|
+
FiberRef as FiberRef2,
|
|
151
|
+
Layer as Layer2,
|
|
152
|
+
Option as Option2,
|
|
153
|
+
PubSub,
|
|
154
|
+
Queue,
|
|
155
|
+
Ref as Ref2,
|
|
156
|
+
Scope as Scope2,
|
|
157
|
+
Stream as Stream2
|
|
158
|
+
} from "effect";
|
|
159
|
+
|
|
160
|
+
// src/internal/runtime/core/process/identity.ts
|
|
161
|
+
var scopeKeyFromScope = (scope) => {
|
|
162
|
+
switch (scope.type) {
|
|
163
|
+
case "app":
|
|
164
|
+
return `app:${scope.appId}`;
|
|
165
|
+
case "moduleInstance":
|
|
166
|
+
return `moduleInstance:${scope.moduleId}::${scope.instanceId}`;
|
|
167
|
+
case "uiSubtree":
|
|
168
|
+
return `uiSubtree:${scope.subtreeId}`;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
var installationKeyFromIdentity = (identity) => `${identity.processId}@@${scopeKeyFromScope(identity.scope)}`;
|
|
172
|
+
var processInstanceIdFromIdentity = (identity) => {
|
|
173
|
+
const scopeKey = scopeKeyFromScope(identity.identity.scope);
|
|
174
|
+
return `process:${identity.identity.processId}::${scopeKey}::r${identity.runSeq}`;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/internal/runtime/core/process/concurrency.ts
|
|
178
|
+
import { Effect as Effect2, Fiber, Option, Ref, Stream } from "effect";
|
|
179
|
+
var DEFAULT_SERIAL_QUEUE_GUARD_LIMIT = 4096;
|
|
180
|
+
var DEFAULT_PARALLEL_LIMIT = 16;
|
|
181
|
+
var resolveQueueLimit = (maxQueue, options) => {
|
|
182
|
+
const defaultGuard = options?.defaultGuard ?? DEFAULT_SERIAL_QUEUE_GUARD_LIMIT;
|
|
183
|
+
const configured = typeof maxQueue === "number" && Number.isFinite(maxQueue) && maxQueue >= 0 ? Math.floor(maxQueue) : "unbounded";
|
|
184
|
+
return {
|
|
185
|
+
configured,
|
|
186
|
+
guard: configured === "unbounded" ? defaultGuard : configured
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
var runProcessTriggerStream = (args) => Effect2.gen(function* () {
|
|
190
|
+
const policy = args.policy;
|
|
191
|
+
const defaultQueueGuard = args.defaultQueueGuard ?? DEFAULT_SERIAL_QUEUE_GUARD_LIMIT;
|
|
192
|
+
if (policy.mode === "latest") {
|
|
193
|
+
const stateRef = yield* Ref.make({ fiber: void 0, runningId: 0, nextId: 0 });
|
|
194
|
+
const onTrigger2 = (trigger0) => Effect2.gen(function* () {
|
|
195
|
+
const trigger = args.assignTriggerSeq(trigger0);
|
|
196
|
+
const [prevFiber, prevRunningId, runId] = yield* Ref.modify(stateRef, (s) => {
|
|
197
|
+
const nextId = s.nextId + 1;
|
|
198
|
+
return [[s.fiber, s.runningId, nextId], { ...s, nextId, runningId: nextId }];
|
|
199
|
+
});
|
|
200
|
+
if (prevFiber && prevRunningId !== 0) {
|
|
201
|
+
const done = yield* Fiber.poll(prevFiber);
|
|
202
|
+
if (Option.isNone(done)) {
|
|
203
|
+
yield* Fiber.interruptFork(prevFiber);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const fiber = yield* Effect2.forkScoped(
|
|
207
|
+
args.run(trigger).pipe(Effect2.ensuring(Ref.update(stateRef, (s) => s.runningId === runId ? { ...s, runningId: 0 } : s)))
|
|
208
|
+
);
|
|
209
|
+
yield* Ref.update(stateRef, (s) => ({ ...s, fiber }));
|
|
210
|
+
});
|
|
211
|
+
return yield* Stream.runForEach(args.stream, onTrigger2);
|
|
212
|
+
}
|
|
213
|
+
const busyRef = yield* Ref.make(false);
|
|
214
|
+
const serialStateRef = yield* Ref.make({
|
|
215
|
+
running: false,
|
|
216
|
+
queue: [],
|
|
217
|
+
peak: 0
|
|
218
|
+
});
|
|
219
|
+
const parallelStateRef = yield* Ref.make({
|
|
220
|
+
active: 0,
|
|
221
|
+
queue: [],
|
|
222
|
+
peak: 0
|
|
223
|
+
});
|
|
224
|
+
const serialQueueLimit = resolveQueueLimit(policy.maxQueue, { defaultGuard: defaultQueueGuard });
|
|
225
|
+
const parallelQueueLimit = resolveQueueLimit(void 0, { defaultGuard: defaultQueueGuard });
|
|
226
|
+
const parallelLimit = typeof policy.maxParallel === "number" && Number.isFinite(policy.maxParallel) && policy.maxParallel >= 1 ? Math.floor(policy.maxParallel) : args.defaultParallelLimit ?? DEFAULT_PARALLEL_LIMIT;
|
|
227
|
+
const drainSerial = () => Effect2.suspend(
|
|
228
|
+
() => Ref.modify(serialStateRef, (state) => {
|
|
229
|
+
if (state.running || state.queue.length === 0) {
|
|
230
|
+
return [Option.none(), state];
|
|
231
|
+
}
|
|
232
|
+
const [next, ...rest] = state.queue;
|
|
233
|
+
return [Option.some(next), { ...state, running: true, queue: rest }];
|
|
234
|
+
}).pipe(
|
|
235
|
+
Effect2.flatMap(
|
|
236
|
+
(next) => Option.match(next, {
|
|
237
|
+
onNone: () => Effect2.void,
|
|
238
|
+
onSome: (trigger) => Effect2.forkScoped(
|
|
239
|
+
args.run(trigger).pipe(
|
|
240
|
+
Effect2.ensuring(Ref.update(serialStateRef, (s) => ({ ...s, running: false }))),
|
|
241
|
+
Effect2.zipRight(drainSerial())
|
|
242
|
+
)
|
|
243
|
+
).pipe(Effect2.asVoid)
|
|
244
|
+
})
|
|
245
|
+
)
|
|
246
|
+
)
|
|
247
|
+
);
|
|
248
|
+
const drainParallel = () => Effect2.suspend(
|
|
249
|
+
() => Ref.modify(parallelStateRef, (state) => {
|
|
250
|
+
if (state.active >= parallelLimit || state.queue.length === 0) {
|
|
251
|
+
return [Option.none(), state];
|
|
252
|
+
}
|
|
253
|
+
const [next, ...rest] = state.queue;
|
|
254
|
+
return [Option.some(next), { ...state, active: state.active + 1, queue: rest }];
|
|
255
|
+
}).pipe(
|
|
256
|
+
Effect2.flatMap(
|
|
257
|
+
(next) => Option.match(next, {
|
|
258
|
+
onNone: () => Effect2.void,
|
|
259
|
+
onSome: (trigger) => Effect2.forkScoped(
|
|
260
|
+
args.run(trigger).pipe(
|
|
261
|
+
Effect2.ensuring(
|
|
262
|
+
Ref.update(parallelStateRef, (s) => ({
|
|
263
|
+
...s,
|
|
264
|
+
active: Math.max(0, s.active - 1)
|
|
265
|
+
}))
|
|
266
|
+
),
|
|
267
|
+
Effect2.zipRight(drainParallel())
|
|
268
|
+
)
|
|
269
|
+
).pipe(Effect2.asVoid, Effect2.zipRight(drainParallel()))
|
|
270
|
+
})
|
|
271
|
+
)
|
|
272
|
+
)
|
|
273
|
+
);
|
|
274
|
+
const onTrigger = (trigger0) => Effect2.gen(function* () {
|
|
275
|
+
const trigger = args.assignTriggerSeq(trigger0);
|
|
276
|
+
if (policy.mode === "drop") {
|
|
277
|
+
const acquired = yield* Ref.modify(
|
|
278
|
+
busyRef,
|
|
279
|
+
(busy) => busy ? [false, busy] : [true, true]
|
|
280
|
+
);
|
|
281
|
+
if (!acquired) {
|
|
282
|
+
yield* args.onDrop(trigger);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
yield* Effect2.forkScoped(args.run(trigger).pipe(Effect2.ensuring(Ref.set(busyRef, false))));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (policy.mode === "parallel") {
|
|
289
|
+
const nextSize2 = yield* Ref.modify(parallelStateRef, (state) => {
|
|
290
|
+
const queue = [...state.queue, trigger];
|
|
291
|
+
return [queue.length, { ...state, queue, peak: Math.max(state.peak, queue.length) }];
|
|
292
|
+
});
|
|
293
|
+
if (nextSize2 > parallelQueueLimit.guard) {
|
|
294
|
+
const state = yield* Ref.get(parallelStateRef);
|
|
295
|
+
yield* args.onQueueOverflow({
|
|
296
|
+
mode: "parallel",
|
|
297
|
+
currentLength: nextSize2,
|
|
298
|
+
peak: state.peak,
|
|
299
|
+
limit: parallelQueueLimit,
|
|
300
|
+
policy
|
|
301
|
+
});
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
yield* drainParallel();
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const nextSize = yield* Ref.modify(serialStateRef, (state) => {
|
|
308
|
+
const queue = [...state.queue, trigger];
|
|
309
|
+
return [queue.length, { ...state, queue, peak: Math.max(state.peak, queue.length) }];
|
|
310
|
+
});
|
|
311
|
+
if (nextSize > serialQueueLimit.guard) {
|
|
312
|
+
const state = yield* Ref.get(serialStateRef);
|
|
313
|
+
yield* args.onQueueOverflow({
|
|
314
|
+
mode: "serial",
|
|
315
|
+
currentLength: nextSize,
|
|
316
|
+
peak: state.peak,
|
|
317
|
+
limit: serialQueueLimit,
|
|
318
|
+
policy
|
|
319
|
+
});
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
yield* drainSerial();
|
|
323
|
+
});
|
|
324
|
+
return yield* Stream.runForEach(args.stream, onTrigger);
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// src/internal/runtime/core/process/events.ts
|
|
328
|
+
var PROCESS_EVENT_MAX_BYTES = 4 * 1024;
|
|
329
|
+
var PROCESS_EVENT_MAX_EVENTS_PER_RUN = 50;
|
|
330
|
+
var PROCESS_EVENT_RESERVED_EVENTS_FOR_SUMMARY = 1;
|
|
331
|
+
var makeProcessRunEventBudgetState = (options) => ({
|
|
332
|
+
maxEvents: typeof options?.maxEvents === "number" && Number.isFinite(options.maxEvents) && options.maxEvents >= 0 ? Math.floor(options.maxEvents) : PROCESS_EVENT_MAX_EVENTS_PER_RUN,
|
|
333
|
+
maxBytes: typeof options?.maxBytes === "number" && Number.isFinite(options.maxBytes) && options.maxBytes >= 0 ? Math.floor(options.maxBytes) : PROCESS_EVENT_MAX_BYTES,
|
|
334
|
+
emitted: 0,
|
|
335
|
+
dropped: 0,
|
|
336
|
+
downgraded: 0,
|
|
337
|
+
summaryEmitted: false
|
|
338
|
+
});
|
|
339
|
+
var makeBudgetSummaryEvent = (args) => ({
|
|
340
|
+
type: "process:trigger",
|
|
341
|
+
identity: args.sourceEvent.identity,
|
|
342
|
+
trigger: args.sourceEvent.trigger,
|
|
343
|
+
severity: "warning",
|
|
344
|
+
eventSeq: args.sourceEvent.eventSeq,
|
|
345
|
+
timestampMs: args.sourceEvent.timestampMs,
|
|
346
|
+
error: {
|
|
347
|
+
message: "Process run event budget exceeded; further trigger/dispatch events are suppressed.",
|
|
348
|
+
code: "process::event_budget_exceeded",
|
|
349
|
+
hint: `maxEvents=${args.maxEvents} maxBytes=${args.maxBytes} emitted=${args.emitted} dropped=${args.dropped} downgraded=${args.downgraded}`
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
var applyProcessRunEventBudget = (state, event) => {
|
|
353
|
+
const maxEvents = Math.max(0, state.maxEvents);
|
|
354
|
+
const maxBytes = Math.max(0, state.maxBytes);
|
|
355
|
+
if (state.summaryEmitted) {
|
|
356
|
+
return [
|
|
357
|
+
{ _tag: "drop" },
|
|
358
|
+
{
|
|
359
|
+
...state,
|
|
360
|
+
dropped: state.dropped + 1
|
|
361
|
+
}
|
|
362
|
+
];
|
|
363
|
+
}
|
|
364
|
+
const reserve = PROCESS_EVENT_RESERVED_EVENTS_FOR_SUMMARY;
|
|
365
|
+
const allowedRegular = Math.max(0, maxEvents - reserve);
|
|
366
|
+
if (state.emitted < allowedRegular) {
|
|
367
|
+
const enforced = enforceProcessEventMaxBytes(event, { maxBytes });
|
|
368
|
+
return [
|
|
369
|
+
{ _tag: "emit", event: enforced.event },
|
|
370
|
+
{
|
|
371
|
+
...state,
|
|
372
|
+
emitted: state.emitted + 1,
|
|
373
|
+
downgraded: state.downgraded + (enforced.downgraded ? 1 : 0)
|
|
374
|
+
}
|
|
375
|
+
];
|
|
376
|
+
}
|
|
377
|
+
const dropped = state.dropped + 1;
|
|
378
|
+
const summary = makeBudgetSummaryEvent({
|
|
379
|
+
sourceEvent: event,
|
|
380
|
+
maxEvents,
|
|
381
|
+
maxBytes,
|
|
382
|
+
emitted: state.emitted,
|
|
383
|
+
dropped,
|
|
384
|
+
downgraded: state.downgraded
|
|
385
|
+
});
|
|
386
|
+
const enforcedSummary = enforceProcessEventMaxBytes(summary, { maxBytes });
|
|
387
|
+
return [
|
|
388
|
+
{ _tag: "emitSummary", event: enforcedSummary.event },
|
|
389
|
+
{
|
|
390
|
+
...state,
|
|
391
|
+
emitted: Math.min(maxEvents, state.emitted + 1),
|
|
392
|
+
dropped,
|
|
393
|
+
downgraded: state.downgraded + (enforcedSummary.downgraded ? 1 : 0),
|
|
394
|
+
summaryEmitted: true
|
|
395
|
+
}
|
|
396
|
+
];
|
|
397
|
+
};
|
|
398
|
+
var estimateEventBytes = (event) => {
|
|
399
|
+
const json = JSON.stringify(event);
|
|
400
|
+
return typeof Buffer !== "undefined" ? Buffer.byteLength(json, "utf8") : new TextEncoder().encode(json).length;
|
|
401
|
+
};
|
|
402
|
+
var truncateChars = (value, maxLen) => value.length <= maxLen ? value : value.slice(0, maxLen);
|
|
403
|
+
var normalizeErrorSummary = (error) => {
|
|
404
|
+
const message = typeof error.message === "string" && error.message.length > 0 ? error.message : "Error";
|
|
405
|
+
const hint = typeof error.hint === "string" && error.hint.length > 0 ? truncateChars(error.hint, 1024) : void 0;
|
|
406
|
+
return {
|
|
407
|
+
name: typeof error.name === "string" && error.name.length > 0 ? error.name : void 0,
|
|
408
|
+
message: truncateChars(message, 256),
|
|
409
|
+
code: typeof error.code === "string" && error.code.length > 0 ? error.code : void 0,
|
|
410
|
+
hint
|
|
411
|
+
};
|
|
412
|
+
};
|
|
413
|
+
var enforceProcessEventMaxBytes = (event, options) => {
|
|
414
|
+
const maxBytes = options?.maxBytes ?? PROCESS_EVENT_MAX_BYTES;
|
|
415
|
+
let downgraded = false;
|
|
416
|
+
let next = event;
|
|
417
|
+
if (event.error) {
|
|
418
|
+
const normalized = normalizeErrorSummary(event.error);
|
|
419
|
+
if (normalized.message !== event.error.message || normalized.hint !== event.error.hint || normalized.code !== event.error.code || normalized.name !== event.error.name) {
|
|
420
|
+
downgraded = true;
|
|
421
|
+
next = { ...event, error: normalized };
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (estimateEventBytes(next) <= maxBytes) {
|
|
425
|
+
return { event: next, downgraded };
|
|
426
|
+
}
|
|
427
|
+
if (!next.error?.hint) {
|
|
428
|
+
return { event: next, downgraded: true };
|
|
429
|
+
}
|
|
430
|
+
const hint = next.error.hint;
|
|
431
|
+
const steps = [512, 256, 128, 64, 32, 0];
|
|
432
|
+
for (const maxLen of steps) {
|
|
433
|
+
const trimmed = maxLen === 0 ? void 0 : truncateChars(hint, maxLen);
|
|
434
|
+
const candidate = {
|
|
435
|
+
...next,
|
|
436
|
+
error: {
|
|
437
|
+
...next.error,
|
|
438
|
+
hint: trimmed
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
if (estimateEventBytes(candidate) <= maxBytes) {
|
|
442
|
+
return { event: candidate, downgraded: true };
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const fallback = next.error ? {
|
|
446
|
+
...next,
|
|
447
|
+
error: {
|
|
448
|
+
...next.error,
|
|
449
|
+
message: truncateChars(next.error.message, 96),
|
|
450
|
+
hint: void 0
|
|
451
|
+
}
|
|
452
|
+
} : next;
|
|
453
|
+
return { event: fallback, downgraded: true };
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
// src/internal/runtime/core/process/selectorSchema.ts
|
|
457
|
+
import * as SchemaAST from "effect/SchemaAST";
|
|
458
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null;
|
|
459
|
+
var resolveSchemaAst = (schema) => {
|
|
460
|
+
if (!isRecord2(schema)) return void 0;
|
|
461
|
+
const ast = schema.ast;
|
|
462
|
+
if (!ast) return void 0;
|
|
463
|
+
if (typeof ast !== "object" && typeof ast !== "function") return void 0;
|
|
464
|
+
return ast;
|
|
465
|
+
};
|
|
466
|
+
var makeDotPathError = (path, message, hint) => {
|
|
467
|
+
const err = new Error(message);
|
|
468
|
+
err.code = "process::invalid_dot_path";
|
|
469
|
+
err.hint = hint ?? [
|
|
470
|
+
"Expected dot-path syntax: segments separated by '.', numeric segments represent array indices.",
|
|
471
|
+
`path: ${path}`,
|
|
472
|
+
"",
|
|
473
|
+
"examples:",
|
|
474
|
+
"- count",
|
|
475
|
+
"- user.name",
|
|
476
|
+
"- items.0.id"
|
|
477
|
+
].join("\n");
|
|
478
|
+
return err;
|
|
479
|
+
};
|
|
480
|
+
var makeSchemaMismatchError = (path) => makeDotPathError(
|
|
481
|
+
path,
|
|
482
|
+
"Invalid dot-path: path does not match the state schema.",
|
|
483
|
+
[
|
|
484
|
+
"The module state schema does not contain the requested dot-path.",
|
|
485
|
+
`path: ${path}`,
|
|
486
|
+
"",
|
|
487
|
+
"fix:",
|
|
488
|
+
"- Ensure the path exists in the state schema.",
|
|
489
|
+
"- Use numeric segments for array indices (e.g. items.0.id)."
|
|
490
|
+
].join("\n")
|
|
491
|
+
);
|
|
492
|
+
var parseDotPath = (path) => {
|
|
493
|
+
if (typeof path !== "string" || path.length === 0) {
|
|
494
|
+
return { ok: false, error: makeDotPathError(String(path), "dot-path must be a non-empty string") };
|
|
495
|
+
}
|
|
496
|
+
const raw = path.split(".");
|
|
497
|
+
if (raw.length === 0) {
|
|
498
|
+
return { ok: false, error: makeDotPathError(path, "dot-path must contain at least one segment") };
|
|
499
|
+
}
|
|
500
|
+
const segments = [];
|
|
501
|
+
for (let i = 0; i < raw.length; i++) {
|
|
502
|
+
const seg = raw[i];
|
|
503
|
+
if (seg.length === 0) {
|
|
504
|
+
return {
|
|
505
|
+
ok: false,
|
|
506
|
+
error: makeDotPathError(
|
|
507
|
+
path,
|
|
508
|
+
`Invalid dot-path: empty segment at index ${i}.`,
|
|
509
|
+
[
|
|
510
|
+
"Expected dot-path syntax: segments separated by '.', numeric segments represent array indices.",
|
|
511
|
+
`path: ${path}`,
|
|
512
|
+
"",
|
|
513
|
+
"examples:",
|
|
514
|
+
"- count",
|
|
515
|
+
"- user.name",
|
|
516
|
+
"- items.0.id",
|
|
517
|
+
"",
|
|
518
|
+
"fix:",
|
|
519
|
+
"- Remove consecutive dots or trailing dots."
|
|
520
|
+
].join("\n")
|
|
521
|
+
)
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
if (/^[0-9]+$/.test(seg)) {
|
|
525
|
+
const n = Number(seg);
|
|
526
|
+
if (!Number.isFinite(n) || n < 0) {
|
|
527
|
+
return {
|
|
528
|
+
ok: false,
|
|
529
|
+
error: makeDotPathError(path, `Invalid array index segment "${seg}" at index ${i}.`)
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
segments.push(Math.floor(n));
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
segments.push(seg);
|
|
536
|
+
}
|
|
537
|
+
return { ok: true, segments };
|
|
538
|
+
};
|
|
539
|
+
var resolveAstForPath = (ast, segments, seen) => {
|
|
540
|
+
if (segments.length === 0) return ast;
|
|
541
|
+
let current = ast;
|
|
542
|
+
while (true) {
|
|
543
|
+
if (SchemaAST.isSuspend(current)) {
|
|
544
|
+
if (seen.has(current)) return void 0;
|
|
545
|
+
seen.add(current);
|
|
546
|
+
current = current.f();
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
if (SchemaAST.isRefinement(current)) {
|
|
550
|
+
current = current.from;
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
break;
|
|
554
|
+
}
|
|
555
|
+
if (SchemaAST.isTransformation(current)) {
|
|
556
|
+
const from = resolveAstForPath(current.from, segments, seen);
|
|
557
|
+
if (from) return from;
|
|
558
|
+
return resolveAstForPath(current.to, segments, seen);
|
|
559
|
+
}
|
|
560
|
+
if (SchemaAST.isUnion(current)) {
|
|
561
|
+
for (const node of current.types) {
|
|
562
|
+
const resolved = resolveAstForPath(node, segments, seen);
|
|
563
|
+
if (resolved) return resolved;
|
|
564
|
+
}
|
|
565
|
+
return void 0;
|
|
566
|
+
}
|
|
567
|
+
if (SchemaAST.isTupleType(current)) {
|
|
568
|
+
const [head, ...tail] = segments;
|
|
569
|
+
if (typeof head !== "number") return void 0;
|
|
570
|
+
const element = head < current.elements.length ? current.elements[head] : current.rest.length > 0 ? current.rest[0] : void 0;
|
|
571
|
+
return element ? resolveAstForPath(element.type, tail, seen) : void 0;
|
|
572
|
+
}
|
|
573
|
+
if (SchemaAST.isTypeLiteral(current)) {
|
|
574
|
+
const [head, ...tail] = segments;
|
|
575
|
+
if (head === void 0) return void 0;
|
|
576
|
+
if (typeof head === "string") {
|
|
577
|
+
for (const ps of current.propertySignatures) {
|
|
578
|
+
if (String(ps.name) !== head) continue;
|
|
579
|
+
return resolveAstForPath(ps.type, tail, seen);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
for (const sig of current.indexSignatures) {
|
|
583
|
+
let param = sig.parameter;
|
|
584
|
+
while (SchemaAST.isRefinement(param)) {
|
|
585
|
+
param = param.from;
|
|
586
|
+
}
|
|
587
|
+
const tag2 = param?._tag;
|
|
588
|
+
const acceptsString = tag2 === "StringKeyword" || tag2 === "TemplateLiteral";
|
|
589
|
+
const acceptsNumber = tag2 === "NumberKeyword";
|
|
590
|
+
if (typeof head === "string" && acceptsString) {
|
|
591
|
+
return resolveAstForPath(sig.type, tail, seen);
|
|
592
|
+
}
|
|
593
|
+
if (typeof head === "number" && acceptsNumber) {
|
|
594
|
+
return resolveAstForPath(sig.type, tail, seen);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const tag = current?._tag;
|
|
599
|
+
if (tag === "AnyKeyword" || tag === "UnknownKeyword" || tag === "ObjectKeyword" || tag === "Declaration") {
|
|
600
|
+
return current;
|
|
601
|
+
}
|
|
602
|
+
return void 0;
|
|
603
|
+
};
|
|
604
|
+
var selectBySegments = (segments) => (state) => {
|
|
605
|
+
let current = state;
|
|
606
|
+
for (const seg of segments) {
|
|
607
|
+
if (current == null) return void 0;
|
|
608
|
+
if (typeof seg === "number") {
|
|
609
|
+
if (Array.isArray(current)) {
|
|
610
|
+
current = current[seg];
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
if (isRecord2(current)) {
|
|
614
|
+
current = current[String(seg)];
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
return void 0;
|
|
618
|
+
}
|
|
619
|
+
if (isRecord2(current)) {
|
|
620
|
+
current = current[seg];
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
return void 0;
|
|
624
|
+
}
|
|
625
|
+
return current;
|
|
626
|
+
};
|
|
627
|
+
var makeSchemaSelector = (path, schemaAst) => {
|
|
628
|
+
const parsed = parseDotPath(path);
|
|
629
|
+
if (!parsed.ok) return { ok: false, error: parsed.error };
|
|
630
|
+
if (schemaAst) {
|
|
631
|
+
const resolved = resolveAstForPath(schemaAst, parsed.segments, /* @__PURE__ */ new Set());
|
|
632
|
+
if (!resolved) {
|
|
633
|
+
return { ok: false, error: makeSchemaMismatchError(path) };
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
return {
|
|
637
|
+
ok: true,
|
|
638
|
+
selector: selectBySegments(parsed.segments),
|
|
639
|
+
segments: parsed.segments
|
|
640
|
+
};
|
|
641
|
+
};
|
|
642
|
+
|
|
643
|
+
// src/internal/runtime/core/process/supervision.ts
|
|
644
|
+
var initialState = () => ({ failureTimes: [] });
|
|
645
|
+
var onFailure = (policy, state, nowMs) => {
|
|
646
|
+
if (policy.mode === "failStop") {
|
|
647
|
+
return {
|
|
648
|
+
decision: "stop",
|
|
649
|
+
nextState: state,
|
|
650
|
+
withinWindowFailures: state.failureTimes.length,
|
|
651
|
+
maxRestarts: 0,
|
|
652
|
+
windowMs: policy.windowMs
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
const maxRestartsRaw = policy.maxRestarts;
|
|
656
|
+
const maxRestarts = typeof maxRestartsRaw === "number" && Number.isFinite(maxRestartsRaw) && maxRestartsRaw >= 0 ? Math.floor(maxRestartsRaw) : 0;
|
|
657
|
+
if (maxRestarts <= 0) {
|
|
658
|
+
return {
|
|
659
|
+
decision: "stop",
|
|
660
|
+
nextState: state,
|
|
661
|
+
withinWindowFailures: state.failureTimes.length,
|
|
662
|
+
maxRestarts,
|
|
663
|
+
windowMs: policy.windowMs
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
const windowMsRaw = policy.windowMs;
|
|
667
|
+
const windowMs = typeof windowMsRaw === "number" && Number.isFinite(windowMsRaw) && windowMsRaw > 0 ? Math.floor(windowMsRaw) : void 0;
|
|
668
|
+
const failureTimesRaw = [...state.failureTimes, nowMs];
|
|
669
|
+
const failureTimes = windowMs ? failureTimesRaw.filter((t) => t >= nowMs - windowMs) : failureTimesRaw;
|
|
670
|
+
const cap = maxRestarts + 1;
|
|
671
|
+
const capped = failureTimes.length > cap ? failureTimes.slice(failureTimes.length - cap) : failureTimes;
|
|
672
|
+
const withinWindowFailures = capped.length;
|
|
673
|
+
const decision = withinWindowFailures <= maxRestarts ? "restart" : "stop";
|
|
674
|
+
return {
|
|
675
|
+
decision,
|
|
676
|
+
nextState: { failureTimes: capped },
|
|
677
|
+
withinWindowFailures,
|
|
678
|
+
maxRestarts,
|
|
679
|
+
windowMs
|
|
680
|
+
};
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// src/internal/runtime/core/process/ProcessRuntime.ts
|
|
684
|
+
var ProcessRuntimeTag = class extends Context2.Tag("@logixjs/core/ProcessRuntime")() {
|
|
685
|
+
};
|
|
686
|
+
var currentProcessTrigger = FiberRef2.unsafeMake(void 0);
|
|
687
|
+
var currentProcessEventBudget = FiberRef2.unsafeMake(
|
|
688
|
+
void 0
|
|
689
|
+
);
|
|
690
|
+
var RUNTIME_BOOT_EVENT = "runtime:boot";
|
|
691
|
+
var deriveDebugModuleId = (processId) => `process:${processId}`;
|
|
692
|
+
var deriveTxnAnchor = (event) => {
|
|
693
|
+
const trigger = event.trigger;
|
|
694
|
+
if (!trigger) return {};
|
|
695
|
+
if ((trigger.kind === "moduleAction" || trigger.kind === "moduleStateChange") && typeof trigger.instanceId === "string" && typeof trigger.txnSeq === "number" && Number.isFinite(trigger.txnSeq) && trigger.txnSeq >= 1) {
|
|
696
|
+
const txnSeq = Math.floor(trigger.txnSeq);
|
|
697
|
+
return {
|
|
698
|
+
txnSeq,
|
|
699
|
+
txnId: `${trigger.instanceId}::t${txnSeq}`
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
return {};
|
|
703
|
+
};
|
|
704
|
+
var shouldNoopDueToSyncTxn = (scope, kind) => {
|
|
705
|
+
const moduleId = scope.type === "moduleInstance" ? scope.moduleId : void 0;
|
|
706
|
+
const instanceId = scope.type === "moduleInstance" ? scope.instanceId : void 0;
|
|
707
|
+
return shouldNoopInSyncTransactionFiber({
|
|
708
|
+
moduleId,
|
|
709
|
+
instanceId,
|
|
710
|
+
code: "process::invalid_usage",
|
|
711
|
+
severity: "error",
|
|
712
|
+
message: "ProcessRuntime scheduling is not allowed inside a synchronous StateTransaction body (it may deadlock the txnQueue).",
|
|
713
|
+
hint: "Trigger/schedule Process outside the transaction window (e.g. in a watcher's run section or a separate fiber); do not trigger Process directly inside a reducer / synchronous transaction body.",
|
|
714
|
+
kind
|
|
715
|
+
});
|
|
716
|
+
};
|
|
717
|
+
var resolveRuntimeStateSchemaAst = (runtime) => {
|
|
718
|
+
try {
|
|
719
|
+
const internals = getRuntimeInternals(runtime);
|
|
720
|
+
return resolveSchemaAst(internals.stateSchema);
|
|
721
|
+
} catch {
|
|
722
|
+
return void 0;
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
var withModuleHint = (error, moduleId) => {
|
|
726
|
+
const hint = error.hint;
|
|
727
|
+
if (typeof hint === "string" && hint.length > 0) {
|
|
728
|
+
if (!hint.includes("moduleId=")) {
|
|
729
|
+
;
|
|
730
|
+
error.hint = `moduleId=${moduleId}
|
|
731
|
+
${hint}`;
|
|
732
|
+
}
|
|
733
|
+
return error;
|
|
734
|
+
}
|
|
735
|
+
;
|
|
736
|
+
error.hint = `moduleId=${moduleId}`;
|
|
737
|
+
return error;
|
|
738
|
+
};
|
|
739
|
+
var actionIdFromUnknown = (action) => {
|
|
740
|
+
if (!action || typeof action !== "object") return void 0;
|
|
741
|
+
const anyAction = action;
|
|
742
|
+
if (typeof anyAction._tag === "string" && anyAction._tag.length > 0) return anyAction._tag;
|
|
743
|
+
if (typeof anyAction.type === "string" && anyAction.type.length > 0) return anyAction.type;
|
|
744
|
+
return void 0;
|
|
745
|
+
};
|
|
746
|
+
var make = (options) => Effect3.gen(function* () {
|
|
747
|
+
const runtimeScope = yield* Effect3.scope;
|
|
748
|
+
const maxEventHistory = typeof options?.maxEventHistory === "number" && Number.isFinite(options.maxEventHistory) && options.maxEventHistory >= 0 ? Math.floor(options.maxEventHistory) : 500;
|
|
749
|
+
const installations = /* @__PURE__ */ new Map();
|
|
750
|
+
const instances = /* @__PURE__ */ new Map();
|
|
751
|
+
const eventsBuffer = [];
|
|
752
|
+
const eventsHub = yield* PubSub.sliding(Math.max(1, Math.min(2048, maxEventHistory)));
|
|
753
|
+
const trimEvents = () => {
|
|
754
|
+
if (maxEventHistory <= 0) {
|
|
755
|
+
eventsBuffer.length = 0;
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
if (eventsBuffer.length <= maxEventHistory) return;
|
|
759
|
+
const excess = eventsBuffer.length - maxEventHistory;
|
|
760
|
+
eventsBuffer.splice(0, excess);
|
|
761
|
+
};
|
|
762
|
+
const recordDebugEvent = (event) => Effect3.gen(function* () {
|
|
763
|
+
const diagnosticsLevel = yield* FiberRef2.get(currentDiagnosticsLevel);
|
|
764
|
+
if (diagnosticsLevel === "off") {
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
const processId = event.identity.identity.processId;
|
|
768
|
+
const processInstanceId = processInstanceIdFromIdentity(event.identity);
|
|
769
|
+
const moduleId = deriveDebugModuleId(processId);
|
|
770
|
+
const { txnSeq, txnId } = deriveTxnAnchor(event);
|
|
771
|
+
yield* record({
|
|
772
|
+
type: event.type,
|
|
773
|
+
moduleId,
|
|
774
|
+
instanceId: processInstanceId,
|
|
775
|
+
identity: event.identity,
|
|
776
|
+
severity: event.severity,
|
|
777
|
+
eventSeq: event.eventSeq,
|
|
778
|
+
timestampMs: event.timestampMs,
|
|
779
|
+
trigger: event.trigger,
|
|
780
|
+
dispatch: event.dispatch,
|
|
781
|
+
error: event.error,
|
|
782
|
+
txnSeq,
|
|
783
|
+
txnId
|
|
784
|
+
});
|
|
785
|
+
});
|
|
786
|
+
const publishEvent = (event) => Effect3.gen(function* () {
|
|
787
|
+
eventsBuffer.push(event);
|
|
788
|
+
trimEvents();
|
|
789
|
+
yield* PubSub.publish(eventsHub, event);
|
|
790
|
+
yield* recordDebugEvent(event);
|
|
791
|
+
});
|
|
792
|
+
const emit = (event) => Effect3.gen(function* () {
|
|
793
|
+
const budgetRef = yield* FiberRef2.get(currentProcessEventBudget);
|
|
794
|
+
if (budgetRef) {
|
|
795
|
+
const decision = yield* Ref2.modify(budgetRef, (state) => {
|
|
796
|
+
const [nextDecision, nextState] = applyProcessRunEventBudget(state, event);
|
|
797
|
+
return [nextDecision, nextState];
|
|
798
|
+
});
|
|
799
|
+
if (decision._tag === "emit" || decision._tag === "emitSummary") {
|
|
800
|
+
yield* publishEvent(decision.event);
|
|
801
|
+
}
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
const enforced = enforceProcessEventMaxBytes(event);
|
|
805
|
+
yield* publishEvent(enforced.event);
|
|
806
|
+
});
|
|
807
|
+
const emitErrorDiagnostic = (scope, processId, code, message, hint) => {
|
|
808
|
+
if (!isDevEnv()) {
|
|
809
|
+
return Effect3.void;
|
|
810
|
+
}
|
|
811
|
+
const moduleId = scope.type === "moduleInstance" ? scope.moduleId : void 0;
|
|
812
|
+
const instanceId = scope.type === "moduleInstance" ? scope.instanceId : void 0;
|
|
813
|
+
return record({
|
|
814
|
+
type: "diagnostic",
|
|
815
|
+
moduleId,
|
|
816
|
+
instanceId,
|
|
817
|
+
code,
|
|
818
|
+
severity: "error",
|
|
819
|
+
message,
|
|
820
|
+
hint,
|
|
821
|
+
actionTag: processId,
|
|
822
|
+
kind: "process_runtime"
|
|
823
|
+
});
|
|
824
|
+
};
|
|
825
|
+
const resolveMissingDependencies = (installation) => {
|
|
826
|
+
const declared = installation.definition.requires ?? [];
|
|
827
|
+
const implicitFromTriggers = [];
|
|
828
|
+
for (const trigger of installation.definition.triggers) {
|
|
829
|
+
if (trigger.kind === "moduleAction" || trigger.kind === "moduleStateChange") {
|
|
830
|
+
implicitFromTriggers.push(trigger.moduleId);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
const requires = Array.from(/* @__PURE__ */ new Set([...declared, ...implicitFromTriggers]));
|
|
834
|
+
if (requires.length === 0) return [];
|
|
835
|
+
const missing = [];
|
|
836
|
+
for (const dep of requires) {
|
|
837
|
+
if (typeof dep !== "string" || dep.length === 0) continue;
|
|
838
|
+
const tag = Context2.Tag(`@logixjs/Module/${dep}`)();
|
|
839
|
+
const found = Context2.getOption(installation.env, tag);
|
|
840
|
+
if (Option2.isNone(found)) {
|
|
841
|
+
missing.push(dep);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return missing;
|
|
845
|
+
};
|
|
846
|
+
const stopInstance = (instance, reason) => Effect3.gen(function* () {
|
|
847
|
+
if (instance.status.status === "stopped" || instance.status.status === "failed" || instance.status.status === "stopping") {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
const fiber = instance.fiber;
|
|
851
|
+
instance.status = {
|
|
852
|
+
...instance.status,
|
|
853
|
+
status: "stopping",
|
|
854
|
+
stoppedReason: reason
|
|
855
|
+
};
|
|
856
|
+
if (fiber) {
|
|
857
|
+
yield* Fiber2.interrupt(fiber);
|
|
858
|
+
}
|
|
859
|
+
yield* Queue.shutdown(instance.platformTriggersQueue);
|
|
860
|
+
instance.status = {
|
|
861
|
+
...instance.status,
|
|
862
|
+
status: "stopped",
|
|
863
|
+
stoppedReason: reason
|
|
864
|
+
};
|
|
865
|
+
instance.fiber = void 0;
|
|
866
|
+
const evt = {
|
|
867
|
+
type: "process:stop",
|
|
868
|
+
identity: instance.identity,
|
|
869
|
+
severity: "info",
|
|
870
|
+
eventSeq: instance.nextEventSeq++,
|
|
871
|
+
timestampMs: Date.now()
|
|
872
|
+
};
|
|
873
|
+
yield* emit(evt);
|
|
874
|
+
const installation = installations.get(instance.installationKey);
|
|
875
|
+
if (installation?.pendingStart) {
|
|
876
|
+
installation.pendingStart = void 0;
|
|
877
|
+
yield* startInstallation(instance.installationKey);
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
const startInstallation = (installationKey) => Effect3.gen(function* () {
|
|
881
|
+
const installation = installations.get(installationKey);
|
|
882
|
+
if (!installation) return;
|
|
883
|
+
installation.pendingStart = void 0;
|
|
884
|
+
const noop = yield* shouldNoopDueToSyncTxn(installation.identity.scope, "process_start_in_transaction");
|
|
885
|
+
if (noop) return;
|
|
886
|
+
const currentId = installation.currentInstanceId;
|
|
887
|
+
if (currentId) {
|
|
888
|
+
const current = instances.get(currentId);
|
|
889
|
+
if (current && (current.status.status === "running" || current.status.status === "starting")) {
|
|
890
|
+
return;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
const runSeq = installation.nextRunSeq++;
|
|
894
|
+
const identity = {
|
|
895
|
+
identity: installation.identity,
|
|
896
|
+
runSeq
|
|
897
|
+
};
|
|
898
|
+
const processInstanceId = processInstanceIdFromIdentity(identity);
|
|
899
|
+
const platformTriggersQueue = yield* Queue.sliding(64);
|
|
900
|
+
const instanceState = {
|
|
901
|
+
installationKey,
|
|
902
|
+
processInstanceId,
|
|
903
|
+
identity,
|
|
904
|
+
processId: installation.identity.processId,
|
|
905
|
+
scope: installation.identity.scope,
|
|
906
|
+
forkScope: installation.forkScope,
|
|
907
|
+
platformTriggersQueue,
|
|
908
|
+
status: {
|
|
909
|
+
identity,
|
|
910
|
+
status: "starting"
|
|
911
|
+
},
|
|
912
|
+
nextEventSeq: 1,
|
|
913
|
+
nextTriggerSeq: 1
|
|
914
|
+
};
|
|
915
|
+
instances.set(processInstanceId, instanceState);
|
|
916
|
+
installation.currentInstanceId = processInstanceId;
|
|
917
|
+
if (installation.forkScope !== runtimeScope) {
|
|
918
|
+
yield* Scope2.addFinalizer(
|
|
919
|
+
installation.forkScope,
|
|
920
|
+
Effect3.suspend(() => {
|
|
921
|
+
const status = instanceState.status.status;
|
|
922
|
+
if (status === "stopped" || status === "failed" || status === "stopping") {
|
|
923
|
+
return Effect3.void;
|
|
924
|
+
}
|
|
925
|
+
return stopInstance(instanceState, "scopeDisposed");
|
|
926
|
+
}).pipe(Effect3.catchAllCause(() => Effect3.void))
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
yield* emit({
|
|
930
|
+
type: "process:start",
|
|
931
|
+
identity,
|
|
932
|
+
severity: "info",
|
|
933
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
934
|
+
timestampMs: Date.now()
|
|
935
|
+
});
|
|
936
|
+
const missing = resolveMissingDependencies(installation);
|
|
937
|
+
if (missing.length > 0) {
|
|
938
|
+
const hint = isDevEnv() ? [
|
|
939
|
+
"Strict scope dependency resolution: missing required modules in the current scope.",
|
|
940
|
+
`missing: ${missing.join(", ")}`,
|
|
941
|
+
"",
|
|
942
|
+
"fix:",
|
|
943
|
+
"- Provide the missing module implementation(s) in the same scope via imports.",
|
|
944
|
+
` Example: RootModule.implement({ imports: [${missing[0]}.implement(...).impl], processes: [...] })`,
|
|
945
|
+
"- Do not rely on cross-scope fallbacks / guessing instances."
|
|
946
|
+
].join("\n") : void 0;
|
|
947
|
+
const error = {
|
|
948
|
+
message: `Missing dependencies in scope: ${missing.join(", ")}`,
|
|
949
|
+
code: "process::missing_dependency",
|
|
950
|
+
hint
|
|
951
|
+
};
|
|
952
|
+
instanceState.status = {
|
|
953
|
+
...instanceState.status,
|
|
954
|
+
status: "failed",
|
|
955
|
+
stoppedReason: "failed",
|
|
956
|
+
lastError: error
|
|
957
|
+
};
|
|
958
|
+
yield* emit({
|
|
959
|
+
type: "process:error",
|
|
960
|
+
identity,
|
|
961
|
+
severity: "error",
|
|
962
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
963
|
+
timestampMs: Date.now(),
|
|
964
|
+
error
|
|
965
|
+
});
|
|
966
|
+
yield* emitErrorDiagnostic(
|
|
967
|
+
installation.identity.scope,
|
|
968
|
+
installation.identity.processId,
|
|
969
|
+
"process::missing_dependency",
|
|
970
|
+
error.message,
|
|
971
|
+
hint
|
|
972
|
+
);
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
const shouldRecordChainEvents = installation.definition.diagnosticsLevel !== "off";
|
|
976
|
+
const baseEnv = installation.env;
|
|
977
|
+
const makeWrappedEnv = () => {
|
|
978
|
+
if (!shouldRecordChainEvents) {
|
|
979
|
+
return baseEnv;
|
|
980
|
+
}
|
|
981
|
+
const requires = installation.definition.requires ?? [];
|
|
982
|
+
if (requires.length === 0) {
|
|
983
|
+
return baseEnv;
|
|
984
|
+
}
|
|
985
|
+
const ids = Array.from(new Set(requires));
|
|
986
|
+
let nextEnv = baseEnv;
|
|
987
|
+
for (const moduleId of ids) {
|
|
988
|
+
if (typeof moduleId !== "string" || moduleId.length === 0) continue;
|
|
989
|
+
const tag = Context2.Tag(`@logixjs/Module/${moduleId}`)();
|
|
990
|
+
const found = Context2.getOption(baseEnv, tag);
|
|
991
|
+
if (Option2.isNone(found)) continue;
|
|
992
|
+
const runtime = found.value;
|
|
993
|
+
const recordDispatch = (action) => Effect3.gen(function* () {
|
|
994
|
+
const trigger = yield* FiberRef2.get(currentProcessTrigger);
|
|
995
|
+
if (!trigger) return;
|
|
996
|
+
const actionId = actionIdFromUnknown(action) ?? "unknown";
|
|
997
|
+
const dispatchModuleId = typeof runtime.moduleId === "string" ? runtime.moduleId : moduleId;
|
|
998
|
+
const dispatchInstanceId = typeof runtime.instanceId === "string" ? runtime.instanceId : "unknown";
|
|
999
|
+
const evt = {
|
|
1000
|
+
type: "process:dispatch",
|
|
1001
|
+
identity,
|
|
1002
|
+
trigger,
|
|
1003
|
+
dispatch: {
|
|
1004
|
+
moduleId: dispatchModuleId,
|
|
1005
|
+
instanceId: dispatchInstanceId,
|
|
1006
|
+
actionId
|
|
1007
|
+
},
|
|
1008
|
+
severity: "info",
|
|
1009
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
1010
|
+
timestampMs: Date.now()
|
|
1011
|
+
};
|
|
1012
|
+
yield* emit(evt);
|
|
1013
|
+
});
|
|
1014
|
+
const wrapped = {
|
|
1015
|
+
...runtime,
|
|
1016
|
+
dispatch: (action) => runtime.dispatch(action).pipe(Effect3.tap(() => recordDispatch(action))),
|
|
1017
|
+
dispatchLowPriority: (action) => runtime.dispatchLowPriority(action).pipe(Effect3.tap(() => recordDispatch(action))),
|
|
1018
|
+
dispatchBatch: (actions) => runtime.dispatchBatch(actions).pipe(Effect3.tap(() => Effect3.forEach(actions, recordDispatch, { discard: true })))
|
|
1019
|
+
};
|
|
1020
|
+
nextEnv = Context2.add(tag, wrapped)(nextEnv);
|
|
1021
|
+
}
|
|
1022
|
+
return nextEnv;
|
|
1023
|
+
};
|
|
1024
|
+
const wrappedEnv = makeWrappedEnv();
|
|
1025
|
+
const providedProcess = Effect3.provide(installation.process, wrappedEnv);
|
|
1026
|
+
const makeTriggerStream = (spec) => Effect3.gen(function* () {
|
|
1027
|
+
if (spec.kind === "timer") {
|
|
1028
|
+
const interval = Duration.decodeUnknown(spec.timerId);
|
|
1029
|
+
if (Option2.isNone(interval)) {
|
|
1030
|
+
const err = new Error(`[ProcessRuntime] invalid timerId (expected DurationInput): ${spec.timerId}`);
|
|
1031
|
+
err.code = "process::invalid_timer_id";
|
|
1032
|
+
err.hint = "timerId must be a valid DurationInput string, e.g. '10 millis', '1 seconds', '5 minutes'.";
|
|
1033
|
+
return yield* Effect3.fail(err);
|
|
1034
|
+
}
|
|
1035
|
+
return Stream2.tick(interval.value).pipe(
|
|
1036
|
+
Stream2.map(
|
|
1037
|
+
() => ({
|
|
1038
|
+
kind: "timer",
|
|
1039
|
+
name: spec.name,
|
|
1040
|
+
timerId: spec.timerId
|
|
1041
|
+
})
|
|
1042
|
+
)
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1045
|
+
if (spec.kind === "moduleAction") {
|
|
1046
|
+
const tag2 = Context2.Tag(`@logixjs/Module/${spec.moduleId}`)();
|
|
1047
|
+
const found2 = Context2.getOption(baseEnv, tag2);
|
|
1048
|
+
if (Option2.isNone(found2)) {
|
|
1049
|
+
return yield* Effect3.fail(new Error(`Missing module runtime in scope: ${spec.moduleId}`));
|
|
1050
|
+
}
|
|
1051
|
+
const runtime2 = found2.value;
|
|
1052
|
+
if (!shouldRecordChainEvents) {
|
|
1053
|
+
const stream2 = runtime2.actions$;
|
|
1054
|
+
if (!stream2) {
|
|
1055
|
+
const err = new Error("ModuleRuntime does not provide actions$ (required for moduleAction trigger).");
|
|
1056
|
+
err.code = "process::missing_action_stream";
|
|
1057
|
+
err.hint = `moduleId=${spec.moduleId}`;
|
|
1058
|
+
return yield* Effect3.fail(err);
|
|
1059
|
+
}
|
|
1060
|
+
return stream2.pipe(
|
|
1061
|
+
Stream2.filter((action) => actionIdFromUnknown(action) === spec.actionId),
|
|
1062
|
+
Stream2.map(
|
|
1063
|
+
() => ({
|
|
1064
|
+
kind: "moduleAction",
|
|
1065
|
+
name: spec.name,
|
|
1066
|
+
moduleId: spec.moduleId,
|
|
1067
|
+
instanceId: runtime2.instanceId,
|
|
1068
|
+
actionId: spec.actionId,
|
|
1069
|
+
txnSeq: 1
|
|
1070
|
+
})
|
|
1071
|
+
)
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
const stream = runtime2.actionsWithMeta$;
|
|
1075
|
+
if (!stream) {
|
|
1076
|
+
const err = new Error(
|
|
1077
|
+
"ModuleRuntime does not provide actionsWithMeta$ (required for moduleAction trigger)."
|
|
1078
|
+
);
|
|
1079
|
+
err.code = "process::missing_action_meta_stream";
|
|
1080
|
+
err.hint = `moduleId=${spec.moduleId}`;
|
|
1081
|
+
return yield* Effect3.fail(err);
|
|
1082
|
+
}
|
|
1083
|
+
return stream.pipe(
|
|
1084
|
+
Stream2.filter((evt) => actionIdFromUnknown(evt.value) === spec.actionId),
|
|
1085
|
+
Stream2.map((evt) => {
|
|
1086
|
+
const txnSeq = evt?.meta?.txnSeq;
|
|
1087
|
+
return {
|
|
1088
|
+
kind: "moduleAction",
|
|
1089
|
+
name: spec.name,
|
|
1090
|
+
moduleId: spec.moduleId,
|
|
1091
|
+
instanceId: runtime2.instanceId,
|
|
1092
|
+
actionId: spec.actionId,
|
|
1093
|
+
txnSeq: typeof txnSeq === "number" ? txnSeq : 1
|
|
1094
|
+
};
|
|
1095
|
+
})
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
const tag = Context2.Tag(`@logixjs/Module/${spec.moduleId}`)();
|
|
1099
|
+
const found = Context2.getOption(baseEnv, tag);
|
|
1100
|
+
if (Option2.isNone(found)) {
|
|
1101
|
+
return yield* Effect3.fail(new Error(`Missing module runtime in scope: ${spec.moduleId}`));
|
|
1102
|
+
}
|
|
1103
|
+
const runtime = found.value;
|
|
1104
|
+
const schemaAst = resolveRuntimeStateSchemaAst(runtime);
|
|
1105
|
+
const selectorResult = makeSchemaSelector(spec.path, schemaAst);
|
|
1106
|
+
if (!selectorResult.ok) {
|
|
1107
|
+
return yield* Effect3.fail(withModuleHint(selectorResult.error, spec.moduleId));
|
|
1108
|
+
}
|
|
1109
|
+
const selectorBase = selectorResult.selector;
|
|
1110
|
+
const prevRef = yield* Ref2.make(Option2.none());
|
|
1111
|
+
const enableSelectorDiagnostics = shouldRecordChainEvents;
|
|
1112
|
+
const selectorDiagnosticsRef = enableSelectorDiagnostics ? yield* Ref2.make({
|
|
1113
|
+
windowStartedMs: Date.now(),
|
|
1114
|
+
triggersInWindow: 0,
|
|
1115
|
+
lastWarningAtMs: 0
|
|
1116
|
+
}) : void 0;
|
|
1117
|
+
const sampleEveryMask = 127;
|
|
1118
|
+
const slowSampleThresholdMs = 4;
|
|
1119
|
+
const triggerWindowMs = 1e3;
|
|
1120
|
+
const triggerWarningThreshold = isDevEnv() ? 20 : 200;
|
|
1121
|
+
const warningCooldownMs = 3e4;
|
|
1122
|
+
let selectorCalls = 0;
|
|
1123
|
+
let selectorSamples = 0;
|
|
1124
|
+
let selectorSlowSamples = 0;
|
|
1125
|
+
let selectorMaxSampleMs = 0;
|
|
1126
|
+
const nowMs = () => {
|
|
1127
|
+
if (typeof performance !== "undefined" && typeof performance.now === "function") {
|
|
1128
|
+
return performance.now();
|
|
1129
|
+
}
|
|
1130
|
+
return Date.now();
|
|
1131
|
+
};
|
|
1132
|
+
const selector = enableSelectorDiagnostics ? (state) => {
|
|
1133
|
+
selectorCalls += 1;
|
|
1134
|
+
if ((selectorCalls & sampleEveryMask) !== 0) {
|
|
1135
|
+
return selectorBase(state);
|
|
1136
|
+
}
|
|
1137
|
+
const t0 = nowMs();
|
|
1138
|
+
const value = selectorBase(state);
|
|
1139
|
+
const dt = nowMs() - t0;
|
|
1140
|
+
selectorSamples += 1;
|
|
1141
|
+
if (dt >= slowSampleThresholdMs) {
|
|
1142
|
+
selectorSlowSamples += 1;
|
|
1143
|
+
}
|
|
1144
|
+
if (dt > selectorMaxSampleMs) {
|
|
1145
|
+
selectorMaxSampleMs = dt;
|
|
1146
|
+
}
|
|
1147
|
+
return value;
|
|
1148
|
+
} : selectorBase;
|
|
1149
|
+
const maybeWarnSelector = (trigger) => {
|
|
1150
|
+
if (!selectorDiagnosticsRef) {
|
|
1151
|
+
return Effect3.void;
|
|
1152
|
+
}
|
|
1153
|
+
return Effect3.gen(function* () {
|
|
1154
|
+
const now = Date.now();
|
|
1155
|
+
const decision = yield* Ref2.modify(selectorDiagnosticsRef, (s) => {
|
|
1156
|
+
const windowExpired = now - s.windowStartedMs >= triggerWindowMs;
|
|
1157
|
+
const windowStartedMs = windowExpired ? now : s.windowStartedMs;
|
|
1158
|
+
const triggersInWindow = windowExpired ? 1 : s.triggersInWindow + 1;
|
|
1159
|
+
const shouldCooldown = now - s.lastWarningAtMs < warningCooldownMs;
|
|
1160
|
+
const tooFrequent = triggersInWindow >= triggerWarningThreshold;
|
|
1161
|
+
const tooSlow = selectorMaxSampleMs >= slowSampleThresholdMs && selectorSamples > 0;
|
|
1162
|
+
const shouldWarn = !shouldCooldown && (tooFrequent || tooSlow);
|
|
1163
|
+
const next = shouldWarn ? {
|
|
1164
|
+
windowStartedMs: now,
|
|
1165
|
+
triggersInWindow: 0,
|
|
1166
|
+
lastWarningAtMs: now
|
|
1167
|
+
} : {
|
|
1168
|
+
...s,
|
|
1169
|
+
windowStartedMs,
|
|
1170
|
+
triggersInWindow
|
|
1171
|
+
};
|
|
1172
|
+
return [
|
|
1173
|
+
{
|
|
1174
|
+
shouldWarn,
|
|
1175
|
+
tooFrequent,
|
|
1176
|
+
tooSlow,
|
|
1177
|
+
triggersInWindow
|
|
1178
|
+
},
|
|
1179
|
+
next
|
|
1180
|
+
];
|
|
1181
|
+
});
|
|
1182
|
+
if (!decision.shouldWarn) {
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
const code = decision.tooFrequent ? "process::selector_high_frequency" : "process::selector_slow";
|
|
1186
|
+
const hint = [
|
|
1187
|
+
`moduleId=${spec.moduleId}`,
|
|
1188
|
+
`path=${spec.path}`,
|
|
1189
|
+
`windowMs=${triggerWindowMs}`,
|
|
1190
|
+
`triggersInWindow=${decision.triggersInWindow}`,
|
|
1191
|
+
`threshold=${triggerWarningThreshold}`,
|
|
1192
|
+
`cooldownMs=${warningCooldownMs}`,
|
|
1193
|
+
"",
|
|
1194
|
+
"selector sampling:",
|
|
1195
|
+
`calls=${selectorCalls}`,
|
|
1196
|
+
`sampled=${selectorSamples}`,
|
|
1197
|
+
`slowSamples(>=${slowSampleThresholdMs}ms)=${selectorSlowSamples}`,
|
|
1198
|
+
`maxSampleMs=${selectorMaxSampleMs.toFixed(2)}`,
|
|
1199
|
+
"",
|
|
1200
|
+
"notes:",
|
|
1201
|
+
"- Ensure the selected value is stable (prefer primitive/tuple; avoid returning fresh objects).",
|
|
1202
|
+
"- Narrow the path to reduce change frequency; avoid selecting large objects."
|
|
1203
|
+
].join("\n");
|
|
1204
|
+
selectorSamples = 0;
|
|
1205
|
+
selectorSlowSamples = 0;
|
|
1206
|
+
selectorMaxSampleMs = 0;
|
|
1207
|
+
yield* emit({
|
|
1208
|
+
type: "process:trigger",
|
|
1209
|
+
identity,
|
|
1210
|
+
trigger,
|
|
1211
|
+
severity: "warning",
|
|
1212
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
1213
|
+
timestampMs: Date.now(),
|
|
1214
|
+
error: {
|
|
1215
|
+
message: "moduleStateChange selector diagnostics warning",
|
|
1216
|
+
code,
|
|
1217
|
+
hint
|
|
1218
|
+
}
|
|
1219
|
+
});
|
|
1220
|
+
});
|
|
1221
|
+
};
|
|
1222
|
+
const baseStream = runtime.changesWithMeta(selector).pipe(
|
|
1223
|
+
Stream2.mapEffect(
|
|
1224
|
+
(evt) => Ref2.get(prevRef).pipe(
|
|
1225
|
+
Effect3.flatMap((prev) => {
|
|
1226
|
+
if (Option2.isSome(prev) && Object.is(prev.value, evt.value)) {
|
|
1227
|
+
return Effect3.succeed(Option2.none());
|
|
1228
|
+
}
|
|
1229
|
+
return Ref2.set(prevRef, Option2.some(evt.value)).pipe(Effect3.as(Option2.some(evt)));
|
|
1230
|
+
})
|
|
1231
|
+
)
|
|
1232
|
+
),
|
|
1233
|
+
Stream2.filterMap((opt) => opt),
|
|
1234
|
+
Stream2.map((evt) => {
|
|
1235
|
+
const txnSeq = evt?.meta?.txnSeq;
|
|
1236
|
+
return {
|
|
1237
|
+
kind: "moduleStateChange",
|
|
1238
|
+
name: spec.name,
|
|
1239
|
+
moduleId: spec.moduleId,
|
|
1240
|
+
instanceId: runtime.instanceId,
|
|
1241
|
+
path: spec.path,
|
|
1242
|
+
txnSeq: typeof txnSeq === "number" ? txnSeq : 1
|
|
1243
|
+
};
|
|
1244
|
+
})
|
|
1245
|
+
);
|
|
1246
|
+
return enableSelectorDiagnostics ? baseStream.pipe(Stream2.tap(maybeWarnSelector)) : baseStream;
|
|
1247
|
+
});
|
|
1248
|
+
const makeRun = (trigger, fatal) => Effect3.locally(
|
|
1249
|
+
currentProcessTrigger,
|
|
1250
|
+
trigger
|
|
1251
|
+
)(
|
|
1252
|
+
providedProcess.pipe(
|
|
1253
|
+
Effect3.catchAllCause((cause) => {
|
|
1254
|
+
if (Cause.isInterruptedOnly(cause)) {
|
|
1255
|
+
return Effect3.void;
|
|
1256
|
+
}
|
|
1257
|
+
return Deferred.succeed(fatal, cause).pipe(
|
|
1258
|
+
Effect3.asVoid,
|
|
1259
|
+
Effect3.catchAll(() => Effect3.void)
|
|
1260
|
+
);
|
|
1261
|
+
})
|
|
1262
|
+
)
|
|
1263
|
+
);
|
|
1264
|
+
const makeChainRun = (trigger, fatal) => {
|
|
1265
|
+
if (!shouldRecordChainEvents) {
|
|
1266
|
+
return makeRun(trigger, fatal);
|
|
1267
|
+
}
|
|
1268
|
+
return Effect3.gen(function* () {
|
|
1269
|
+
const budgetRef = yield* Ref2.make(makeProcessRunEventBudgetState());
|
|
1270
|
+
return yield* Effect3.locally(
|
|
1271
|
+
currentProcessEventBudget,
|
|
1272
|
+
budgetRef
|
|
1273
|
+
)(emitTriggerEvent(trigger, "info").pipe(Effect3.zipRight(makeRun(trigger, fatal))));
|
|
1274
|
+
});
|
|
1275
|
+
};
|
|
1276
|
+
const assignTriggerSeq = (trigger) => {
|
|
1277
|
+
if (!shouldRecordChainEvents) {
|
|
1278
|
+
return trigger;
|
|
1279
|
+
}
|
|
1280
|
+
return {
|
|
1281
|
+
...trigger,
|
|
1282
|
+
triggerSeq: instanceState.nextTriggerSeq++
|
|
1283
|
+
};
|
|
1284
|
+
};
|
|
1285
|
+
const emitTriggerEvent = (trigger, severity) => {
|
|
1286
|
+
if (!shouldRecordChainEvents) {
|
|
1287
|
+
return Effect3.void;
|
|
1288
|
+
}
|
|
1289
|
+
const evt = {
|
|
1290
|
+
type: "process:trigger",
|
|
1291
|
+
identity,
|
|
1292
|
+
trigger,
|
|
1293
|
+
severity,
|
|
1294
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
1295
|
+
timestampMs: Date.now()
|
|
1296
|
+
};
|
|
1297
|
+
return emit(evt);
|
|
1298
|
+
};
|
|
1299
|
+
const policy = installation.definition.concurrency;
|
|
1300
|
+
const autoStart = installation.definition.triggers.some(
|
|
1301
|
+
(t) => t.kind === "platformEvent" && t.platformEvent === RUNTIME_BOOT_EVENT
|
|
1302
|
+
);
|
|
1303
|
+
const bootTriggerSpec = installation.definition.triggers.find(
|
|
1304
|
+
(t) => t.kind === "platformEvent" && t.platformEvent === RUNTIME_BOOT_EVENT
|
|
1305
|
+
);
|
|
1306
|
+
const instanceProgram = Effect3.gen(function* () {
|
|
1307
|
+
const fatal = yield* Deferred.make();
|
|
1308
|
+
const platformEventStream = Stream2.fromQueue(
|
|
1309
|
+
instanceState.platformTriggersQueue
|
|
1310
|
+
);
|
|
1311
|
+
const nonPlatformTriggers = installation.definition.triggers.filter(
|
|
1312
|
+
(t) => t.kind !== "platformEvent"
|
|
1313
|
+
);
|
|
1314
|
+
const streams = yield* Effect3.forEach(nonPlatformTriggers, makeTriggerStream);
|
|
1315
|
+
const triggerStream = Stream2.mergeAll([platformEventStream, ...streams], {
|
|
1316
|
+
concurrency: "unbounded"
|
|
1317
|
+
});
|
|
1318
|
+
const reportQueueOverflow = (info) => {
|
|
1319
|
+
const err = new Error("Process trigger queue overflow (serial maxQueue guard).");
|
|
1320
|
+
err.code = "process::serial_queue_overflow";
|
|
1321
|
+
err.hint = [
|
|
1322
|
+
`mode=${info.mode}`,
|
|
1323
|
+
`queue: current=${info.currentLength} peak=${info.peak}`,
|
|
1324
|
+
`maxQueue: configured=${info.limit.configured} guard=${info.limit.guard}`,
|
|
1325
|
+
`policy: ${JSON.stringify(info.policy)}`,
|
|
1326
|
+
"",
|
|
1327
|
+
"fix:",
|
|
1328
|
+
"- Configure concurrency.maxQueue (serial) to a finite value, or switch to mode=latest/drop to avoid unbounded backlog."
|
|
1329
|
+
].join("\n");
|
|
1330
|
+
return Deferred.succeed(fatal, Cause.fail(err)).pipe(
|
|
1331
|
+
Effect3.asVoid,
|
|
1332
|
+
Effect3.catchAll(() => Effect3.void)
|
|
1333
|
+
);
|
|
1334
|
+
};
|
|
1335
|
+
const runnerFiber = yield* Effect3.forkScoped(
|
|
1336
|
+
runProcessTriggerStream({
|
|
1337
|
+
stream: triggerStream,
|
|
1338
|
+
policy,
|
|
1339
|
+
assignTriggerSeq,
|
|
1340
|
+
run: (trigger) => makeChainRun(trigger, fatal),
|
|
1341
|
+
onDrop: (trigger) => emitTriggerEvent(trigger, "warning"),
|
|
1342
|
+
onQueueOverflow: reportQueueOverflow
|
|
1343
|
+
})
|
|
1344
|
+
);
|
|
1345
|
+
if (autoStart) {
|
|
1346
|
+
yield* Queue.offer(instanceState.platformTriggersQueue, {
|
|
1347
|
+
kind: "platformEvent",
|
|
1348
|
+
name: bootTriggerSpec?.name,
|
|
1349
|
+
platformEvent: RUNTIME_BOOT_EVENT
|
|
1350
|
+
});
|
|
1351
|
+
}
|
|
1352
|
+
const cause = yield* Deferred.await(fatal);
|
|
1353
|
+
yield* Fiber2.interrupt(runnerFiber);
|
|
1354
|
+
return yield* Effect3.failCause(cause);
|
|
1355
|
+
});
|
|
1356
|
+
const fiber = yield* Effect3.forkIn(installation.forkScope)(
|
|
1357
|
+
Effect3.scoped(instanceProgram).pipe(
|
|
1358
|
+
Effect3.catchAllCause(
|
|
1359
|
+
(cause) => Effect3.gen(function* () {
|
|
1360
|
+
if (Cause.isInterruptedOnly(cause)) {
|
|
1361
|
+
if (instanceState.status.status === "stopping") {
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
instanceState.status = {
|
|
1365
|
+
...instanceState.status,
|
|
1366
|
+
status: "stopped",
|
|
1367
|
+
stoppedReason: "scopeDisposed"
|
|
1368
|
+
};
|
|
1369
|
+
instanceState.fiber = void 0;
|
|
1370
|
+
yield* Effect3.uninterruptible(
|
|
1371
|
+
emit({
|
|
1372
|
+
type: "process:stop",
|
|
1373
|
+
identity,
|
|
1374
|
+
severity: "info",
|
|
1375
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
1376
|
+
timestampMs: Date.now()
|
|
1377
|
+
})
|
|
1378
|
+
);
|
|
1379
|
+
const installation2 = installations.get(installationKey);
|
|
1380
|
+
if (installation2?.pendingStart) {
|
|
1381
|
+
installation2.pendingStart = void 0;
|
|
1382
|
+
yield* startInstallation(installationKey);
|
|
1383
|
+
}
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
const primary = Option2.getOrElse(
|
|
1387
|
+
Cause.failureOption(cause),
|
|
1388
|
+
() => Option2.getOrElse(Cause.dieOption(cause), () => cause)
|
|
1389
|
+
);
|
|
1390
|
+
const summary = toSerializableErrorSummary(primary);
|
|
1391
|
+
const error = summary.errorSummary;
|
|
1392
|
+
instanceState.status = {
|
|
1393
|
+
...instanceState.status,
|
|
1394
|
+
status: "failed",
|
|
1395
|
+
stoppedReason: "failed",
|
|
1396
|
+
lastError: error
|
|
1397
|
+
};
|
|
1398
|
+
yield* emit({
|
|
1399
|
+
type: "process:error",
|
|
1400
|
+
identity,
|
|
1401
|
+
severity: "error",
|
|
1402
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
1403
|
+
timestampMs: Date.now(),
|
|
1404
|
+
error
|
|
1405
|
+
});
|
|
1406
|
+
const decision = onFailure(
|
|
1407
|
+
installation.definition.errorPolicy,
|
|
1408
|
+
installation.supervision,
|
|
1409
|
+
Date.now()
|
|
1410
|
+
);
|
|
1411
|
+
installation.supervision = decision.nextState;
|
|
1412
|
+
if (decision.decision === "restart") {
|
|
1413
|
+
yield* emit({
|
|
1414
|
+
type: "process:restart",
|
|
1415
|
+
identity,
|
|
1416
|
+
severity: "warning",
|
|
1417
|
+
eventSeq: instanceState.nextEventSeq++,
|
|
1418
|
+
timestampMs: Date.now(),
|
|
1419
|
+
error
|
|
1420
|
+
});
|
|
1421
|
+
yield* startInstallation(installationKey);
|
|
1422
|
+
} else {
|
|
1423
|
+
yield* emitErrorDiagnostic(
|
|
1424
|
+
installation.identity.scope,
|
|
1425
|
+
installation.identity.processId,
|
|
1426
|
+
"process::failed_stop",
|
|
1427
|
+
"Process failed and stopped (failStop / restart limit reached).",
|
|
1428
|
+
`processId=${installation.identity.processId} scopeKey=${installation.scopeKey} failures=${decision.withinWindowFailures} maxRestarts=${decision.maxRestarts}`
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
})
|
|
1432
|
+
)
|
|
1433
|
+
)
|
|
1434
|
+
);
|
|
1435
|
+
instanceState.fiber = fiber;
|
|
1436
|
+
instanceState.status = {
|
|
1437
|
+
...instanceState.status,
|
|
1438
|
+
status: "running"
|
|
1439
|
+
};
|
|
1440
|
+
yield* Effect3.yieldNow();
|
|
1441
|
+
});
|
|
1442
|
+
const install = (process, options2) => Effect3.gen(function* () {
|
|
1443
|
+
const meta = getMeta(process);
|
|
1444
|
+
if (!meta) {
|
|
1445
|
+
return void 0;
|
|
1446
|
+
}
|
|
1447
|
+
const env = yield* Effect3.context();
|
|
1448
|
+
const forkScopeOpt = yield* Effect3.serviceOption(Scope2.Scope);
|
|
1449
|
+
const forkScope = Option2.isSome(forkScopeOpt) ? forkScopeOpt.value : runtimeScope;
|
|
1450
|
+
const scopeKey = scopeKeyFromScope(options2.scope);
|
|
1451
|
+
const identity = {
|
|
1452
|
+
processId: meta.definition.processId,
|
|
1453
|
+
scope: options2.scope
|
|
1454
|
+
};
|
|
1455
|
+
const installationKey = installationKeyFromIdentity(identity);
|
|
1456
|
+
const existing = installations.get(installationKey);
|
|
1457
|
+
if (existing) {
|
|
1458
|
+
existing.env = env;
|
|
1459
|
+
existing.forkScope = forkScope;
|
|
1460
|
+
existing.enabled = options2.enabled ?? true;
|
|
1461
|
+
existing.installedAt = options2.installedAt ?? existing.installedAt;
|
|
1462
|
+
if (!existing.enabled) {
|
|
1463
|
+
existing.pendingStart = void 0;
|
|
1464
|
+
return {
|
|
1465
|
+
identity,
|
|
1466
|
+
enabled: existing.enabled,
|
|
1467
|
+
installedAt: existing.installedAt
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
const currentId = existing.currentInstanceId;
|
|
1471
|
+
const current = currentId ? instances.get(currentId) : void 0;
|
|
1472
|
+
const status = current?.status.status;
|
|
1473
|
+
if (status === "running" || status === "starting") {
|
|
1474
|
+
const mode = options2.mode ?? "switch";
|
|
1475
|
+
if (mode === "switch" && current && current.forkScope !== forkScope) {
|
|
1476
|
+
existing.pendingStart = { forkScope };
|
|
1477
|
+
yield* Scope2.addFinalizer(
|
|
1478
|
+
forkScope,
|
|
1479
|
+
Effect3.sync(() => {
|
|
1480
|
+
const installation2 = installations.get(installationKey);
|
|
1481
|
+
if (!installation2) return;
|
|
1482
|
+
if (installation2.pendingStart?.forkScope === forkScope) {
|
|
1483
|
+
installation2.pendingStart = void 0;
|
|
1484
|
+
}
|
|
1485
|
+
})
|
|
1486
|
+
);
|
|
1487
|
+
} else {
|
|
1488
|
+
existing.pendingStart = void 0;
|
|
1489
|
+
}
|
|
1490
|
+
return {
|
|
1491
|
+
identity,
|
|
1492
|
+
enabled: existing.enabled,
|
|
1493
|
+
installedAt: existing.installedAt
|
|
1494
|
+
};
|
|
1495
|
+
}
|
|
1496
|
+
if (status === "stopping") {
|
|
1497
|
+
const mode = options2.mode ?? "switch";
|
|
1498
|
+
if (mode === "switch") {
|
|
1499
|
+
existing.pendingStart = { forkScope };
|
|
1500
|
+
yield* Scope2.addFinalizer(
|
|
1501
|
+
forkScope,
|
|
1502
|
+
Effect3.sync(() => {
|
|
1503
|
+
const installation2 = installations.get(installationKey);
|
|
1504
|
+
if (!installation2) return;
|
|
1505
|
+
if (installation2.pendingStart?.forkScope === forkScope) {
|
|
1506
|
+
installation2.pendingStart = void 0;
|
|
1507
|
+
}
|
|
1508
|
+
})
|
|
1509
|
+
);
|
|
1510
|
+
} else {
|
|
1511
|
+
existing.pendingStart = void 0;
|
|
1512
|
+
}
|
|
1513
|
+
return {
|
|
1514
|
+
identity,
|
|
1515
|
+
enabled: existing.enabled,
|
|
1516
|
+
installedAt: existing.installedAt
|
|
1517
|
+
};
|
|
1518
|
+
}
|
|
1519
|
+
existing.pendingStart = void 0;
|
|
1520
|
+
yield* startInstallation(installationKey);
|
|
1521
|
+
return {
|
|
1522
|
+
identity,
|
|
1523
|
+
enabled: existing.enabled,
|
|
1524
|
+
installedAt: existing.installedAt
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
const derived = Effect3.suspend(() => process);
|
|
1528
|
+
attachMeta(derived, {
|
|
1529
|
+
...meta,
|
|
1530
|
+
installationScope: options2.scope
|
|
1531
|
+
});
|
|
1532
|
+
const installation = {
|
|
1533
|
+
identity,
|
|
1534
|
+
scopeKey,
|
|
1535
|
+
definition: meta.definition,
|
|
1536
|
+
env,
|
|
1537
|
+
forkScope,
|
|
1538
|
+
process: derived,
|
|
1539
|
+
kind: meta.kind ?? "process",
|
|
1540
|
+
enabled: options2.enabled ?? true,
|
|
1541
|
+
installedAt: options2.installedAt,
|
|
1542
|
+
nextRunSeq: 1,
|
|
1543
|
+
supervision: initialState(),
|
|
1544
|
+
pendingStart: void 0
|
|
1545
|
+
};
|
|
1546
|
+
installations.set(installationKey, installation);
|
|
1547
|
+
if (installation.enabled) {
|
|
1548
|
+
yield* startInstallation(installationKey);
|
|
1549
|
+
}
|
|
1550
|
+
return {
|
|
1551
|
+
identity,
|
|
1552
|
+
enabled: installation.enabled,
|
|
1553
|
+
installedAt: installation.installedAt
|
|
1554
|
+
};
|
|
1555
|
+
});
|
|
1556
|
+
const listInstallations = (filter) => Effect3.sync(() => {
|
|
1557
|
+
const scopeType = filter?.scopeType;
|
|
1558
|
+
const scopeKey = filter?.scopeKey;
|
|
1559
|
+
const out = [];
|
|
1560
|
+
for (const installation of installations.values()) {
|
|
1561
|
+
if (scopeType && installation.identity.scope.type !== scopeType) continue;
|
|
1562
|
+
if (scopeKey && installation.scopeKey !== scopeKey) continue;
|
|
1563
|
+
out.push({
|
|
1564
|
+
identity: installation.identity,
|
|
1565
|
+
enabled: installation.enabled,
|
|
1566
|
+
installedAt: installation.installedAt
|
|
1567
|
+
});
|
|
1568
|
+
}
|
|
1569
|
+
return out;
|
|
1570
|
+
});
|
|
1571
|
+
const getInstanceStatus = (processInstanceId) => Effect3.sync(() => instances.get(processInstanceId)?.status);
|
|
1572
|
+
const controlInstance = (processInstanceId, request) => Effect3.suspend(() => {
|
|
1573
|
+
const instance = instances.get(processInstanceId);
|
|
1574
|
+
if (!instance) {
|
|
1575
|
+
return Effect3.void;
|
|
1576
|
+
}
|
|
1577
|
+
return shouldNoopDueToSyncTxn(instance.scope, "process_control_in_transaction").pipe(
|
|
1578
|
+
Effect3.flatMap((noop) => {
|
|
1579
|
+
if (noop) {
|
|
1580
|
+
return Effect3.void;
|
|
1581
|
+
}
|
|
1582
|
+
if (request.action === "stop") {
|
|
1583
|
+
return stopInstance(instance, "manualStop");
|
|
1584
|
+
}
|
|
1585
|
+
if (request.action === "restart") {
|
|
1586
|
+
return stopInstance(instance, "manualStop").pipe(
|
|
1587
|
+
Effect3.flatMap(() => {
|
|
1588
|
+
const installation = installations.get(instance.installationKey);
|
|
1589
|
+
if (!installation) {
|
|
1590
|
+
return Effect3.void;
|
|
1591
|
+
}
|
|
1592
|
+
installation.currentInstanceId = void 0;
|
|
1593
|
+
return startInstallation(instance.installationKey);
|
|
1594
|
+
})
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1597
|
+
if (request.action === "start") {
|
|
1598
|
+
if (instance.status.status === "running" || instance.status.status === "starting") {
|
|
1599
|
+
return Effect3.void;
|
|
1600
|
+
}
|
|
1601
|
+
const installation = installations.get(instance.installationKey);
|
|
1602
|
+
if (!installation) {
|
|
1603
|
+
return Effect3.void;
|
|
1604
|
+
}
|
|
1605
|
+
installation.currentInstanceId = void 0;
|
|
1606
|
+
return startInstallation(instance.installationKey);
|
|
1607
|
+
}
|
|
1608
|
+
return Effect3.void;
|
|
1609
|
+
})
|
|
1610
|
+
);
|
|
1611
|
+
});
|
|
1612
|
+
const deliverPlatformEvent = (event) => Effect3.gen(function* () {
|
|
1613
|
+
const noop = yield* shouldNoopInSyncTransactionFiber({
|
|
1614
|
+
code: "process::invalid_usage",
|
|
1615
|
+
severity: "error",
|
|
1616
|
+
message: "ProcessRuntime platform events are not allowed inside a synchronous StateTransaction body (it may deadlock the txnQueue).",
|
|
1617
|
+
hint: "Deliver platformEvent outside the transaction window.",
|
|
1618
|
+
kind: "process_platform_event_in_transaction"
|
|
1619
|
+
});
|
|
1620
|
+
if (noop) return;
|
|
1621
|
+
const targets = Array.from(instances.values());
|
|
1622
|
+
const eventName = event.eventName;
|
|
1623
|
+
yield* Effect3.forEach(
|
|
1624
|
+
targets,
|
|
1625
|
+
(instance) => Effect3.suspend(() => {
|
|
1626
|
+
if (instance.status.status !== "starting" && instance.status.status !== "running") {
|
|
1627
|
+
return Effect3.void;
|
|
1628
|
+
}
|
|
1629
|
+
const installation = installations.get(instance.installationKey);
|
|
1630
|
+
if (!installation) {
|
|
1631
|
+
return Effect3.void;
|
|
1632
|
+
}
|
|
1633
|
+
const specs = installation.definition.triggers.filter(
|
|
1634
|
+
(t) => t.kind === "platformEvent" && t.platformEvent === eventName
|
|
1635
|
+
);
|
|
1636
|
+
if (specs.length === 0) {
|
|
1637
|
+
return Effect3.void;
|
|
1638
|
+
}
|
|
1639
|
+
return Effect3.forEach(
|
|
1640
|
+
specs,
|
|
1641
|
+
(spec) => Queue.offer(instance.platformTriggersQueue, {
|
|
1642
|
+
kind: "platformEvent",
|
|
1643
|
+
name: spec.name,
|
|
1644
|
+
platformEvent: spec.platformEvent
|
|
1645
|
+
}),
|
|
1646
|
+
{ discard: true }
|
|
1647
|
+
);
|
|
1648
|
+
}),
|
|
1649
|
+
{ discard: true }
|
|
1650
|
+
);
|
|
1651
|
+
});
|
|
1652
|
+
const eventsStream = Stream2.fromPubSub(eventsHub);
|
|
1653
|
+
const getEventsSnapshot = () => Effect3.sync(() => eventsBuffer.slice());
|
|
1654
|
+
yield* Effect3.addFinalizer(
|
|
1655
|
+
() => Effect3.gen(function* () {
|
|
1656
|
+
for (const installation of installations.values()) {
|
|
1657
|
+
installation.pendingStart = void 0;
|
|
1658
|
+
}
|
|
1659
|
+
for (const instance of instances.values()) {
|
|
1660
|
+
if (instance.fiber) {
|
|
1661
|
+
yield* stopInstance(instance, "scopeDisposed");
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}).pipe(
|
|
1665
|
+
Effect3.catchAllCause(
|
|
1666
|
+
(cause) => Effect3.sync(() => {
|
|
1667
|
+
if (isDevEnv()) {
|
|
1668
|
+
console.warn("[ProcessRuntime] finalizer failed", Cause.pretty(cause));
|
|
1669
|
+
}
|
|
1670
|
+
})
|
|
1671
|
+
)
|
|
1672
|
+
)
|
|
1673
|
+
);
|
|
1674
|
+
return {
|
|
1675
|
+
install,
|
|
1676
|
+
listInstallations,
|
|
1677
|
+
getInstanceStatus,
|
|
1678
|
+
controlInstance,
|
|
1679
|
+
deliverPlatformEvent,
|
|
1680
|
+
events: eventsStream,
|
|
1681
|
+
getEventsSnapshot
|
|
1682
|
+
};
|
|
1683
|
+
});
|
|
1684
|
+
var layer = (options) => Layer2.scoped(ProcessRuntimeTag, make(options));
|
|
1685
|
+
|
|
1686
|
+
export {
|
|
1687
|
+
EvidenceCollectorTag,
|
|
1688
|
+
evidenceCollectorLayer,
|
|
1689
|
+
makeEvidenceCollector,
|
|
1690
|
+
getMeta,
|
|
1691
|
+
getDefinition,
|
|
1692
|
+
attachMeta,
|
|
1693
|
+
ProcessRuntimeTag,
|
|
1694
|
+
layer
|
|
1695
|
+
};
|
|
1696
|
+
//# sourceMappingURL=chunk-PAYXCY6A.js.map
|