@moltzap/client 2026.518.0 → 2026.519.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/channel-base/format-cross-conv.d.ts +43 -0
- package/dist/channel-base/format-cross-conv.d.ts.map +1 -0
- package/dist/channel-base/format-cross-conv.js +69 -0
- package/dist/channel-base/format-cross-conv.js.map +1 -0
- package/dist/channel-base/format-group-block.d.ts +43 -0
- package/dist/channel-base/format-group-block.d.ts.map +1 -0
- package/dist/channel-base/format-group-block.js +59 -0
- package/dist/channel-base/format-group-block.js.map +1 -0
- package/dist/channel-base/index.d.ts +21 -0
- package/dist/channel-base/index.d.ts.map +1 -0
- package/dist/channel-base/index.js +24 -0
- package/dist/channel-base/index.js.map +1 -0
- package/dist/channel-base/lease-guard.d.ts +30 -0
- package/dist/channel-base/lease-guard.d.ts.map +1 -0
- package/dist/channel-base/lease-guard.js +40 -0
- package/dist/channel-base/lease-guard.js.map +1 -0
- package/dist/channel-base/lease-store.d.ts +30 -0
- package/dist/channel-base/lease-store.d.ts.map +1 -0
- package/dist/channel-base/lease-store.js +58 -0
- package/dist/channel-base/lease-store.js.map +1 -0
- package/dist/channel-base/lease.d.ts +94 -0
- package/dist/channel-base/lease.d.ts.map +1 -0
- package/dist/channel-base/lease.js +110 -0
- package/dist/channel-base/lease.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/notification/__tests__/filter-equivalence.test.d.ts +2 -0
- package/dist/notification/__tests__/filter-equivalence.test.d.ts.map +1 -0
- package/dist/notification/__tests__/filter-equivalence.test.js +123 -0
- package/dist/notification/__tests__/filter-equivalence.test.js.map +1 -0
- package/dist/notification/__tests__/snapshot-semantics.test.d.ts +2 -0
- package/dist/notification/__tests__/snapshot-semantics.test.d.ts.map +1 -0
- package/dist/notification/__tests__/snapshot-semantics.test.js +261 -0
- package/dist/notification/__tests__/snapshot-semantics.test.js.map +1 -0
- package/dist/notification/__tests__/snapshot-semantics.types-check.d.ts +3 -0
- package/dist/notification/__tests__/snapshot-semantics.types-check.d.ts.map +1 -0
- package/dist/notification/__tests__/snapshot-semantics.types-check.js +62 -0
- package/dist/notification/__tests__/snapshot-semantics.types-check.js.map +1 -0
- package/dist/notification/errors.d.ts +27 -0
- package/dist/notification/errors.d.ts.map +1 -0
- package/dist/notification/errors.js +24 -0
- package/dist/notification/errors.js.map +1 -0
- package/dist/notification/stream.d.ts +84 -0
- package/dist/notification/stream.d.ts.map +1 -0
- package/dist/notification/stream.js +106 -0
- package/dist/notification/stream.js.map +1 -0
- package/dist/runtime/index.d.ts +3 -4
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +3 -3
- package/dist/runtime/service-teardown.d.ts +5 -0
- package/dist/runtime/service-teardown.d.ts.map +1 -0
- package/dist/runtime/service-teardown.js +36 -0
- package/dist/runtime/service-teardown.js.map +1 -0
- package/dist/runtime/service-teardown.test.d.ts +2 -0
- package/dist/runtime/service-teardown.test.d.ts.map +1 -0
- package/dist/runtime/service-teardown.test.js +80 -0
- package/dist/runtime/service-teardown.test.js.map +1 -0
- package/dist/runtime/subscribers.d.ts +74 -136
- package/dist/runtime/subscribers.d.ts.map +1 -1
- package/dist/runtime/subscribers.js +187 -93
- package/dist/runtime/subscribers.js.map +1 -1
- package/dist/service.d.ts +10 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +45 -12
- package/dist/service.js.map +1 -1
- package/dist/test-utils/conformance-adapter.d.ts +6 -16
- package/dist/test-utils/conformance-adapter.d.ts.map +1 -1
- package/dist/test-utils/conformance-adapter.js +100 -59
- package/dist/test-utils/conformance-adapter.js.map +1 -1
- package/dist/ws-client-test-support.d.ts +1 -1
- package/dist/ws-client-test-support.d.ts.map +1 -1
- package/dist/ws-client-test-support.js +24 -3
- package/dist/ws-client-test-support.js.map +1 -1
- package/dist/ws-client.d.ts +52 -54
- package/dist/ws-client.d.ts.map +1 -1
- package/dist/ws-client.js +40 -168
- package/dist/ws-client.js.map +1 -1
- package/package.json +7 -3
- package/dist/runtime/subscribers.test.d.ts +0 -2
- package/dist/runtime/subscribers.test.d.ts.map +0 -1
- package/dist/runtime/subscribers.test.js +0 -193
- package/dist/runtime/subscribers.test.js.map +0 -1
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Channel-base lease primitives.
|
|
3
|
+
*
|
|
4
|
+
* Public surface for spec C (#597):
|
|
5
|
+
* - `LeaseAlreadyConsumed`: canonical tagged error class. One definition site
|
|
6
|
+
* across all three channels (claude-code, openclaw, nanoclaw).
|
|
7
|
+
* - `projectLeaseInvalid`: predicate that narrows a `RpcServerError` to
|
|
8
|
+
* `LeaseAlreadyConsumed` when the server's wire-error payload matches the
|
|
9
|
+
* single-use-lease shape.
|
|
10
|
+
* - `catchLeaseInvalid`: Effect-pipe convenience that runs the projection
|
|
11
|
+
* inside `Effect.catchTag("RpcServerError", ...)` with
|
|
12
|
+
* `Clock.currentTimeMillis` threaded into the projector as `consumedAt`.
|
|
13
|
+
*/
|
|
14
|
+
import { Clock, Data, Effect } from "effect";
|
|
15
|
+
import { RpcServerError } from "@moltzap/protocol";
|
|
16
|
+
/**
|
|
17
|
+
* The dispatch lease was already consumed (server returned the typed
|
|
18
|
+
* single-use-lease failure on a second `messages/send` for the same lease).
|
|
19
|
+
*
|
|
20
|
+
* Construction is **only** via `projectLeaseInvalid` (or `catchLeaseInvalid`).
|
|
21
|
+
* The original `RpcServerError` is preserved on `cause` so hosts can inspect
|
|
22
|
+
* the wire payload without re-fetching.
|
|
23
|
+
*
|
|
24
|
+
* See arch sub-issue #605 §3.1 for the shape rationale (cause field is the
|
|
25
|
+
* verbatim wire error; consumedAt is `Clock.currentTimeMillis` at projection
|
|
26
|
+
* time; message is derived from cause.message).
|
|
27
|
+
*/
|
|
28
|
+
export class LeaseAlreadyConsumed extends Data.TaggedError("LeaseAlreadyConsumed") {
|
|
29
|
+
}
|
|
30
|
+
const LEASE_ID_FALLBACK = "(unknown)";
|
|
31
|
+
function isLeaseInvalidData(data) {
|
|
32
|
+
if (typeof data !== "object" || data === null)
|
|
33
|
+
return false;
|
|
34
|
+
const reason = data.reason;
|
|
35
|
+
const tag = data._tag;
|
|
36
|
+
// Today's wire shape: `ForbiddenError.data.reason === "LeaseInvalid"`
|
|
37
|
+
// (arch sub-issue #605 §3.2). The `_tag` arm is forward-compat for a
|
|
38
|
+
// future server that emits the canonical tag in `data` directly.
|
|
39
|
+
return reason === "LeaseInvalid" || tag === "LeaseAlreadyConsumed";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Project an `RpcServerError` to `LeaseAlreadyConsumed` if it matches the
|
|
43
|
+
* lease-invalid wire shape; otherwise return the original error unchanged.
|
|
44
|
+
*
|
|
45
|
+
* Predicate (architect-corrected per arch sub-issue #605 §3.2):
|
|
46
|
+
* `err.data.reason === "LeaseInvalid"` OR
|
|
47
|
+
* `err.data._tag === "LeaseAlreadyConsumed"` (forward-compat for a future
|
|
48
|
+
* server that emits the canonical tag in data).
|
|
49
|
+
*
|
|
50
|
+
* The wire code (-32001 / generic Forbidden) is intentionally NOT part of
|
|
51
|
+
* the predicate because the code is too generic to discriminate on alone.
|
|
52
|
+
*
|
|
53
|
+
* `ctx.leaseId` (optional) is the lease the caller just sent. Caller-supplied
|
|
54
|
+
* because the server's `ForbiddenError.data` shape does NOT carry leaseId.
|
|
55
|
+
* Falls back to `"(unknown)"` when omitted (matches the pre-refactor
|
|
56
|
+
* claude-code behavior).
|
|
57
|
+
*
|
|
58
|
+
* `ctx.consumedAt` (required) is the epoch ms to stamp on the resulting
|
|
59
|
+
* `LeaseAlreadyConsumed.consumedAt`. Required because `LeaseAlreadyConsumed`
|
|
60
|
+
* requires it and this function is synchronous (no Clock access). Callers
|
|
61
|
+
* either pass `Date.now()` directly or use `catchLeaseInvalid` which reads
|
|
62
|
+
* `Clock.currentTimeMillis` inside the Effect.
|
|
63
|
+
*/
|
|
64
|
+
export function projectLeaseInvalid(err, ctx) {
|
|
65
|
+
if (!isLeaseInvalidData(err.data))
|
|
66
|
+
return err;
|
|
67
|
+
return new LeaseAlreadyConsumed({
|
|
68
|
+
leaseId: ctx.leaseId ?? LEASE_ID_FALLBACK,
|
|
69
|
+
consumedAt: ctx.consumedAt,
|
|
70
|
+
cause: err,
|
|
71
|
+
message: err.message,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Effect-pipe convenience: catches `RpcServerError` and runs
|
|
76
|
+
* `projectLeaseInvalid` on each instance. Reads `Clock.currentTimeMillis`
|
|
77
|
+
* inside the catch and passes the result to `projectLeaseInvalid` as
|
|
78
|
+
* `consumedAt`. Matching errors are surfaced as the typed
|
|
79
|
+
* `LeaseAlreadyConsumed` on the failure channel; non-matching errors are
|
|
80
|
+
* re-raised unchanged so downstream `mapError`s see the original
|
|
81
|
+
* `RpcServerError`.
|
|
82
|
+
*
|
|
83
|
+
* Use at every channel's outbound `core.sendReply(...)` boundary:
|
|
84
|
+
*
|
|
85
|
+
* ```ts
|
|
86
|
+
* core.sendReply(conv, text, { dispatchLeaseId: leaseId }).pipe(
|
|
87
|
+
* catchLeaseInvalid({ leaseId }),
|
|
88
|
+
* // ... per-channel surfacing
|
|
89
|
+
* )
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export function catchLeaseInvalid(ctx) {
|
|
93
|
+
// `Effect.catchAll` over the union (rather than `catchTag("RpcServerError",
|
|
94
|
+
// ...)`) keeps the typechecker happy when `E2` is unconstrained — without
|
|
95
|
+
// narrowing on the runtime instance, TS conservatively infers that `E2`
|
|
96
|
+
// could itself carry `_tag: "RpcServerError"`. The `instanceof` branch
|
|
97
|
+
// partitions cleanly.
|
|
98
|
+
return (eff) => Effect.catchAll(eff, (err) => {
|
|
99
|
+
if (err instanceof RpcServerError) {
|
|
100
|
+
return Effect.flatMap(Clock.currentTimeMillis, (consumedAt) => Effect.fail(projectLeaseInvalid(err, {
|
|
101
|
+
...(ctx?.leaseId !== undefined ? { leaseId: ctx.leaseId } : {}),
|
|
102
|
+
consumedAt,
|
|
103
|
+
})));
|
|
104
|
+
}
|
|
105
|
+
// Non-RpcServerError residual (E2). Re-raise unchanged so downstream
|
|
106
|
+
// `mapError`s see it without coupling to channel-base.
|
|
107
|
+
return Effect.fail(err);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=lease.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lease.js","sourceRoot":"","sources":["../../src/channel-base/lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,oBAAqB,SAAQ,IAAI,CAAC,WAAW,CACxD,sBAAsB,CAMtB;CAAG;AAaL,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAEtC,SAAS,kBAAkB,CAAC,IAAa;IACvC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC5D,MAAM,MAAM,GAAI,IAAsC,CAAC,MAAM,CAAC;IAC9D,MAAM,GAAG,GAAI,IAAoC,CAAC,IAAI,CAAC;IACvD,sEAAsE;IACtE,qEAAqE;IACrE,iEAAiE;IACjE,OAAO,MAAM,KAAK,cAAc,IAAI,GAAG,KAAK,sBAAsB,CAAC;AACrE,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAmB,EACnB,GAA+D;IAE/D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAC9C,OAAO,IAAI,oBAAoB,CAAC;QAC9B,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,iBAAiB;QACzC,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,KAAK,EAAE,GAAG;QACV,OAAO,EAAE,GAAG,CAAC,OAAO;KACrB,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,iBAAiB,CAAW,GAE3C;IAGC,4EAA4E;IAC5E,0EAA0E;IAC1E,wEAAwE;IACxE,uEAAuE;IACvE,sBAAsB;IACtB,OAAO,CAAC,GAAG,EAAE,EAAE,CACb,MAAM,CAAC,QAAQ,CACb,GAAG,EACH,CAAC,GAAG,EAAwD,EAAE;QAC5D,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YAClC,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,UAAU,EAAE,EAAE,CAC5D,MAAM,CAAC,IAAI,CACT,mBAAmB,CAAC,GAAG,EAAE;gBACvB,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/D,UAAU;aACX,CAAC,CACH,CACF,CAAC;QACJ,CAAC;QACD,qEAAqE;QACrE,uDAAuD;QACvD,OAAO,MAAM,CAAC,IAAI,CAAC,GAAS,CAAC,CAAC;IAChC,CAAC,CACF,CAAC;AACN,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { MoltZapService, formatCrossConversationBlock, sanitizeForSystemReminder
|
|
|
5
5
|
export { AgentNotFoundError, MalformedFrameError } from "./runtime/errors.js";
|
|
6
6
|
export { MoltZapChannelCore, type ChannelCoreOptions, type ChannelService, type ContextBlocks, type DispatchAdmissionDecision, type DispatchAdmissionRequest, type DispatchReleaseFrame, type EnrichedConversationMeta, type EnrichedInboundMessage, type EnrichedSender, type InboundHandler, type PendingDispatchMessage, } from "./channel-core.js";
|
|
7
7
|
export { MoltZapWsClient, type MoltZapWsClientOptions, type ServerRpcContext, type ServerRpcHandler, type RpcCallOptions, } from "./ws-client.js";
|
|
8
|
-
export type { SubscriptionFilter, SubscriptionId, NotificationSubscription, SubscriberHandler, } from "./runtime/subscribers.js";
|
|
9
8
|
export type { CloseInfo } from "./runtime/close-info.js";
|
|
9
|
+
export { TimeoutError as NotificationTimeoutError, StreamClosedError as NotificationStreamClosedError, type NotificationConsumerError, } from "./notification/errors.js";
|
|
10
10
|
export { registerAgent, type RegisterAgentOptions, type RegisterResponse, } from "./auth.js";
|
|
11
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAIzD,OAAO,EACL,YAAY,IAAI,wBAAwB,EACxC,iBAAiB,IAAI,6BAA6B,EAClD,KAAK,yBAAyB,GAC/B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,GACtB,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,5 +5,9 @@ export { MoltZapService, formatCrossConversationBlock, sanitizeForSystemReminder
|
|
|
5
5
|
export { AgentNotFoundError, MalformedFrameError } from "./runtime/errors.js";
|
|
6
6
|
export { MoltZapChannelCore, } from "./channel-core.js";
|
|
7
7
|
export { MoltZapWsClient, } from "./ws-client.js";
|
|
8
|
+
// Spec B (#596) — tagged errors for the typed-Stream subscribe surface.
|
|
9
|
+
// `NotificationConsumerError` is a type union (see notification/errors.ts
|
|
10
|
+
// header for rationale, codex review r1 finding #8).
|
|
11
|
+
export { TimeoutError as NotificationTimeoutError, StreamClosedError as NotificationStreamClosedError, } from "./notification/errors.js";
|
|
8
12
|
export { registerAgent, } from "./auth.js";
|
|
9
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,yBAAyB,GAO1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,kBAAkB,GAYnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,GAKhB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,cAAc,EACd,4BAA4B,EAC5B,yBAAyB,GAO1B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,kBAAkB,GAYnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,GAKhB,MAAM,gBAAgB,CAAC;AAExB,wEAAwE;AACxE,0EAA0E;AAC1E,qDAAqD;AACrD,OAAO,EACL,YAAY,IAAI,wBAAwB,EACxC,iBAAiB,IAAI,6BAA6B,GAEnD,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,GAGd,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-equivalence.test.d.ts","sourceRoot":"","sources":["../../../src/notification/__tests__/filter-equivalence.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/* eslint-disable max-nested-callbacks, max-lines-per-function, sonarjs/max-lines-per-function, agent-code-guard/as-unknown-as, agent-code-guard/async-keyword, jsdoc/text-escaping -- fast-check + Effect.gen + Stream.runForEach nest by construction; the cross-shape brand erasure in `oracle`/`fakeOtherFrame` is the typed→erased boundary the property test deliberately probes; fc.asyncProperty requires an async function */
|
|
2
|
+
/**
|
|
3
|
+
* Filter-equivalence oracle (spec #596 §Acceptance criteria).
|
|
4
|
+
*
|
|
5
|
+
* For any property-generated sequence of inbound notifications (length up
|
|
6
|
+
* to 32, value pool size up to 8) and any property-generated typed
|
|
7
|
+
* predicate `p`, the Stream-based subscribe API output equals the pure-JS
|
|
8
|
+
* reference `frames.filter(frame => def===frame.definition && p(frame.params))`.
|
|
9
|
+
*
|
|
10
|
+
* The oracle is a pure-JS reference implementation embedded in this file
|
|
11
|
+
* (NOT a reference to the deleted three-storage shape).
|
|
12
|
+
*
|
|
13
|
+
* Bounded generators per spec: max array length 32, value pool size 8.
|
|
14
|
+
*
|
|
15
|
+
* The type-guard overload narrows the Stream's payload to
|
|
16
|
+
* `DecodedNotification<D, R>`; the second property-test below pins the
|
|
17
|
+
* runtime narrowing matches the compile-time canary in
|
|
18
|
+
* `snapshot-semantics.types-check.ts → Canary #1`.
|
|
19
|
+
*/
|
|
20
|
+
import { describe, expect, it } from "vitest";
|
|
21
|
+
import * as fc from "fast-check";
|
|
22
|
+
import { Effect, Fiber, Ref, Stream } from "effect";
|
|
23
|
+
import { PresenceChangedNotificationDefinition, } from "@moltzap/protocol";
|
|
24
|
+
import { makeSubscriberRegistry } from "../../runtime/subscribers.js";
|
|
25
|
+
import { subscribe } from "../stream.js";
|
|
26
|
+
const MAX_SEQUENCE_LENGTH = 32;
|
|
27
|
+
const VALUE_POOL_SIZE = 8;
|
|
28
|
+
const PROPERTY_RUN_COUNT = 25;
|
|
29
|
+
const arbAgentId = fc
|
|
30
|
+
.integer({ min: 0, max: VALUE_POOL_SIZE - 1 })
|
|
31
|
+
.map((n) => `agent-${n}`);
|
|
32
|
+
const arbStatus = fc.constantFrom("online", "offline");
|
|
33
|
+
const arbGeneratedFrame = fc.record({
|
|
34
|
+
definitionTag: fc.constantFrom("presence", "other"),
|
|
35
|
+
agentId: arbAgentId,
|
|
36
|
+
status: arbStatus,
|
|
37
|
+
});
|
|
38
|
+
const arbSequence = fc.array(arbGeneratedFrame, {
|
|
39
|
+
minLength: 0,
|
|
40
|
+
maxLength: MAX_SEQUENCE_LENGTH,
|
|
41
|
+
});
|
|
42
|
+
/** Pure-JS reference oracle. Filters by definition identity + predicate. */
|
|
43
|
+
function oracle(frames, predicate) {
|
|
44
|
+
const presenceOnly = frames.filter((f) => f.definitionTag === "presence");
|
|
45
|
+
const presenceParams = presenceOnly.map((f) => ({ agentId: f.agentId, status: f.status }));
|
|
46
|
+
return presenceParams.filter(predicate);
|
|
47
|
+
}
|
|
48
|
+
function decodedPresence(generated) {
|
|
49
|
+
return {
|
|
50
|
+
_tag: "Notification",
|
|
51
|
+
jsonrpc: "2.0",
|
|
52
|
+
definition: PresenceChangedNotificationDefinition,
|
|
53
|
+
method: PresenceChangedNotificationDefinition.name,
|
|
54
|
+
params: {
|
|
55
|
+
agentId: generated.agentId,
|
|
56
|
+
status: generated.status,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function fakeOtherFrame(generated) {
|
|
61
|
+
// A frame whose `.definition` reference does NOT match
|
|
62
|
+
// `PresenceChangedNotificationDefinition` — used to verify the registry's
|
|
63
|
+
// definition-identity filter drops it before the predicate runs.
|
|
64
|
+
const raw = {
|
|
65
|
+
_tag: "Notification",
|
|
66
|
+
jsonrpc: "2.0",
|
|
67
|
+
definition: { name: "other/method" },
|
|
68
|
+
method: "other/method",
|
|
69
|
+
params: { agentId: generated.agentId, status: generated.status },
|
|
70
|
+
};
|
|
71
|
+
return raw; // #ignore-sloppy-code[as-unknown-as]: fake-frame for the non-matching arm; the test is precisely about the boundary's behaviour on misshapen frames
|
|
72
|
+
}
|
|
73
|
+
describe("Spec B filter-equivalence oracle", () => {
|
|
74
|
+
it("Stream output equals pure-JS filter oracle for arbitrary inputs", () => fc.assert(fc.asyncProperty(arbSequence, async (frames) => {
|
|
75
|
+
// Property-generated predicate: deterministic, total, varies by
|
|
76
|
+
// status. Closing over an outer counter would invalidate the
|
|
77
|
+
// oracle equivalence.
|
|
78
|
+
const predicate = (params) => params.status === "online";
|
|
79
|
+
const collected = await Effect.runPromise(Effect.gen(function* () {
|
|
80
|
+
const registry = yield* makeSubscriberRegistry();
|
|
81
|
+
const seen = yield* Ref.make([]);
|
|
82
|
+
const fiber = yield* Effect.fork(subscribe(registry, PresenceChangedNotificationDefinition, predicate).pipe(Stream.runForEach((frame) => Ref.update(seen, (xs) => [...xs, frame.params])), Effect.catchAll(() => Effect.void)));
|
|
83
|
+
// Yield once to materialise the Stream's subscription via
|
|
84
|
+
// Stream.async's register callback.
|
|
85
|
+
yield* Effect.yieldNow();
|
|
86
|
+
for (const f of frames) {
|
|
87
|
+
const decoded = f.definitionTag === "presence"
|
|
88
|
+
? decodedPresence(f)
|
|
89
|
+
: fakeOtherFrame(f);
|
|
90
|
+
yield* registry.dispatch(decoded);
|
|
91
|
+
}
|
|
92
|
+
yield* Effect.yieldNow();
|
|
93
|
+
yield* registry.closeAll;
|
|
94
|
+
yield* Fiber.join(fiber);
|
|
95
|
+
return yield* Ref.get(seen);
|
|
96
|
+
}));
|
|
97
|
+
const expected = oracle(frames, predicate);
|
|
98
|
+
expect(collected).toEqual(expected);
|
|
99
|
+
}), { numRuns: PROPERTY_RUN_COUNT }));
|
|
100
|
+
it("user-defined type guard narrows the Stream payload", () => Effect.runPromise(Effect.gen(function* () {
|
|
101
|
+
const registry = yield* makeSubscriberRegistry();
|
|
102
|
+
const seen = yield* Ref.make([]);
|
|
103
|
+
const isOnline = (params) => params.status === "online";
|
|
104
|
+
const fiber = yield* Effect.fork(subscribe(registry, PresenceChangedNotificationDefinition, isOnline).pipe(Stream.runForEach((frame) => Ref.update(seen, (xs) => [...xs, frame.params])), Effect.catchAll(() => Effect.void)));
|
|
105
|
+
yield* Effect.yieldNow();
|
|
106
|
+
yield* registry.dispatch(decodedPresence({
|
|
107
|
+
definitionTag: "presence",
|
|
108
|
+
agentId: "agent-0",
|
|
109
|
+
status: "online",
|
|
110
|
+
}));
|
|
111
|
+
yield* registry.dispatch(decodedPresence({
|
|
112
|
+
definitionTag: "presence",
|
|
113
|
+
agentId: "agent-1",
|
|
114
|
+
status: "offline",
|
|
115
|
+
}));
|
|
116
|
+
yield* Effect.yieldNow();
|
|
117
|
+
yield* registry.closeAll;
|
|
118
|
+
yield* Fiber.join(fiber);
|
|
119
|
+
const observed = yield* Ref.get(seen);
|
|
120
|
+
expect(observed).toEqual([{ agentId: "agent-0", status: "online" }]);
|
|
121
|
+
})));
|
|
122
|
+
});
|
|
123
|
+
//# sourceMappingURL=filter-equivalence.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-equivalence.test.js","sourceRoot":"","sources":["../../../src/notification/__tests__/filter-equivalence.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-semantics.test.d.ts","sourceRoot":"","sources":["../../../src/notification/__tests__/snapshot-semantics.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/* eslint-disable max-nested-callbacks, max-lines-per-function, sonarjs/max-lines-per-function, agent-code-guard/no-example-only-tests -- vitest + Effect.gen + Stream.runForEach nest by construction; AD1 properties are scenario-shaped (snapshot semantics + lifecycle); generative coverage lives in filter-equivalence.test.ts */
|
|
2
|
+
/**
|
|
3
|
+
* Snapshot-semantics property test (validates AD1 via spec #222 §5.3 OQ-3
|
|
4
|
+
* acceptance criterion). Spec B (#596).
|
|
5
|
+
*
|
|
6
|
+
* Four architect-named properties (see `snapshot-semantics.types-check.ts`
|
|
7
|
+
* for the compile-time AD1 canaries):
|
|
8
|
+
*
|
|
9
|
+
* 1. "No notification with arrival time > T_cancel is delivered through s."
|
|
10
|
+
* — verified via two subscriptions (`s_observer` + `s_target`) racing
|
|
11
|
+
* against a series of dispatched frames. After `s_target` cancels at
|
|
12
|
+
* frame index K, only `s_observer` keeps receiving frames K+1…N.
|
|
13
|
+
* 2. "Unregister between frames doesn't affect prior dispatches." —
|
|
14
|
+
* verified by registering three subscribers, running `dispatch(frameN)`
|
|
15
|
+
* once; *after* the dispatch returns, interrupt `s2`, then
|
|
16
|
+
* `dispatch(frameN+1)` — assert s2 received frameN but not frameN+1.
|
|
17
|
+
* (Renamed in r1 cleanup per P2-3: this test does NOT exercise true
|
|
18
|
+
* mid-dispatch interleaving; the standalone "mid-dispatch" test below
|
|
19
|
+
* does.)
|
|
20
|
+
* 3. "In-flight dispatch of frame N is NOT interrupted by an unregister
|
|
21
|
+
* that commits during frame N." — verified by forking a dispatch whose
|
|
22
|
+
* first invoked subscriber suspends on a `Deferred`. While the
|
|
23
|
+
* dispatch fiber is parked mid-handler, interrupt a SIBLING
|
|
24
|
+
* subscriber's consumer fiber (which calls `handle.unregister`
|
|
25
|
+
* via the Stream finalizer); release the dispatch fiber and assert
|
|
26
|
+
* the interrupted sibling STILL received the frame — proving the
|
|
27
|
+
* dispatch is iterating a snapshot, not the live list.
|
|
28
|
+
* 4. "Closed client terminates all in-flight Streams with `NotConnectedError`."
|
|
29
|
+
* — verified by forking a `Stream.runForEach` consumer, calling
|
|
30
|
+
* `closeAll`, then asserting the fiber's exit is a typed
|
|
31
|
+
* `NotConnectedError` failure.
|
|
32
|
+
*
|
|
33
|
+
* The tests intentionally exercise `SubscriberRegistry` + the
|
|
34
|
+
* `notification/stream.ts` Stream factories together (the public API
|
|
35
|
+
* surface), not the registry alone — Canary #3's "internal Scope, no
|
|
36
|
+
* leakage" contract is what we are validating end-to-end.
|
|
37
|
+
*
|
|
38
|
+
* Per P3 #612 fix (architect revision): each `expect` here asserts a
|
|
39
|
+
* value computed by the system under test rather than the test's own
|
|
40
|
+
* input — no tautological "X === X" patterns.
|
|
41
|
+
*
|
|
42
|
+
* Determinism (r1 cleanup, P2-2): readiness between forked consumers and
|
|
43
|
+
* the dispatch path uses `Effect.yieldNow()` (deterministic single-tick
|
|
44
|
+
* scheduling) rather than `Effect.sleep(...)` (wall-clock dependent).
|
|
45
|
+
* Mid-dispatch suspension uses `Deferred` so the dispatch fiber is parked
|
|
46
|
+
* at a known point inside the handler, independent of any timer.
|
|
47
|
+
*/
|
|
48
|
+
import { describe, expect, it } from "vitest";
|
|
49
|
+
import { Cause, Deferred, Effect, Exit, Fiber, Option, Ref, Stream, } from "effect";
|
|
50
|
+
import { NotConnectedError, } from "@moltzap/protocol";
|
|
51
|
+
import { PresenceChangedNotificationDefinition, MessageReceivedNotificationDefinition, } from "@moltzap/protocol";
|
|
52
|
+
import { makeSubscriberRegistry } from "../../runtime/subscribers.js";
|
|
53
|
+
import { subscribe, subscribeAll } from "../stream.js";
|
|
54
|
+
const PROP_TEST_FRAME_COUNT = 6;
|
|
55
|
+
const PROP_TEST_CANCEL_AT = 3;
|
|
56
|
+
function decodedPresence(seq) {
|
|
57
|
+
return {
|
|
58
|
+
_tag: "Notification",
|
|
59
|
+
jsonrpc: "2.0",
|
|
60
|
+
definition: PresenceChangedNotificationDefinition,
|
|
61
|
+
method: PresenceChangedNotificationDefinition.name,
|
|
62
|
+
params: {
|
|
63
|
+
agentId: `agent-${seq}`,
|
|
64
|
+
status: seq % 2 === 0 ? "online" : "offline",
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function decodedMessageReceived() {
|
|
69
|
+
return {
|
|
70
|
+
_tag: "Notification",
|
|
71
|
+
jsonrpc: "2.0",
|
|
72
|
+
definition: MessageReceivedNotificationDefinition,
|
|
73
|
+
method: MessageReceivedNotificationDefinition.name,
|
|
74
|
+
params: {
|
|
75
|
+
message: {
|
|
76
|
+
id: "m1",
|
|
77
|
+
conversationId: "c1",
|
|
78
|
+
senderId: "agent-0",
|
|
79
|
+
parts: [{ type: "text", text: "hi" }],
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
describe("AD1 snapshot semantics — Stream cancellation", () => {
|
|
85
|
+
it("no notification with index > T_cancel is delivered through s_target", () => Effect.runPromise(Effect.gen(function* () {
|
|
86
|
+
const registry = yield* makeSubscriberRegistry();
|
|
87
|
+
const observerSeen = yield* Ref.make([]);
|
|
88
|
+
const targetSeen = yield* Ref.make([]);
|
|
89
|
+
const observerFiber = yield* Effect.fork(subscribe(registry, PresenceChangedNotificationDefinition).pipe(Stream.runForEach((frame) => Ref.update(observerSeen, (xs) => [
|
|
90
|
+
...xs,
|
|
91
|
+
Number(frame.params.agentId.slice("agent-".length)),
|
|
92
|
+
])), Effect.catchAll(() => Effect.void)));
|
|
93
|
+
const targetStream = subscribe(registry, PresenceChangedNotificationDefinition);
|
|
94
|
+
const targetFiber = yield* Effect.fork(targetStream.pipe(Stream.take(PROP_TEST_CANCEL_AT), Stream.runForEach((frame) => Ref.update(targetSeen, (xs) => [
|
|
95
|
+
...xs,
|
|
96
|
+
Number(frame.params.agentId.slice("agent-".length)),
|
|
97
|
+
])), Effect.catchAll(() => Effect.void)));
|
|
98
|
+
// Yield once so each forked consumer's Stream.async register
|
|
99
|
+
// callback commits its subscription into `subsRef` before the
|
|
100
|
+
// dispatch loop reads the snapshot. `Effect.yieldNow()` is
|
|
101
|
+
// deterministic (single-tick scheduling) — replaces the prior
|
|
102
|
+
// `Effect.sleep("10 millis")` which was wall-clock dependent
|
|
103
|
+
// (P2-2 r1 cleanup).
|
|
104
|
+
yield* Effect.yieldNow();
|
|
105
|
+
for (let i = 0; i < PROP_TEST_FRAME_COUNT; i++) {
|
|
106
|
+
yield* registry.dispatch(decodedPresence(i));
|
|
107
|
+
}
|
|
108
|
+
yield* Effect.yieldNow();
|
|
109
|
+
yield* Fiber.join(targetFiber);
|
|
110
|
+
// Drain the registry by running closeAll so the observer fiber
|
|
111
|
+
// terminates with NotConnectedError and we can assert what it saw.
|
|
112
|
+
yield* registry.closeAll;
|
|
113
|
+
yield* Fiber.join(observerFiber);
|
|
114
|
+
const target = yield* Ref.get(targetSeen);
|
|
115
|
+
const observer = yield* Ref.get(observerSeen);
|
|
116
|
+
// Target only saw the first PROP_TEST_CANCEL_AT frames before
|
|
117
|
+
// Stream.take cancelled its subscription.
|
|
118
|
+
expect(target.length).toBe(PROP_TEST_CANCEL_AT);
|
|
119
|
+
for (const idx of target) {
|
|
120
|
+
expect(idx).toBeLessThan(PROP_TEST_CANCEL_AT);
|
|
121
|
+
}
|
|
122
|
+
// Observer (never cancelled) saw every frame.
|
|
123
|
+
expect(observer.length).toBe(PROP_TEST_FRAME_COUNT);
|
|
124
|
+
})));
|
|
125
|
+
it("unregister between frames doesn't affect prior dispatches", () => Effect.runPromise(Effect.gen(function* () {
|
|
126
|
+
// This test confirms a sequential property — dispatch frameN, then
|
|
127
|
+
// interrupt s2 BETWEEN dispatches, then dispatch frameN+1 — and
|
|
128
|
+
// observes that s2 received frameN (because it was registered) and
|
|
129
|
+
// did NOT receive frameN+1 (because the snapshot at the start of
|
|
130
|
+
// frameN+1's dispatch excludes the now-unregistered s2). Note that
|
|
131
|
+
// there is NO concurrent interleaving here: every step completes
|
|
132
|
+
// before the next begins. True mid-dispatch interleaving is
|
|
133
|
+
// exercised by the "in-flight dispatch is NOT interrupted by an
|
|
134
|
+
// unregister that commits during frame N" test below.
|
|
135
|
+
const registry = yield* makeSubscriberRegistry();
|
|
136
|
+
const receivedByS2 = yield* Ref.make([]);
|
|
137
|
+
const s1Fiber = yield* Effect.fork(subscribe(registry, PresenceChangedNotificationDefinition).pipe(Stream.runDrain, Effect.catchAll(() => Effect.void)));
|
|
138
|
+
const s3Fiber = yield* Effect.fork(subscribe(registry, PresenceChangedNotificationDefinition).pipe(Stream.runDrain, Effect.catchAll(() => Effect.void)));
|
|
139
|
+
const s2Stream = subscribe(registry, PresenceChangedNotificationDefinition);
|
|
140
|
+
const s2Fiber = yield* Effect.fork(s2Stream.pipe(Stream.runForEach((frame) => Ref.update(receivedByS2, (xs) => [
|
|
141
|
+
...xs,
|
|
142
|
+
Number(frame.params.agentId.slice("agent-".length)),
|
|
143
|
+
])), Effect.catchAll(() => Effect.void)));
|
|
144
|
+
// Single-tick yield so every forked consumer's Stream.async
|
|
145
|
+
// register callback commits before the first dispatch reads
|
|
146
|
+
// the snapshot. Deterministic — see file header (P2-2 r1).
|
|
147
|
+
yield* Effect.yieldNow();
|
|
148
|
+
yield* registry.dispatch(decodedPresence(0));
|
|
149
|
+
// Drain s2's onFrame Effect into receivedByS2 deterministically.
|
|
150
|
+
yield* Effect.yieldNow();
|
|
151
|
+
// Interrupt s2's consumer; Stream finalizer runs `unregister`
|
|
152
|
+
// synchronously. Subsequent dispatch's snapshot must exclude s2.
|
|
153
|
+
yield* Fiber.interrupt(s2Fiber);
|
|
154
|
+
yield* registry.dispatch(decodedPresence(1));
|
|
155
|
+
yield* Effect.yieldNow();
|
|
156
|
+
const seen = yield* Ref.get(receivedByS2);
|
|
157
|
+
expect(seen).toEqual([0]);
|
|
158
|
+
// Tidy up sibling fibers.
|
|
159
|
+
yield* registry.closeAll;
|
|
160
|
+
yield* Fiber.join(s1Fiber);
|
|
161
|
+
yield* Fiber.join(s3Fiber);
|
|
162
|
+
})));
|
|
163
|
+
it("in-flight dispatch is NOT interrupted by an unregister that commits during frame N", () => Effect.runPromise(Effect.gen(function* () {
|
|
164
|
+
// True mid-dispatch interleaving — distinguishes the snapshot
|
|
165
|
+
// semantic from a live-list-iteration semantic (which would skip
|
|
166
|
+
// the unregistered subscriber).
|
|
167
|
+
//
|
|
168
|
+
// Method: register two subscribers directly via the registry API
|
|
169
|
+
// so we control the dispatch fiber's progress mid-handler. s1's
|
|
170
|
+
// handler parks the dispatcher on a `Deferred` inside onFrame.
|
|
171
|
+
// While parked, we call `s2.unregister` synchronously — mutating
|
|
172
|
+
// `subsRef`. We then release s1; the dispatcher continues to s2
|
|
173
|
+
// (per its captured snapshot) and invokes `s2.onFrame`. If the
|
|
174
|
+
// dispatcher iterated the LIVE list, s2 would have been skipped
|
|
175
|
+
// and `s2Received` would still be empty.
|
|
176
|
+
//
|
|
177
|
+
// (Stream-API end-to-end coverage is exercised by tests #1 and
|
|
178
|
+
// the closeAll lifecycle test #4; here we need the registry's
|
|
179
|
+
// direct API to control dispatch ordering deterministically.)
|
|
180
|
+
const registry = yield* makeSubscriberRegistry();
|
|
181
|
+
const enteredS1 = yield* Deferred.make();
|
|
182
|
+
const releaseS1 = yield* Deferred.make();
|
|
183
|
+
const s2Received = yield* Ref.make([]);
|
|
184
|
+
yield* registry.register(PresenceChangedNotificationDefinition, undefined, {
|
|
185
|
+
onFrame: () => Effect.gen(function* () {
|
|
186
|
+
yield* Deferred.succeed(enteredS1, void 0);
|
|
187
|
+
yield* Deferred.await(releaseS1);
|
|
188
|
+
}),
|
|
189
|
+
onClose: () => Effect.void,
|
|
190
|
+
});
|
|
191
|
+
const s2Handle = yield* registry.register(PresenceChangedNotificationDefinition, undefined, {
|
|
192
|
+
onFrame: (frame) => Ref.update(s2Received, (xs) => [
|
|
193
|
+
...xs,
|
|
194
|
+
Number(frame.params.agentId.slice("agent-".length)),
|
|
195
|
+
]),
|
|
196
|
+
onClose: () => Effect.void,
|
|
197
|
+
});
|
|
198
|
+
// Fork dispatch. Snapshot at fork time has both s1 and s2.
|
|
199
|
+
const dispatchFiber = yield* Effect.fork(registry.dispatch(decodedPresence(0)));
|
|
200
|
+
// Wait until s1's handler enters (dispatch is parked mid-flight).
|
|
201
|
+
yield* Deferred.await(enteredS1);
|
|
202
|
+
// Unregister s2 NOW — concurrently with the parked dispatch.
|
|
203
|
+
// Mutates subsRef; in-flight snapshot is unaffected.
|
|
204
|
+
yield* s2Handle.unregister;
|
|
205
|
+
// Release s1; dispatch proceeds to s2 per its snapshot.
|
|
206
|
+
yield* Deferred.succeed(releaseS1, void 0);
|
|
207
|
+
yield* Fiber.join(dispatchFiber);
|
|
208
|
+
const observed = yield* Ref.get(s2Received);
|
|
209
|
+
// Snapshot semantic: s2 was in the snapshot, so its onFrame fires
|
|
210
|
+
// even though it was unregistered while dispatch was mid-flight.
|
|
211
|
+
expect(observed).toEqual([0]);
|
|
212
|
+
// Sanity: confirm s2's unregister DID commit to subsRef — a
|
|
213
|
+
// subsequent dispatch must NOT deliver to s2.
|
|
214
|
+
yield* registry.dispatch(decodedPresence(1));
|
|
215
|
+
expect(yield* Ref.get(s2Received)).toEqual([0]);
|
|
216
|
+
yield* registry.closeAll;
|
|
217
|
+
})));
|
|
218
|
+
it("closeAll terminates in-flight Streams with NotConnectedError", () => Effect.runPromise(Effect.gen(function* () {
|
|
219
|
+
const registry = yield* makeSubscriberRegistry();
|
|
220
|
+
const fiber = yield* Effect.fork(subscribe(registry, MessageReceivedNotificationDefinition).pipe(Stream.runDrain));
|
|
221
|
+
// Deterministic single-tick yield so the Stream materialises its
|
|
222
|
+
// subscription (Stream.async register callback runs synchronously
|
|
223
|
+
// inside Stream.runDrain's setup on the forked fiber's first turn)
|
|
224
|
+
// before we call closeAll. P2-2 r1 cleanup.
|
|
225
|
+
yield* Effect.yieldNow();
|
|
226
|
+
yield* registry.closeAll;
|
|
227
|
+
const exit = yield* Fiber.await(fiber);
|
|
228
|
+
const failure = Exit.causeOption(exit).pipe(Option.flatMap(Cause.failureOption));
|
|
229
|
+
// Verify the typed failure was NotConnectedError, not a defect.
|
|
230
|
+
const ok = Option.match(failure, {
|
|
231
|
+
onNone: () => false,
|
|
232
|
+
onSome: (e) => e instanceof NotConnectedError,
|
|
233
|
+
});
|
|
234
|
+
expect(ok).toBe(true);
|
|
235
|
+
})));
|
|
236
|
+
it("subscribeAll receives every notification regardless of definition", () => Effect.runPromise(Effect.gen(function* () {
|
|
237
|
+
const registry = yield* makeSubscriberRegistry();
|
|
238
|
+
const observed = yield* Ref.make([]);
|
|
239
|
+
const fiber = yield* Effect.fork(subscribeAll(registry).pipe(Stream.runForEach((frame) => Ref.update(observed, (xs) => [
|
|
240
|
+
...xs,
|
|
241
|
+
frame.definition.name,
|
|
242
|
+
])), Effect.catchAll(() => Effect.void)));
|
|
243
|
+
// Single-tick yield ensures the forked subscribeAll consumer's
|
|
244
|
+
// register callback commits before dispatch reads the snapshot
|
|
245
|
+
// (P2-2 r1).
|
|
246
|
+
yield* Effect.yieldNow();
|
|
247
|
+
yield* registry.dispatch(decodedPresence(0));
|
|
248
|
+
yield* registry.dispatch(decodedMessageReceived());
|
|
249
|
+
// Drain the consumer's onFrame Effect into `observed` before
|
|
250
|
+
// closing — deterministic single-tick.
|
|
251
|
+
yield* Effect.yieldNow();
|
|
252
|
+
yield* registry.closeAll;
|
|
253
|
+
yield* Fiber.join(fiber);
|
|
254
|
+
const names = yield* Ref.get(observed);
|
|
255
|
+
expect(names).toEqual([
|
|
256
|
+
PresenceChangedNotificationDefinition.name,
|
|
257
|
+
MessageReceivedNotificationDefinition.name,
|
|
258
|
+
]);
|
|
259
|
+
})));
|
|
260
|
+
});
|
|
261
|
+
//# sourceMappingURL=snapshot-semantics.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-semantics.test.js","sourceRoot":"","sources":["../../../src/notification/__tests__/snapshot-semantics.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-semantics.types-check.d.ts","sourceRoot":"","sources":["../../../src/notification/__tests__/snapshot-semantics.types-check.ts"],"names":[],"mappings":"AAkLA,QAAA,MAAM,yBAAyB,EAAE,OAAsB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,CAAC"}
|