@effect-agent/platform-node 0.1.0-beta.53 → 0.1.0-beta.55
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/{NodeDurableAgentRuntime-D3ka19Zy.d.mts → NodeDurableAgentRuntime-CPmWN-L_.d.mts} +2 -2
- package/dist/NodeDurableAgentRuntime.d.mts +1 -1
- package/dist/NodeDurableHost.d.mts +2 -2
- package/dist/{NodeWakeScheduler-DWdHIhWA.d.mts → NodeWakeScheduler-4ZeXYwPu.d.mts} +2 -2
- package/dist/NodeWakeScheduler.d.mts +1 -1
- package/dist/NodeWakeScheduler.mjs +9 -5
- package/dist/NodeWakeScheduler.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/package.json +1 -1
- package/src/NodeWakeScheduler.ts +11 -6
package/dist/{NodeDurableAgentRuntime-D3ka19Zy.d.mts → NodeDurableAgentRuntime-CPmWN-L_.d.mts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as NodeWakeSchedulerConfig } from "./NodeWakeScheduler-
|
|
1
|
+
import { t as NodeWakeSchedulerConfig } from "./NodeWakeScheduler-4ZeXYwPu.mjs";
|
|
2
2
|
import { RunContextPreparation, RunCostEstimator, RunToolAuthorization, RunToolFailureObserver } from "@effect-agent/engine/RunOptions";
|
|
3
3
|
import { SqliteStorageConfig } from "@effect-agent/storage-sqlite/SqliteStorageConfig";
|
|
4
4
|
import { SqliteStorageFailpointHandler } from "@effect-agent/storage-sqlite/SqliteStorageFailpoint";
|
|
@@ -168,4 +168,4 @@ declare class NodeDurableAgentRuntime {
|
|
|
168
168
|
}
|
|
169
169
|
//#endregion
|
|
170
170
|
export { NodeDurableAgentRuntimeOptions as a, NodePlatformConfigError as c, NodeDurableAgentRuntimeInitializationError as i, ownershipDrainLayer as l, NodeDurableAgentRuntimeConfig as n, NodeDurableAgentRuntimeServices as o, NodeDurableAgentRuntimeConfigValue as r, NodeDurableAgentRuntime_d_exports as s, NodeDurableAgentRuntime as t };
|
|
171
|
-
//# sourceMappingURL=NodeDurableAgentRuntime-
|
|
171
|
+
//# sourceMappingURL=NodeDurableAgentRuntime-CPmWN-L_.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as NodeDurableAgentRuntimeOptions, c as NodePlatformConfigError, i as NodeDurableAgentRuntimeInitializationError, l as ownershipDrainLayer, n as NodeDurableAgentRuntimeConfig, o as NodeDurableAgentRuntimeServices, r as NodeDurableAgentRuntimeConfigValue, t as NodeDurableAgentRuntime } from "./NodeDurableAgentRuntime-
|
|
1
|
+
import { a as NodeDurableAgentRuntimeOptions, c as NodePlatformConfigError, i as NodeDurableAgentRuntimeInitializationError, l as ownershipDrainLayer, n as NodeDurableAgentRuntimeConfig, o as NodeDurableAgentRuntimeServices, r as NodeDurableAgentRuntimeConfigValue, t as NodeDurableAgentRuntime } from "./NodeDurableAgentRuntime-CPmWN-L_.mjs";
|
|
2
2
|
export { NodeDurableAgentRuntime, NodeDurableAgentRuntimeConfig, NodeDurableAgentRuntimeConfigValue, NodeDurableAgentRuntimeInitializationError, NodeDurableAgentRuntimeOptions, NodeDurableAgentRuntimeServices, NodePlatformConfigError, ownershipDrainLayer };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as NodeWakeSchedulerConfig } from "./NodeWakeScheduler-
|
|
2
|
-
import { a as NodeDurableAgentRuntimeOptions, c as NodePlatformConfigError, n as NodeDurableAgentRuntimeConfig, o as NodeDurableAgentRuntimeServices } from "./NodeDurableAgentRuntime-
|
|
1
|
+
import { t as NodeWakeSchedulerConfig } from "./NodeWakeScheduler-4ZeXYwPu.mjs";
|
|
2
|
+
import { a as NodeDurableAgentRuntimeOptions, c as NodePlatformConfigError, n as NodeDurableAgentRuntimeConfig, o as NodeDurableAgentRuntimeServices } from "./NodeDurableAgentRuntime-CPmWN-L_.mjs";
|
|
3
3
|
import { SubmissionId, ThreadId } from "@effect-agent/core/Identifiers";
|
|
4
4
|
import { AgentRegistration, DurableBindingFailure, ResolvedBinding } from "@effect-agent/thread/AgentRegistration";
|
|
5
5
|
import { DurableAbortFailure, DurableAgentRuntime, DurableAwaitFailure, DurableExplainFailure, DurableObligationFailure, DurableObserveOptions, DurableRetryFailure, DurableSubmitAgent, DurableSubmitFailure, DurableSubmitOptions, DurableVerifyFailure, DurableWorkerFailure, Receipt, RecoveryReport } from "@effect-agent/thread/DurableAgentRuntime";
|
|
@@ -16,7 +16,7 @@ declare class NodeWakeSchedulerConfig extends NodeWakeSchedulerConfig_base {
|
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* In-process Node `WakeScheduler`: `notify` publishes to a bounded sliding PubSub for prompt
|
|
19
|
-
* same-process wakeups, and
|
|
19
|
+
* same-process wakeups, and active `wakes` subscriptions share one periodic
|
|
20
20
|
* `SubmissionLedger.scanNonterminal` fallback so a dropped, coalesced, or never-sent notification
|
|
21
21
|
* can never strand accepted work (persistence §14). Delivery may duplicate; consumers already
|
|
22
22
|
* treat wakes as pure liveness hints.
|
|
@@ -24,4 +24,4 @@ declare class NodeWakeSchedulerConfig extends NodeWakeSchedulerConfig_base {
|
|
|
24
24
|
declare const nodeWakeSchedulerLayer: Layer.Layer<WakeScheduler, never, SubmissionLedger | NodeWakeSchedulerConfig>;
|
|
25
25
|
//#endregion
|
|
26
26
|
export { NodeWakeScheduler_d_exports as n, nodeWakeSchedulerLayer as r, NodeWakeSchedulerConfig as t };
|
|
27
|
-
//# sourceMappingURL=NodeWakeScheduler-
|
|
27
|
+
//# sourceMappingURL=NodeWakeScheduler-4ZeXYwPu.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { r as nodeWakeSchedulerLayer, t as NodeWakeSchedulerConfig } from "./NodeWakeScheduler-
|
|
1
|
+
import { r as nodeWakeSchedulerLayer, t as NodeWakeSchedulerConfig } from "./NodeWakeScheduler-4ZeXYwPu.mjs";
|
|
2
2
|
export { NodeWakeSchedulerConfig, nodeWakeSchedulerLayer };
|
|
@@ -37,19 +37,23 @@ const makeWakeScheduler = Effect.gen(function* () {
|
|
|
37
37
|
}), Effect.catch((error) => Effect.logWarning("NodeWakeScheduler fallback scan failed", error).pipe(Effect.as([]))));
|
|
38
38
|
/**
|
|
39
39
|
* Deployment §3: correctness must not depend on in-memory notifications, so every `wakes` run
|
|
40
|
-
* merges its PubSub subscription with
|
|
41
|
-
* the
|
|
40
|
+
* merges its PubSub subscription with shared Clock-driven ledger scans. Share whole snapshots:
|
|
41
|
+
* sliding individual lanes would strand the beginning of scans larger than the hint buffer.
|
|
42
|
+
* The scan starts with the first subscriber and stops when the last subscriber leaves.
|
|
42
43
|
*/
|
|
43
|
-
const fallbackScans = Stream.
|
|
44
|
+
const fallbackScans = yield* Stream.share(Stream.fromEffectRepeat(Effect.sleep(config.scanInterval).pipe(Effect.andThen(scanOnce))), {
|
|
45
|
+
capacity: 1,
|
|
46
|
+
strategy: "sliding"
|
|
47
|
+
});
|
|
44
48
|
return WakeScheduler.of({
|
|
45
49
|
notify: (threadId) => progress.notify(threadId).pipe(Effect.andThen(PubSub.publish(hints, threadId)), Effect.asVoid),
|
|
46
50
|
subscribe: progress.subscribe,
|
|
47
|
-
wakes: Stream.merge(Stream.fromPubSub(hints), fallbackScans)
|
|
51
|
+
wakes: Stream.merge(Stream.fromPubSub(hints), fallbackScans.pipe(Stream.flatMap(Stream.fromIterable)))
|
|
48
52
|
});
|
|
49
53
|
});
|
|
50
54
|
/**
|
|
51
55
|
* In-process Node `WakeScheduler`: `notify` publishes to a bounded sliding PubSub for prompt
|
|
52
|
-
* same-process wakeups, and
|
|
56
|
+
* same-process wakeups, and active `wakes` subscriptions share one periodic
|
|
53
57
|
* `SubmissionLedger.scanNonterminal` fallback so a dropped, coalesced, or never-sent notification
|
|
54
58
|
* can never strand accepted work (persistence §14). Delivery may duplicate; consumers already
|
|
55
59
|
* treat wakes as pure liveness hints.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeWakeScheduler.mjs","names":[],"sources":["../src/NodeWakeScheduler.ts"],"sourcesContent":["import { type ThreadId } from \"@effect-agent/core/Identifiers\";\nimport { SubmissionLedger } from \"@effect-agent/thread/SubmissionLedger\";\nimport { makeWakeSubscriptionHub, WakeScheduler } from \"@effect-agent/thread/WakeScheduler\";\nimport type { Duration } from \"effect\";\nimport { Context, Effect, Layer, PubSub, Stream } from \"effect\";\n\n/**\n * Bounded in-process wake buffer. Wake hints are droppable by contract (the ledger-scan fallback\n * keeps liveness), so a full buffer slides out the oldest hint instead of growing without bound.\n */\nconst WAKE_BUFFER_CAPACITY = 1_024;\n\n/** Cadence authority for the Node wake scheduler's ledger-scan fallback loop. */\nexport class NodeWakeSchedulerConfig extends Context.Service<\n NodeWakeSchedulerConfig,\n {\n /** Interval between ledger scans that re-emit every nonterminal Thread lane. */\n readonly scanInterval: Duration.Duration;\n }\n>()(\"@effect-agent/platform-node/NodeWakeSchedulerConfig\") {\n static layer(options: {\n readonly scanInterval: Duration.Duration;\n }): Layer.Layer<NodeWakeSchedulerConfig> {\n return Layer.succeed(NodeWakeSchedulerConfig)({ scanInterval: options.scanInterval });\n }\n}\n\nconst makeWakeScheduler = Effect.gen(function* () {\n const ledger = yield* SubmissionLedger;\n const config = yield* NodeWakeSchedulerConfig;\n const hints = yield* PubSub.sliding<ThreadId>(WAKE_BUFFER_CAPACITY);\n const progress = yield* makeWakeSubscriptionHub;\n\n yield* Effect.addFinalizer(() => PubSub.shutdown(hints));\n\n /**\n * One fallback scan: every Thread lane with nonterminal work, deduplicated. A scan\n * failure degrades to \"no hints this round\" — the wake channel has no error contract and the\n * next round retries — but is logged so a persistently failing ledger stays visible.\n */\n const scanOnce: Effect.Effect<ReadonlyArray<ThreadId>> = Stream.runCollect(\n ledger.scanNonterminal,\n ).pipe(\n Effect.map((snapshots) => {\n const lanes = new Set<ThreadId>();\n\n for (const snapshot of snapshots) {\n lanes.add(snapshot.threadId);\n }\n\n return [...lanes];\n }),\n Effect.catch((error) =>\n Effect.logWarning(\"NodeWakeScheduler fallback scan failed\", error).pipe(\n Effect.as([] as ReadonlyArray<ThreadId>),\n ),\n ),\n );\n\n /**\n * Deployment §3: correctness must not depend on in-memory notifications, so every `wakes` run\n * merges its PubSub subscription with
|
|
1
|
+
{"version":3,"file":"NodeWakeScheduler.mjs","names":[],"sources":["../src/NodeWakeScheduler.ts"],"sourcesContent":["import { type ThreadId } from \"@effect-agent/core/Identifiers\";\nimport { SubmissionLedger } from \"@effect-agent/thread/SubmissionLedger\";\nimport { makeWakeSubscriptionHub, WakeScheduler } from \"@effect-agent/thread/WakeScheduler\";\nimport type { Duration } from \"effect\";\nimport { Context, Effect, Layer, PubSub, Stream } from \"effect\";\n\n/**\n * Bounded in-process wake buffer. Wake hints are droppable by contract (the ledger-scan fallback\n * keeps liveness), so a full buffer slides out the oldest hint instead of growing without bound.\n */\nconst WAKE_BUFFER_CAPACITY = 1_024;\n\n/** Cadence authority for the Node wake scheduler's ledger-scan fallback loop. */\nexport class NodeWakeSchedulerConfig extends Context.Service<\n NodeWakeSchedulerConfig,\n {\n /** Interval between ledger scans that re-emit every nonterminal Thread lane. */\n readonly scanInterval: Duration.Duration;\n }\n>()(\"@effect-agent/platform-node/NodeWakeSchedulerConfig\") {\n static layer(options: {\n readonly scanInterval: Duration.Duration;\n }): Layer.Layer<NodeWakeSchedulerConfig> {\n return Layer.succeed(NodeWakeSchedulerConfig)({ scanInterval: options.scanInterval });\n }\n}\n\nconst makeWakeScheduler = Effect.gen(function* () {\n const ledger = yield* SubmissionLedger;\n const config = yield* NodeWakeSchedulerConfig;\n const hints = yield* PubSub.sliding<ThreadId>(WAKE_BUFFER_CAPACITY);\n const progress = yield* makeWakeSubscriptionHub;\n\n yield* Effect.addFinalizer(() => PubSub.shutdown(hints));\n\n /**\n * One fallback scan: every Thread lane with nonterminal work, deduplicated. A scan\n * failure degrades to \"no hints this round\" — the wake channel has no error contract and the\n * next round retries — but is logged so a persistently failing ledger stays visible.\n */\n const scanOnce: Effect.Effect<ReadonlyArray<ThreadId>> = Stream.runCollect(\n ledger.scanNonterminal,\n ).pipe(\n Effect.map((snapshots) => {\n const lanes = new Set<ThreadId>();\n\n for (const snapshot of snapshots) {\n lanes.add(snapshot.threadId);\n }\n\n return [...lanes];\n }),\n Effect.catch((error) =>\n Effect.logWarning(\"NodeWakeScheduler fallback scan failed\", error).pipe(\n Effect.as([] as ReadonlyArray<ThreadId>),\n ),\n ),\n );\n\n /**\n * Deployment §3: correctness must not depend on in-memory notifications, so every `wakes` run\n * merges its PubSub subscription with shared Clock-driven ledger scans. Share whole snapshots:\n * sliding individual lanes would strand the beginning of scans larger than the hint buffer.\n * The scan starts with the first subscriber and stops when the last subscriber leaves.\n */\n const fallbackScans = yield* Stream.share(\n Stream.fromEffectRepeat(Effect.sleep(config.scanInterval).pipe(Effect.andThen(scanOnce))),\n { capacity: 1, strategy: \"sliding\" },\n );\n\n return WakeScheduler.of({\n notify: (threadId) =>\n progress\n .notify(threadId)\n .pipe(Effect.andThen(PubSub.publish(hints, threadId)), Effect.asVoid),\n subscribe: progress.subscribe,\n wakes: Stream.merge(\n Stream.fromPubSub(hints),\n fallbackScans.pipe(Stream.flatMap(Stream.fromIterable)),\n ),\n });\n});\n\n/**\n * In-process Node `WakeScheduler`: `notify` publishes to a bounded sliding PubSub for prompt\n * same-process wakeups, and active `wakes` subscriptions share one periodic\n * `SubmissionLedger.scanNonterminal` fallback so a dropped, coalesced, or never-sent notification\n * can never strand accepted work (persistence §14). Delivery may duplicate; consumers already\n * treat wakes as pure liveness hints.\n */\nexport const nodeWakeSchedulerLayer: Layer.Layer<\n WakeScheduler,\n never,\n SubmissionLedger | NodeWakeSchedulerConfig\n> = Layer.effect(WakeScheduler)(makeWakeScheduler);\n"],"mappings":";;;;;;;;;;;;;;AAUA,MAAM,uBAAuB;;AAG7B,IAAa,0BAAb,MAAa,gCAAgC,QAAQ,QAMnD,CAAC,CAAC,qDAAqD,CAAC,CAAC;CACzD,OAAO,MAAM,SAE4B;EACvC,OAAO,MAAM,QAAQ,uBAAuB,CAAC,CAAC,EAAE,cAAc,QAAQ,aAAa,CAAC;CACtF;AACF;AAEA,MAAM,oBAAoB,OAAO,IAAI,aAAa;CAChD,MAAM,SAAS,OAAO;CACtB,MAAM,SAAS,OAAO;CACtB,MAAM,QAAQ,OAAO,OAAO,QAAkB,oBAAoB;CAClE,MAAM,WAAW,OAAO;CAExB,OAAO,OAAO,mBAAmB,OAAO,SAAS,KAAK,CAAC;;;;;;CAOvD,MAAM,WAAmD,OAAO,WAC9D,OAAO,eACT,CAAC,CAAC,KACA,OAAO,KAAK,cAAc;EACxB,MAAM,wBAAQ,IAAI,IAAc;EAEhC,KAAK,MAAM,YAAY,WACrB,MAAM,IAAI,SAAS,QAAQ;EAG7B,OAAO,CAAC,GAAG,KAAK;CAClB,CAAC,GACD,OAAO,OAAO,UACZ,OAAO,WAAW,0CAA0C,KAAK,CAAC,CAAC,KACjE,OAAO,GAAG,CAAC,CAA4B,CACzC,CACF,CACF;;;;;;;CAQA,MAAM,gBAAgB,OAAO,OAAO,MAClC,OAAO,iBAAiB,OAAO,MAAM,OAAO,YAAY,CAAC,CAAC,KAAK,OAAO,QAAQ,QAAQ,CAAC,CAAC,GACxF;EAAE,UAAU;EAAG,UAAU;CAAU,CACrC;CAEA,OAAO,cAAc,GAAG;EACtB,SAAS,aACP,SACG,OAAO,QAAQ,CAAC,CAChB,KAAK,OAAO,QAAQ,OAAO,QAAQ,OAAO,QAAQ,CAAC,GAAG,OAAO,MAAM;EACxE,WAAW,SAAS;EACpB,OAAO,OAAO,MACZ,OAAO,WAAW,KAAK,GACvB,cAAc,KAAK,OAAO,QAAQ,OAAO,YAAY,CAAC,CACxD;CACF,CAAC;AACH,CAAC;;;;;;;;AASD,MAAa,yBAIT,MAAM,OAAO,aAAa,CAAC,CAAC,iBAAiB"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as NodeWakeScheduler_d_exports } from "./NodeWakeScheduler-
|
|
2
|
-
import { s as NodeDurableAgentRuntime_d_exports } from "./NodeDurableAgentRuntime-
|
|
1
|
+
import { n as NodeWakeScheduler_d_exports } from "./NodeWakeScheduler-4ZeXYwPu.mjs";
|
|
2
|
+
import { s as NodeDurableAgentRuntime_d_exports } from "./NodeDurableAgentRuntime-CPmWN-L_.mjs";
|
|
3
3
|
import { t as NodeDurableHost_d_exports } from "./NodeDurableHost.mjs";
|
|
4
4
|
import { t as NodeScheduling_d_exports } from "./NodeScheduling.mjs";
|
|
5
5
|
import { t as NodeSubscriptions_d_exports } from "./NodeSubscriptions.mjs";
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@effect-agent/platform-node","version":"0.1.0-beta.
|
|
1
|
+
{"name":"@effect-agent/platform-node","version":"0.1.0-beta.55","dependencies":{"@effect-agent/core":"0.1.0-beta.55","@effect-agent/engine":"0.1.0-beta.55","@effect-agent/storage-sqlite":"0.1.0-beta.55","@effect-agent/thread":"0.1.0-beta.55","@effect-agent/workflow":"0.1.0-beta.55","@effect/platform-node":"4.0.0-rc.112","@effect/sql-sqlite-node":"4.0.0-rc.112"},"devDependencies":{"@effect-agent/capabilities":"0.1.0-beta.55","@effect/vitest":"4.0.0-rc.112","effect":"4.0.0-rc.112","typescript":"7.0.2","vite-plus":"0.3.0"},"peerDependencies":{"effect":"^4.0.0-rc.112"},"exports":{".":{"types":"./dist/index.d.mts","default":"./dist/index.mjs"},"./NodeDurableAgentRuntime":{"types":"./dist/NodeDurableAgentRuntime.d.mts","default":"./dist/NodeDurableAgentRuntime.mjs"},"./NodeDurableHost":{"types":"./dist/NodeDurableHost.d.mts","default":"./dist/NodeDurableHost.mjs"},"./NodeScheduling":{"types":"./dist/NodeScheduling.d.mts","default":"./dist/NodeScheduling.mjs"},"./NodeSubscriptions":{"types":"./dist/NodeSubscriptions.d.mts","default":"./dist/NodeSubscriptions.mjs"},"./NodeWakeScheduler":{"types":"./dist/NodeWakeScheduler.d.mts","default":"./dist/NodeWakeScheduler.mjs"},"./NodeWorkflow":{"types":"./dist/NodeWorkflow.d.mts","default":"./dist/NodeWorkflow.mjs"}},"description":"Class DN layer assembly for Effect Agent: the durable Node/SQLite runtime host, wake scheduler, and ownership drain.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/danieljvdm/effect-agent.git","directory":"packages/platform-node"},"files":["dist","src"],"type":"module","sideEffects":[],"publishConfig":{"access":"public"},"scripts":{"build":"vp pack","check":"tsc --noEmit -p tsconfig.json","test":"vp test --passWithNoTests"}}
|
package/src/NodeWakeScheduler.ts
CHANGED
|
@@ -59,11 +59,13 @@ const makeWakeScheduler = Effect.gen(function* () {
|
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Deployment §3: correctness must not depend on in-memory notifications, so every `wakes` run
|
|
62
|
-
* merges its PubSub subscription with
|
|
63
|
-
* the
|
|
62
|
+
* merges its PubSub subscription with shared Clock-driven ledger scans. Share whole snapshots:
|
|
63
|
+
* sliding individual lanes would strand the beginning of scans larger than the hint buffer.
|
|
64
|
+
* The scan starts with the first subscriber and stops when the last subscriber leaves.
|
|
64
65
|
*/
|
|
65
|
-
const fallbackScans
|
|
66
|
-
Effect.sleep(config.scanInterval).pipe(Effect.andThen(scanOnce)),
|
|
66
|
+
const fallbackScans = yield* Stream.share(
|
|
67
|
+
Stream.fromEffectRepeat(Effect.sleep(config.scanInterval).pipe(Effect.andThen(scanOnce))),
|
|
68
|
+
{ capacity: 1, strategy: "sliding" },
|
|
67
69
|
);
|
|
68
70
|
|
|
69
71
|
return WakeScheduler.of({
|
|
@@ -72,13 +74,16 @@ const makeWakeScheduler = Effect.gen(function* () {
|
|
|
72
74
|
.notify(threadId)
|
|
73
75
|
.pipe(Effect.andThen(PubSub.publish(hints, threadId)), Effect.asVoid),
|
|
74
76
|
subscribe: progress.subscribe,
|
|
75
|
-
wakes: Stream.merge(
|
|
77
|
+
wakes: Stream.merge(
|
|
78
|
+
Stream.fromPubSub(hints),
|
|
79
|
+
fallbackScans.pipe(Stream.flatMap(Stream.fromIterable)),
|
|
80
|
+
),
|
|
76
81
|
});
|
|
77
82
|
});
|
|
78
83
|
|
|
79
84
|
/**
|
|
80
85
|
* In-process Node `WakeScheduler`: `notify` publishes to a bounded sliding PubSub for prompt
|
|
81
|
-
* same-process wakeups, and
|
|
86
|
+
* same-process wakeups, and active `wakes` subscriptions share one periodic
|
|
82
87
|
* `SubmissionLedger.scanNonterminal` fallback so a dropped, coalesced, or never-sent notification
|
|
83
88
|
* can never strand accepted work (persistence §14). Delivery may duplicate; consumers already
|
|
84
89
|
* treat wakes as pure liveness hints.
|