@zlink-systems/stream-connector 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,8 +28,14 @@ export interface ZlinkStreamExpectNoneCall<TPayload = ZlinkStreamEncodedPayload>
28
28
  within(windowMs: number): ZlinkStreamExpectNoneCall<TPayload>;
29
29
  run(signal?: AbortSignal): Promise<void>;
30
30
  }
31
+ /**
32
+ * Spec stream-connector 32 §10.1: the predicates and the returned values are
33
+ * messages, not payloads. A payload-only predicate cannot read the packet name
34
+ * or the metadata, so `TPayload` is the type of the payload the message carries
35
+ * and never the value handed to `expect(...)`.
36
+ */
31
37
  export interface ZlinkStreamSequenceCall<TPayload = ZlinkStreamEncodedPayload> {
32
- expect(predicate: (payload: TPayload) => boolean): ZlinkStreamSequenceCall<TPayload>;
38
+ expect(predicate: (message: ZlinkStreamMessage<TPayload>) => boolean): ZlinkStreamSequenceCall<TPayload>;
33
39
  timeout(timeoutMs: number): ZlinkStreamSequenceCall<TPayload>;
34
- run(signal?: AbortSignal): Promise<readonly TPayload[]>;
40
+ run(signal?: AbortSignal): Promise<readonly ZlinkStreamMessage<TPayload>[]>;
35
41
  }
