@zlink-systems/stream-connector 0.17.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.
- package/dist/browser/Contracts/Calls/ZlinkStreamCalls.d.ts +8 -2
- package/dist/browser/Contracts/IZlinkStreamConnector.d.ts +24 -3
- package/dist/browser/Contracts/ZlinkStreamConnectorOptions.d.ts +5 -17
- package/dist/browser/Runtime/Calls/ZlinkStreamObservationBuilders.d.ts +2 -2
- package/dist/browser/Runtime/ZlinkStreamConnector.d.ts +26 -5
- package/dist/browser/Runtime/ZlinkStreamConnectorLifecycle.d.ts +41 -4
- package/dist/browser/Runtime/ZlinkStreamConnectorOptions.d.ts +15 -1
- package/dist/browser/Runtime/ZlinkStreamFrameSender.d.ts +1 -3
- package/dist/browser/Runtime/ZlinkStreamReceiveDispatcher.d.ts +15 -4
- package/dist/browser/Runtime/ZlinkStreamReceivedMessages.d.ts +41 -1
- package/dist/browser/index.d.ts +9 -4
- package/dist/browser/index.global.js +340 -206
- package/dist/browser/index.mjs +328 -180
- package/package.json +2 -2
- package/dist/browser/Runtime/ZlinkStreamRuntimeMetrics.d.ts +0 -17
|
@@ -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: (
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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: (
|
|
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
|
-
*
|
|
33
|
-
*
|
|
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>(
|
|
47
|
-
expectNone<TPayload = ZlinkStreamEncodedPayload>(
|
|
48
|
-
waitForSequence<TPayload = ZlinkStreamEncodedPayload>(
|
|
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
|
|
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
|
-
|
|
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
|
|
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,
|
|
24
|
-
|
|
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;
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
export * from './Contracts';
|
|
2
|
-
export { DefaultZlinkStreamConnector, } from './Runtime/ZlinkStreamConnector';
|
|
3
2
|
export { zlinkStreamAssert } from './Runtime/ZlinkStreamAssertions';
|
|
4
|
-
import {
|
|
5
|
-
|
|
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):
|
|
12
|
+
create(options: ZlinkStreamConnectorOptions): ZlinkStreamConnector;
|
|
8
13
|
};
|