@@ -22,6 +22,21 @@ export interface ZlinkStreamConnector {
22
22
  * with {@link import('./ZlinkStreamEnums').ZlinkStreamErrorCode.ConfigurationError}.
23
23
  */
24
24
  setDiagnosticsLevel(level: ZlinkStreamDiagnosticsLevel): void;
25
+ /**
26
+ * Asynchronous counterpart of {@link setDiagnosticsLevel} (spec
27
+ * stream-connector 32 §13). Both surfaces change the same value, and this
28
+ * one never replaces the synchronous surface: the synchronous call does not
29
+ * wait for a completion, so a caller whose idiom is an awaited completion
30
+ * uses this one instead. Rejects unknown values the same way.
31
+ */
32
+ setDiagnosticsLevelAsync(level: ZlinkStreamDiagnosticsLevel): Promise<void>;
33
+ /**
34
+ * Number of packets received under `name` on the current connection (spec
35
+ * stream-connector 32 §10). Counts arrivals, so consuming a message through
36
+ * a handler or a wait surface never lowers it, and the dispatch mode does
37
+ * not change it. Restarts at 0 every time a connection is established.
38
+ */
39
+ receivedCount(name: string): number;
25
40
  onErrorReceived(handler: (error: ZlinkStreamError, signal?: AbortSignal) => Promise<void> | void): Disposable;
26
41
  onDisconnected(handler: (signal?: AbortSignal) => Promise<void> | void): Disposable;
27
42
  onConnectionStateChanged(handler: (change: ZlinkStreamConnectionStateChanged, signal?: AbortSignal) => Promise<void> | void): Disposable;
@@ -31,7 +46,13 @@ export interface ZlinkStreamConnector {
31
46
  send(payload: unknown, messageType?: Function): ZlinkStreamSendCall;
32
47
  request(payload: unknown, messageType?: Function): ZlinkStreamRequestCall;
33
48
  on<TPayload = ZlinkStreamEncodedPayload>(name: string, handler: (message: ZlinkStreamMessage<TPayload>, signal?: AbortSignal) => Promise<void> | void, messageType?: Function): Disposable;
34
- waitFor<TPayload = ZlinkStreamEncodedPayload>(name: string): ZlinkStreamWaitCall<TPayload>;
35
- expectNone<TPayload = ZlinkStreamEncodedPayload>(name: string): ZlinkStreamExpectNoneCall<TPayload>;
36
- waitForSequence<TPayload = ZlinkStreamEncodedPayload>(name: string): ZlinkStreamSequenceCall<TPayload>;
49
+ /**
50
+ * Wait surfaces (spec stream-connector 32 §10.1). Each takes the packet name
51
+ * the caller states explicitly, or the payload constructor the options'
52
+ * `nameResolver` turns into that name — TypeScript types are erased at
53
+ * runtime, so the type-driven path takes a constructor value.
54
+ */
55
+ waitFor<TPayload = ZlinkStreamEncodedPayload>(nameOrType: string | Function): ZlinkStreamWaitCall<TPayload>;
56
+ expectNone<TPayload = ZlinkStreamEncodedPayload>(nameOrType: string | Function): ZlinkStreamExpectNoneCall<TPayload>;
57
+ waitForSequence<TPayload = ZlinkStreamEncodedPayload>(nameOrType: string | Function): ZlinkStreamSequenceCall<TPayload>;
37
58
  }
@@ -16,7 +16,6 @@ export interface ZlinkStreamConnectorOptions {
16
16
  readonly compression?: ZlinkStreamCompression;
17
17
  readonly compressionCodec?: ZlinkStreamCompressionCodec;
18
18
  readonly nameResolver?: ZlinkStreamPacketNameResolver;
19
- readonly meterProvider?: ZlinkStreamMeterProvider;
20
19
  /**
21
20
  * Initial diagnostics level (spec 26 §4); defaults to
22
21
  * {@link ZlinkStreamDiagnosticsLevel.Errors}, which preserves the current
@@ -27,20 +26,6 @@ export interface ZlinkStreamConnectorOptions {
27
26
  */
28
27
  readonly diagnosticsLevel?: ZlinkStreamDiagnosticsLevel;
29
28
  }
30
- export interface ZlinkStreamMeterProvider {
31
- getMeter(name: string): {
32
- createCounter(name: string, options?: {
33
- readonly unit?: string;
34
- }): {
35
- add(value: number, attributes?: Readonly<Record<string, string | number | boolean>>): void;
36
- };
37
- createHistogram(name: string, options?: {
38
- readonly unit?: string;
39
- }): {
40
- record(value: number, attributes?: Readonly<Record<string, string | number | boolean>>): void;
41
- };
42
- };
43
- }
44
29
  export interface ZlinkStreamHeartbeatOptions {
45
30
  readonly enabled?: boolean;
46
31
  readonly intervalMs?: number;
@@ -51,7 +36,11 @@ export interface ZlinkStreamReconnectOptions {
51
36
  readonly initialDelayMs?: number;
52
37
  readonly maxDelayMs?: number;
53
38
  readonly backoffFactor?: number;
54
- readonly maxAttempts?: number;
39
+ /**
40
+ * `null` means unlimited (spec stream-connector 32 §6: the option has to be
41
+ * able to say "keep trying"); any other value must be a positive number.
42
+ */
43
+ readonly maxAttempts?: number | null;
55
44
  }
56
45
  export interface ZlinkStreamPacketNameResolver {
57
46
  resolve(payloadType: Function): string;
@@ -88,6 +77,5 @@ export interface RequiredZlinkStreamConnectorOptions {
88
77
  readonly nameResolver: ZlinkStreamPacketNameResolver;
89
78
  readonly transportFactory: ZlinkStreamTransportFactory;
90
79
  readonly codec?: ZlinkStreamPayloadCodec;
91
- readonly meterProvider?: ZlinkStreamMeterProvider;
92
80
  readonly diagnosticsLevel: ZlinkStreamDiagnosticsLevel;
93
81
  }
@@ -21,9 +21,9 @@ export declare class ZlinkStreamSequenceBuilder<TPayload> implements ZlinkStream
21
21
  private timeoutMs;
22
22
  private executed;
23
23
  constructor(connector: ZlinkStreamMessageWaiter, name: string);
24
- expect(predicate: (payload: TPayload) => boolean): this;
24
+ expect(predicate: (message: ZlinkStreamMessage<TPayload>) => boolean): this;
25
25
  timeout(timeoutMs: number): this;
26
- run(signal?: AbortSignal): Promise<readonly TPayload[]>;
26
+ run(signal?: AbortSignal): Promise<readonly ZlinkStreamMessage<TPayload>[]>;
27
27
  private ensureConfigurable;
28
28
  private markExecuted;
29
29
  }
@@ -16,6 +16,14 @@ export declare class DefaultZlinkStreamConnector implements ZlinkStreamConnector
16
16
  get closeReason(): import("..").ZlinkStreamCloseReason | undefined;
17
17
  get state(): ZlinkStreamConnectionState;
18
18
  get pendingDispatchCount(): number;
19
+ /**
20
+ * Spec stream-connector 32 §10: how many packets carrying `name` arrived on
21
+ * the current connection. Arrivals are what is counted, so a message a
22
+ * handler dispatched or a wait surface consumed still counts, and `Manual`
23
+ * and `Immediate` report the same number. Establishing a connection resets
24
+ * the count to 0, a reconnect included.
25
+ */
26
+ receivedCount(name: string): number;
19
27
  /**
20
28
  * Current diagnostics level (spec 26 §4.1, spec stream-connector 32 §13).
21
29
  * Reflects the level set by the most recent {@link setDiagnosticsLevel}
@@ -29,10 +37,16 @@ export declare class DefaultZlinkStreamConnector implements ZlinkStreamConnector
29
37
  * state update: it applies to processing points that read the level after
30
38
  * this call returns and is never applied retroactively to frames already
31
39
  * built. Rejects unknown values with {@link ZlinkStreamErrorCode.ConfigurationError}.
32
- * Do not call this synchronous bridge from a framework execution context such
33
- * as a handler or callback; use setDiagnosticsLevelAsync there.
40
+ * Spec stream-connector 32 §13: this surface changes the value without
41
+ * waiting for anything; it is not a blocking call over the asynchronous pair,
42
+ * which a receive callback would otherwise make wait for its own completion.
34
43
  */
35
44
  setDiagnosticsLevel(level: ZlinkStreamDiagnosticsLevel): void;
45
+ /**
46
+ * Asynchronous counterpart of {@link setDiagnosticsLevel} (spec
47
+ * stream-connector 32 §13). It changes the same value; awaiting it is how a
48
+ * caller observes the change, and it never replaces the synchronous surface.
49
+ */
36
50
  setDiagnosticsLevelAsync(level: ZlinkStreamDiagnosticsLevel): Promise<void>;
37
51
  onErrorReceived(handler: (error: ZlinkStreamError, signal?: AbortSignal) => Promise<void> | void): Disposable;
38
52
  onDisconnected(handler: (signal?: AbortSignal) => Promise<void> | void): Disposable;
@@ -43,9 +57,16 @@ export declare class DefaultZlinkStreamConnector implements ZlinkStreamConnector
43
57
  send(payload: unknown, messageType?: Function): ZlinkStreamSendCall;
44
58
  request(payload: unknown, messageType?: Function): ZlinkStreamRequestCall;
45
59
  on<TPayload = ZlinkStreamEncodedPayload>(name: string, handler: (message: ZlinkStreamMessage<TPayload>, signal?: AbortSignal) => Promise<void> | void, messageType?: Function): Disposable;
46
- waitFor<TPayload = ZlinkStreamEncodedPayload>(name: string): ZlinkStreamWaitCall<TPayload>;
47
- expectNone<TPayload = ZlinkStreamEncodedPayload>(name: string): ZlinkStreamExpectNoneCall<TPayload>;
48
- waitForSequence<TPayload = ZlinkStreamEncodedPayload>(name: string): ZlinkStreamSequenceCall<TPayload>;
60
+ waitFor<TPayload = ZlinkStreamEncodedPayload>(nameOrType: string | Function): ZlinkStreamWaitCall<TPayload>;
61
+ expectNone<TPayload = ZlinkStreamEncodedPayload>(nameOrType: string | Function): ZlinkStreamExpectNoneCall<TPayload>;
62
+ waitForSequence<TPayload = ZlinkStreamEncodedPayload>(nameOrType: string | Function): ZlinkStreamSequenceCall<TPayload>;
63
+ /**
64
+ * Spec stream-connector 32 §10.1: each wait surface offers both ways of
65
+ * naming a packet. A string is the name the caller states; a constructor
66
+ * goes through the options' `nameResolver`, which is the same resolver
67
+ * `send` and `request` use, so both paths land on one name for one type.
68
+ */
69
+ private observedName;
49
70
  waitForMessage<TPayload>(name: string, timeoutMs: number, predicate: (message: ZlinkStreamMessage<TPayload>) => boolean, signal?: AbortSignal): Promise<ZlinkStreamMessage<TPayload>>;
50
71
  private encodePayload;
51
72
  private decodePayload;
@@ -6,7 +6,6 @@ import type { ZlinkStreamFrameSender } from './ZlinkStreamFrameSender';
6
6
  import type { ZlinkStreamPendingRequests } from './ZlinkStreamPendingRequests';
7
7
  import type { ZlinkStreamReceiveDispatcher } from './ZlinkStreamReceiveDispatcher';
8
8
  import type { ZlinkStreamReceivedMessages } from './ZlinkStreamReceivedMessages';
9
- import type { ZlinkStreamRuntimeMetrics } from './ZlinkStreamRuntimeMetrics';
10
9
  export declare class ZlinkStreamConnectorLifecycle {
11
10
  private readonly options;
12
11
  private readonly pendingRequests;
@@ -14,7 +13,6 @@ export declare class ZlinkStreamConnectorLifecycle {
14
13
  private readonly receiveDispatcher;
15
14
  private readonly receivedMessages;
16
15
  private readonly events;
17
- private readonly metrics;
18
16
  private receiveLoopAbort;
19
17
  private receiveLoopSleeping;
20
18
  private receiveLoopWake;
@@ -23,6 +21,7 @@ export declare class ZlinkStreamConnectorLifecycle {
23
21
  private connectionGeneration;
24
22
  private currentState;
25
23
  private heartbeatTimer;
24
+ private heartbeatTickRunning;
26
25
  private lastInboundAt;
27
26
  private closeTask;
28
27
  private connectTask;
@@ -31,7 +30,7 @@ export declare class ZlinkStreamConnectorLifecycle {
31
30
  private disconnectedPublished;
32
31
  private closeReasonValue?;
33
32
  private lateConnectCleanupError;
34
- constructor(options: RequiredZlinkStreamConnectorOptions, pendingRequests: ZlinkStreamPendingRequests, frameSender: ZlinkStreamFrameSender, receiveDispatcher: ZlinkStreamReceiveDispatcher, receivedMessages: ZlinkStreamReceivedMessages, events: ZlinkStreamConnectorEvents, metrics: ZlinkStreamRuntimeMetrics);
33
+ constructor(options: RequiredZlinkStreamConnectorOptions, pendingRequests: ZlinkStreamPendingRequests, frameSender: ZlinkStreamFrameSender, receiveDispatcher: ZlinkStreamReceiveDispatcher, receivedMessages: ZlinkStreamReceivedMessages, events: ZlinkStreamConnectorEvents);
35
34
  get isConnected(): boolean;
36
35
  get state(): ZlinkStreamConnectionState;
37
36
  get closeReason(): ZlinkStreamCloseReason | undefined;
@@ -65,8 +64,46 @@ export declare class ZlinkStreamConnectorLifecycle {
65
64
  private runHeartbeatTick;
66
65
  private disconnectForTransportFailure;
67
66
  private isCurrentConnection;
68
- private disconnectOnce;
67
+ /** Transport teardown only — no application callback runs from here. */
68
+ private tearDownConnection;
69
+ /**
70
+ * Runs once the teardown promise has settled, so a handler reached from here
71
+ * may call `connect` without waiting for a task its own caller still holds.
72
+ * The reconnect is queued before the notification is awaited for the same
73
+ * reason: spec stream-connector 32 §6 has reconnect on by default, and a
74
+ * handler that is slow — or whose promise never settles at all — must not
75
+ * cost the connector the attempt. The state is already `Disconnected` and the
76
+ * state handlers are already invoked by the time the queued microtask runs,
77
+ * because `setState` records the state and hands the change to the handlers
78
+ * before it awaits any of them.
79
+ */
80
+ private announceDisconnect;
69
81
  private shouldReconnect;
82
+ private claimDisconnectedPublish;
70
83
  private publishDisconnectedOnce;
84
+ /**
85
+ * Spec stream-connector 32 §7: the connector runs the registered handler, it
86
+ * does not wait for it to finish. `close` returns once its own work is done —
87
+ * the drain, the transport close, the pending requests — having run the
88
+ * disconnect handler but without looking at whether that handler has ended.
89
+ *
90
+ * Starting the publish without awaiting it still runs every handler right
91
+ * here: an `async` function body runs synchronously up to its first `await`,
92
+ * and `publishDisconnected` reaches each handler before that point. So the
93
+ * handler has run by the time `close` returns, which is what the spec asks
94
+ * for, while a handler that calls `close` no longer waits for the very
95
+ * `closeTask` it is running inside. Java and C++ hand the handler to a queue
96
+ * and return the same way.
97
+ *
98
+ * `claimDisconnectedPublish` is taken by the same call and before any await,
99
+ * so deferring the completion never turns the one notification into two.
100
+ *
101
+ * Nothing awaits the promise, so a rejection would reach the process as an
102
+ * unhandled rejection and kill it. Handler failures are already contained
103
+ * where they were before this call stopped waiting — the `Promise.allSettled`
104
+ * in `publishDisconnected` — and this `catch` covers what is left rather than
105
+ * reporting the same failure a second time on the error surface.
106
+ */
107
+ private publishDisconnectedWithoutWaiting;
71
108
  private setState;
72
109
  }
@@ -1,3 +1,17 @@
1
- import { RequiredZlinkStreamConnectorOptions, ZlinkStreamConnectorOptions, ZlinkStreamDiagnosticsLevel } from '../Contracts';
1
+ import { RequiredZlinkStreamConnectorOptions, ZlinkStreamConnectorOptions, ZlinkStreamDiagnosticsLevel, ZlinkStreamPacketNameResolver } from '../Contracts';
2
2
  export declare function normalizeOptions(options: ZlinkStreamConnectorOptions, defaultTransportFactory: RequiredZlinkStreamConnectorOptions['transportFactory']): RequiredZlinkStreamConnectorOptions;
3
+ /**
4
+ * Spec stream-connector 32 §5 and the TypeScript projection §4: a payload type
5
+ * carries its packet name in a static `packetName` member, and that name wins
6
+ * over the type's own name.
7
+ *
8
+ * The `name` fallback is a convenience for a type that declares nothing, and it
9
+ * is NOT trustworthy in a browser build: a minifier renames the constructor, so
10
+ * the same type produces a different packet name after a build setting changes
11
+ * and the server stops finding the handler — exactly the "name that changes
12
+ * with the build environment" §5 forbids. A payload type that crosses the wire
13
+ * declares `static readonly packetName`; leaving it out is only safe while the
14
+ * bundle keeps class names.
15
+ */
16
+ export declare const defaultPacketNameResolver: ZlinkStreamPacketNameResolver;
3
17
  export declare function validateDiagnosticsLevel(level: ZlinkStreamDiagnosticsLevel | undefined): void;
@@ -1,13 +1,11 @@
1
1
  import type { ZlinkStreamConnection, ZlinkStreamEncodedPayload, ZlinkStreamFlow, ZlinkStreamMetadata, ZlinkStreamMessageKind } from '../Contracts';
2
2
  import type { ZlinkStreamFrameProtocol } from './Protocol/ZlinkStreamFrameProtocol';
3
3
  import type { ZlinkFlowContext } from './ZlinkFlowContext';
4
- import type { ZlinkStreamRuntimeMetrics } from './ZlinkStreamRuntimeMetrics';
5
4
  export declare class ZlinkStreamFrameSender {
6
5
  private readonly protocol;
7
6
  private readonly flowContext;
8
- private readonly metrics;
9
7
  private readonly pendingWrites;
10
- constructor(protocol: ZlinkStreamFrameProtocol, flowContext: ZlinkFlowContext, metrics: ZlinkStreamRuntimeMetrics);
8
+ constructor(protocol: ZlinkStreamFrameProtocol, flowContext: ZlinkFlowContext);
11
9
  send(connection: ZlinkStreamConnection, kind: ZlinkStreamMessageKind, name: string, payload: ZlinkStreamEncodedPayload, metadata: ZlinkStreamMetadata, compress: boolean, requestSeq: bigint | undefined, signal?: AbortSignal, correlationId?: string, explicitFlow?: ZlinkStreamFlow): Promise<void>;
12
10
  sendControl(connection: ZlinkStreamConnection, name: string, signal?: AbortSignal): Promise<void>;
13
11
  drain(signal?: AbortSignal): Promise<void>;
@@ -6,7 +6,6 @@ import type { ZlinkStreamPendingRequests } from './ZlinkStreamPendingRequests';
6
6
  import type { ZlinkStreamReceivedMessages } from './ZlinkStreamReceivedMessages';
7
7
  import type { ZlinkFlowContext } from './ZlinkFlowContext';
8
8
  import type { ZlinkStreamCloseReason } from '../Contracts';
9
- import type { ZlinkStreamRuntimeMetrics } from './ZlinkStreamRuntimeMetrics';
10
9
  export interface ZlinkStreamReceiveResult {
11
10
  readonly available: boolean;
12
11
  readonly inbound: boolean;
@@ -18,10 +17,22 @@ export declare class ZlinkStreamReceiveDispatcher {
18
17
  private readonly frameSender;
19
18
  private readonly events;
20
19
  private readonly flowContext;
21
- private readonly metrics;
22
20
  private readonly serverClosing?;
23
- constructor(protocol: ZlinkStreamFrameProtocol, pendingRequests: ZlinkStreamPendingRequests, receivedMessages: ZlinkStreamReceivedMessages, frameSender: ZlinkStreamFrameSender, events: ZlinkStreamConnectorEvents, flowContext: ZlinkFlowContext, metrics: ZlinkStreamRuntimeMetrics, serverClosing?: ((reason: ZlinkStreamCloseReason) => Promise<void>) | undefined);
24
- readAndDispatch(connection: ZlinkStreamConnection | undefined, signal?: AbortSignal, isCurrent?: () => boolean): Promise<ZlinkStreamReceiveResult>;
21
+ constructor(protocol: ZlinkStreamFrameProtocol, pendingRequests: ZlinkStreamPendingRequests, receivedMessages: ZlinkStreamReceivedMessages, frameSender: ZlinkStreamFrameSender, events: ZlinkStreamConnectorEvents, flowContext: ZlinkFlowContext, serverClosing?: ((reason: ZlinkStreamCloseReason) => Promise<void>) | undefined);
22
+ /**
23
+ * @param isCurrent Tells whether the connection this batch was read from is
24
+ * still the connector's connection. It is asked again at the head of every
25
+ * frame, not only after the read: `dispatch` awaits application code —
26
+ * registered handlers in `Immediate`, the error handler on a failed frame —
27
+ * and a disconnect and reconnect can complete inside that await. Without
28
+ * the recheck the rest of a dead connection's batch lands on the new
29
+ * connection's state, and the §10 arrival counts, which start at 0 when a
30
+ * connection is established, take the stale frames on top.
31
+ * @param connectionForSend Resolves the connection a reply belongs on at the
32
+ * moment it is written. The captured `connection` is the one the batch was
33
+ * read from, which a reconnect may already have replaced.
34
+ */
35
+ readAndDispatch(connection: ZlinkStreamConnection | undefined, signal?: AbortSignal, isCurrent?: () => boolean, connectionForSend?: () => ZlinkStreamConnection): Promise<ZlinkStreamReceiveResult>;
25
36
  private dispatch;
26
37
  private dispatchControl;
27
38
  }
@@ -16,6 +16,8 @@ export declare class ZlinkStreamReceivedMessages {
16
16
  private queueHead;
17
17
  private queuedCount;
18
18
  private drainTask;
19
+ private draining;
20
+ private readonly receivedCounts;
19
21
  /**
20
22
  * @param deliverOnArrival `Immediate` runs registered handlers on the receive
21
23
  * path; `Manual` leaves them queued until {@link pump} runs them on the
@@ -31,12 +33,50 @@ export declare class ZlinkStreamReceivedMessages {
31
33
  * `Manual` needs no dispatch pump to complete a wait. The queue is scanned in
32
34
  * a microtask so a message that arrived before the wait started is still
33
35
  * observed, and so the caller has its subscription in hand by then.
36
+ *
37
+ * @param onConnectionEnded Called, instead of {@link observer}, when
38
+ * {@link resetForNewConnection} abandons this registration because the
39
+ * connection it was watching ended before a message matched (spec
40
+ * stream-connector 32 §10.1: "연결이 끝나 대기를 이어갈 수 없으면
41
+ * `Disconnected`다").
34
42
  */
35
- observe(name: string, observer: EncodedMessageObserver): Disposable;
43
+ observe(name: string, observer: EncodedMessageObserver, onConnectionEnded: () => void): Disposable;
44
+ /** Spec stream-connector 32 §10: arrivals under `name` on this connection. */
45
+ receivedCount(name: string): number;
46
+ /**
47
+ * Rebaselines the queue for a connection that was just established. Spec
48
+ * stream-connector 32 §10 (line ~649): the reference point is the moment a
49
+ * connection is established, so counts restart at 0 and whatever the
50
+ * previous connection left unconsumed goes with it — keeping the queue
51
+ * while only the counts reset would let counts and queue describe two
52
+ * different connections, and let `waitFor` hand back a packet from before
53
+ * the drop as if the new connection had delivered it.
54
+ *
55
+ * `ZlinkStreamMessage`/`ZlinkStreamEncodedPayload` are plain data (name,
56
+ * metadata, a `Uint8Array` payload) with no dispose/close of their own —
57
+ * unlike Java's queued frames, which `closeMessage` releases — so dropping
58
+ * the queue's references is the whole of the release here.
59
+ *
60
+ * @param replacesAnEarlierConnection False for the very first connection:
61
+ * there is no earlier queue or wait to abandon yet. True for a reconnect,
62
+ * which also fails every wait surface still registered from the
63
+ * connection that just ended with `Disconnected` (Java
64
+ * `ZLinkStreamDispatchQueue.resetForNewConnection` parity) — that
65
+ * registration was watching a queue this call just discarded, so letting
66
+ * it keep watching would silently rebind it to the new connection.
67
+ */
68
+ resetForNewConnection(replacesAnEarlierConnection: boolean): void;
36
69
  enqueue(message: ZlinkStreamMessage<ZlinkStreamEncodedPayload>, signal?: AbortSignal): void;
37
70
  /**
38
71
  * Runs the registered handlers the receive path left queued. `Manual` calls
39
72
  * this from `dispatch`; `Immediate` has already drained on arrival.
73
+ *
74
+ * A handler that calls `dispatch` arrives back here from inside the drain it
75
+ * was started by. `scheduleDrain` would find `drainTask` already set and
76
+ * return, and the await below would then be the drain waiting on itself —
77
+ * a deadlock with neither timeout nor error. The drain loop already takes
78
+ * every message a handler exists for, so there is nothing a second drain
79
+ * would deliver and returning is the whole of the correct behaviour.
40
80
  */
41
81
  pump(): Promise<void>;
42
82
  private offerQueued;
@@ -1,8 +1,13 @@
1
1
  export * from './Contracts';
2
- export { DefaultZlinkStreamConnector, } from './Runtime/ZlinkStreamConnector';
3
2
  export { zlinkStreamAssert } from './Runtime/ZlinkStreamAssertions';
4
- import { DefaultZlinkStreamConnector } from './Runtime/ZlinkStreamConnector';
5
- import type { ZlinkStreamConnectorOptions } from './Contracts';
3
+ import type { ZlinkStreamConnector, ZlinkStreamConnectorOptions } from './Contracts';
4
+ /**
5
+ * The only way to build a connector (TypeScript spec §4). The concrete class
6
+ * stays inside the package — the other four connectors hide their
7
+ * implementation type as well, and a consumer that named it here would depend
8
+ * on a shape no spec fixes. `create` validates every option before it returns
9
+ * and throws `ZlinkStreamException` when one is rejected (common spec §6.3).
10
+ */
6
11
  export declare const zlinkStreamConnectorFactory: {
7
- create(options: ZlinkStreamConnectorOptions): DefaultZlinkStreamConnector;
12
+ create(options: ZlinkStreamConnectorOptions): ZlinkStreamConnector;
8
13
  };