@spinajs/http-socket-client 0.0.0-stage → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -2
- package/lib/cjs/browser.d.ts +4 -0
- package/lib/cjs/browser.d.ts.map +1 -0
- package/lib/cjs/browser.js +21 -0
- package/lib/cjs/browser.js.map +1 -0
- package/lib/cjs/client.d.ts +94 -0
- package/lib/cjs/client.d.ts.map +1 -0
- package/lib/cjs/client.js +139 -0
- package/lib/cjs/client.js.map +1 -0
- package/lib/cjs/commands.d.ts +30 -0
- package/lib/cjs/commands.d.ts.map +1 -0
- package/lib/cjs/commands.js +132 -0
- package/lib/cjs/commands.js.map +1 -0
- package/lib/cjs/connection.d.ts +71 -0
- package/lib/cjs/connection.d.ts.map +1 -0
- package/lib/cjs/connection.js +233 -0
- package/lib/cjs/connection.js.map +1 -0
- package/lib/cjs/contract.d.ts +27 -0
- package/lib/cjs/contract.d.ts.map +1 -0
- package/lib/cjs/contract.js +3 -0
- package/lib/cjs/contract.js.map +1 -0
- package/lib/cjs/durable.d.ts +122 -0
- package/lib/cjs/durable.d.ts.map +1 -0
- package/lib/cjs/durable.js +396 -0
- package/lib/cjs/durable.js.map +1 -0
- package/lib/cjs/emitter.d.ts +22 -0
- package/lib/cjs/emitter.d.ts.map +1 -0
- package/lib/cjs/emitter.js +82 -0
- package/lib/cjs/emitter.js.map +1 -0
- package/lib/cjs/ids.d.ts +7 -0
- package/lib/cjs/ids.d.ts.map +1 -0
- package/lib/cjs/ids.js +11 -0
- package/lib/cjs/ids.js.map +1 -0
- package/lib/cjs/index.d.ts +17 -0
- package/lib/cjs/index.d.ts.map +1 -0
- package/lib/cjs/index.js +36 -0
- package/lib/cjs/index.js.map +1 -0
- package/lib/cjs/node/file-outbox.d.ts +40 -0
- package/lib/cjs/node/file-outbox.d.ts.map +1 -0
- package/lib/cjs/node/file-outbox.js +234 -0
- package/lib/cjs/node/file-outbox.js.map +1 -0
- package/lib/cjs/node/index.d.ts +4 -0
- package/lib/cjs/node/index.d.ts.map +1 -0
- package/lib/cjs/node/index.js +21 -0
- package/lib/cjs/node/index.js.map +1 -0
- package/lib/cjs/outbox-indexeddb.d.ts +38 -0
- package/lib/cjs/outbox-indexeddb.d.ts.map +1 -0
- package/lib/cjs/outbox-indexeddb.js +212 -0
- package/lib/cjs/outbox-indexeddb.js.map +1 -0
- package/lib/cjs/outbox.d.ts +53 -0
- package/lib/cjs/outbox.d.ts.map +1 -0
- package/lib/cjs/outbox.js +41 -0
- package/lib/cjs/outbox.js.map +1 -0
- package/lib/cjs/package.json +1 -0
- package/lib/cjs/reconnect.d.ts +21 -0
- package/lib/cjs/reconnect.d.ts.map +1 -0
- package/lib/cjs/reconnect.js +37 -0
- package/lib/cjs/reconnect.js.map +1 -0
- package/lib/cjs/streams.d.ts +91 -0
- package/lib/cjs/streams.d.ts.map +1 -0
- package/lib/cjs/streams.js +302 -0
- package/lib/cjs/streams.js.map +1 -0
- package/lib/cjs/timeout.d.ts +4 -0
- package/lib/cjs/timeout.d.ts.map +1 -0
- package/lib/cjs/timeout.js +13 -0
- package/lib/cjs/timeout.js.map +1 -0
- package/lib/mjs/browser.d.ts +4 -0
- package/lib/mjs/browser.d.ts.map +1 -0
- package/lib/mjs/browser.js +3 -0
- package/lib/mjs/browser.js.map +1 -0
- package/lib/mjs/client.d.ts +94 -0
- package/lib/mjs/client.d.ts.map +1 -0
- package/lib/mjs/client.js +135 -0
- package/lib/mjs/client.js.map +1 -0
- package/lib/mjs/commands.d.ts +30 -0
- package/lib/mjs/commands.d.ts.map +1 -0
- package/lib/mjs/commands.js +128 -0
- package/lib/mjs/commands.js.map +1 -0
- package/lib/mjs/connection.d.ts +71 -0
- package/lib/mjs/connection.d.ts.map +1 -0
- package/lib/mjs/connection.js +229 -0
- package/lib/mjs/connection.js.map +1 -0
- package/lib/mjs/contract.d.ts +27 -0
- package/lib/mjs/contract.d.ts.map +1 -0
- package/lib/mjs/contract.js +2 -0
- package/lib/mjs/contract.js.map +1 -0
- package/lib/mjs/durable.d.ts +122 -0
- package/lib/mjs/durable.d.ts.map +1 -0
- package/lib/mjs/durable.js +392 -0
- package/lib/mjs/durable.js.map +1 -0
- package/lib/mjs/emitter.d.ts +22 -0
- package/lib/mjs/emitter.d.ts.map +1 -0
- package/lib/mjs/emitter.js +77 -0
- package/lib/mjs/emitter.js.map +1 -0
- package/lib/mjs/ids.d.ts +7 -0
- package/lib/mjs/ids.d.ts.map +1 -0
- package/lib/mjs/ids.js +8 -0
- package/lib/mjs/ids.js.map +1 -0
- package/lib/mjs/index.d.ts +17 -0
- package/lib/mjs/index.d.ts.map +1 -0
- package/lib/mjs/index.js +9 -0
- package/lib/mjs/index.js.map +1 -0
- package/lib/mjs/node/file-outbox.d.ts +40 -0
- package/lib/mjs/node/file-outbox.d.ts.map +1 -0
- package/lib/mjs/node/file-outbox.js +230 -0
- package/lib/mjs/node/file-outbox.js.map +1 -0
- package/lib/mjs/node/index.d.ts +4 -0
- package/lib/mjs/node/index.d.ts.map +1 -0
- package/lib/mjs/node/index.js +3 -0
- package/lib/mjs/node/index.js.map +1 -0
- package/lib/mjs/outbox-indexeddb.d.ts +38 -0
- package/lib/mjs/outbox-indexeddb.d.ts.map +1 -0
- package/lib/mjs/outbox-indexeddb.js +208 -0
- package/lib/mjs/outbox-indexeddb.js.map +1 -0
- package/lib/mjs/outbox.d.ts +53 -0
- package/lib/mjs/outbox.d.ts.map +1 -0
- package/lib/mjs/outbox.js +37 -0
- package/lib/mjs/outbox.js.map +1 -0
- package/lib/mjs/package.json +1 -0
- package/lib/mjs/reconnect.d.ts +21 -0
- package/lib/mjs/reconnect.d.ts.map +1 -0
- package/lib/mjs/reconnect.js +33 -0
- package/lib/mjs/reconnect.js.map +1 -0
- package/lib/mjs/streams.d.ts +91 -0
- package/lib/mjs/streams.d.ts.map +1 -0
- package/lib/mjs/streams.js +297 -0
- package/lib/mjs/streams.js.map +1 -0
- package/lib/mjs/timeout.d.ts +4 -0
- package/lib/mjs/timeout.d.ts.map +1 -0
- package/lib/mjs/timeout.js +9 -0
- package/lib/mjs/timeout.js.map +1 -0
- package/lib/tsconfig.cjs.tsbuildinfo +1 -0
- package/lib/tsconfig.mjs.tsbuildinfo +1 -0
- package/package.json +67 -4
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ReconnectOptions {
|
|
2
|
+
minMs: number;
|
|
3
|
+
maxMs: number;
|
|
4
|
+
/** Fraction in [0, 1] by which a delay is randomly varied. */
|
|
5
|
+
jitter: number;
|
|
6
|
+
}
|
|
7
|
+
/** Ceiling for a server-provided retry hint, independent of the backoff ceiling. */
|
|
8
|
+
export declare const MAX_SERVER_HINT_MS = 300000;
|
|
9
|
+
export declare const DEFAULT_RECONNECT: Readonly<ReconnectOptions>;
|
|
10
|
+
export declare class ReconnectPolicy {
|
|
11
|
+
private readonly random;
|
|
12
|
+
readonly options: Readonly<ReconnectOptions>;
|
|
13
|
+
constructor(options?: Partial<ReconnectOptions>, random?: () => number);
|
|
14
|
+
/**
|
|
15
|
+
* Delay before retry `attempt` (0 = the first retry after a failure). Jitter only shortens the
|
|
16
|
+
* exponential delay, so maxMs is a hard ceiling. A server hint is a floor, spread upwards so that
|
|
17
|
+
* clients told the same retryAfterMs do not all come back at once.
|
|
18
|
+
*/
|
|
19
|
+
delay(attempt: number, retryAfterMs?: number): number;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=reconnect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnect.d.ts","sourceRoot":"","sources":["../../src/reconnect.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,SAAU,CAAC;AAE1C,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,gBAAgB,CAA6D,CAAC;AAEvH,qBAAa,eAAe;IAG2B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAF5E,SAAgB,OAAO,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAEpD,YAAY,OAAO,GAAE,OAAO,CAAC,gBAAgB,CAAM,EAAmB,MAAM,GAAE,MAAM,MAAoB,EAMvG;IAED;;;;OAIG;IACI,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAS3D;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Ceiling for a server-provided retry hint, independent of the backoff ceiling. */
|
|
2
|
+
export const MAX_SERVER_HINT_MS = 300_000;
|
|
3
|
+
export const DEFAULT_RECONNECT = Object.freeze({ minMs: 500, maxMs: 30_000, jitter: 0.3 });
|
|
4
|
+
export class ReconnectPolicy {
|
|
5
|
+
constructor(options = {}, random = Math.random) {
|
|
6
|
+
this.random = random;
|
|
7
|
+
const merged = { ...DEFAULT_RECONNECT, ...options };
|
|
8
|
+
if (!(merged.minMs >= 0))
|
|
9
|
+
throw new RangeError(`reconnect.minMs must be >= 0, got ${merged.minMs}`);
|
|
10
|
+
if (!(merged.maxMs >= merged.minMs))
|
|
11
|
+
throw new RangeError(`reconnect.maxMs must be >= minMs, got ${merged.maxMs}`);
|
|
12
|
+
if (!(merged.jitter >= 0 && merged.jitter <= 1))
|
|
13
|
+
throw new RangeError(`reconnect.jitter must be within [0, 1], got ${merged.jitter}`);
|
|
14
|
+
this.options = Object.freeze(merged);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Delay before retry `attempt` (0 = the first retry after a failure). Jitter only shortens the
|
|
18
|
+
* exponential delay, so maxMs is a hard ceiling. A server hint is a floor, spread upwards so that
|
|
19
|
+
* clients told the same retryAfterMs do not all come back at once.
|
|
20
|
+
*/
|
|
21
|
+
delay(attempt, retryAfterMs) {
|
|
22
|
+
const { minMs, maxMs, jitter } = this.options;
|
|
23
|
+
// clamped: 2 ** 1024 is Infinity, and 0 * Infinity is NaN
|
|
24
|
+
const exponential = Math.min(maxMs, minMs * 2 ** Math.min(attempt, 64));
|
|
25
|
+
const backoff = Math.round(exponential * (1 - jitter * this.random()));
|
|
26
|
+
if (retryAfterMs === undefined || !Number.isFinite(retryAfterMs) || retryAfterMs <= 0)
|
|
27
|
+
return backoff;
|
|
28
|
+
// a hostile or buggy server must not park the client for days
|
|
29
|
+
const hinted = Math.min(Math.round(retryAfterMs * (1 + jitter * this.random())), MAX_SERVER_HINT_MS);
|
|
30
|
+
return Math.max(backoff, hinted);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=reconnect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconnect.js","sourceRoot":"","sources":["../../src/reconnect.ts"],"names":[],"mappings":"AAOA,oFAAoF;AACpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAE1C,MAAM,CAAC,MAAM,iBAAiB,GAA+B,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;AAEvH,MAAM,OAAO,eAAe;IAG1B,YAAY,OAAO,GAA8B,EAAE,EAAmB,MAAM,GAAiB,IAAI,CAAC,MAAM;sBAAlC,MAAM;QAC1E,MAAM,MAAM,GAAG,EAAE,GAAG,iBAAiB,EAAE,GAAG,OAAO,EAAE,CAAC;QACpD,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,qCAAqC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACpG,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,yCAAyC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACnH,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,+CAA+C,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACtI,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,OAAe,EAAE,YAAqB;QACjD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC9C,0DAA0D;QAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,YAAY,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC;YAAE,OAAO,OAAO,CAAC;QACtG,8DAA8D;QAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;QACrG,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { type Chunk, type SocketError, type StreamEnd } from '@spinajs/http-socket-common';
|
|
2
|
+
import type { CommandOptions } from './commands.js';
|
|
3
|
+
import type { Connection } from './connection.js';
|
|
4
|
+
export interface StreamOptions extends CommandOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Chunks the server may send ahead of the consumer: the most that are ever in flight or buffered.
|
|
7
|
+
* More are granted as the consumer reads. At most the server's `http.socket.streams.maxCredits` ( 64 ).
|
|
8
|
+
*/
|
|
9
|
+
credits?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const DEFAULT_STREAM_CREDITS = 8;
|
|
12
|
+
interface StreamHost {
|
|
13
|
+
readonly connection: Connection;
|
|
14
|
+
readonly defaultTimeoutMs: number;
|
|
15
|
+
nextId(): string;
|
|
16
|
+
hold(stream: ClientStream<unknown>): void;
|
|
17
|
+
register(id: string, stream: ClientStream<unknown>): void;
|
|
18
|
+
release(stream: ClientStream<unknown>): void;
|
|
19
|
+
}
|
|
20
|
+
/** Routes stream frames to their ClientStream and fails or resumes streams on connection changes. */
|
|
21
|
+
export declare class StreamDispatcher implements StreamHost {
|
|
22
|
+
readonly connection: Connection;
|
|
23
|
+
private readonly ids;
|
|
24
|
+
readonly defaultTimeoutMs: number;
|
|
25
|
+
private readonly waiting;
|
|
26
|
+
private readonly open;
|
|
27
|
+
constructor(connection: Connection, ids: () => string, defaultTimeoutMs: number);
|
|
28
|
+
/** @internal streams held offline plus streams sent or open; 0 once every stream has settled */
|
|
29
|
+
get activeStreams(): number;
|
|
30
|
+
stream<T>(name: string, payload?: unknown, options?: StreamOptions): ClientStream<T>;
|
|
31
|
+
nextId(): string;
|
|
32
|
+
hold(stream: ClientStream<unknown>): void;
|
|
33
|
+
register(id: string, stream: ClientStream<unknown>): void;
|
|
34
|
+
release(stream: ClientStream<unknown>): void;
|
|
35
|
+
private onState;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One stream reply as an async iterator. It starts on the first `next()`. It keeps
|
|
39
|
+
* `granted − consumed ≤ credits`, so no more than `credits` chunks are ever in flight or buffered.
|
|
40
|
+
*/
|
|
41
|
+
export declare class ClientStream<T> implements AsyncIterableIterator<T> {
|
|
42
|
+
private readonly host;
|
|
43
|
+
private readonly name;
|
|
44
|
+
private readonly payload;
|
|
45
|
+
private readonly options;
|
|
46
|
+
private phase;
|
|
47
|
+
private requestId;
|
|
48
|
+
private readonly buffer;
|
|
49
|
+
private reader;
|
|
50
|
+
private failure;
|
|
51
|
+
private received;
|
|
52
|
+
private granted;
|
|
53
|
+
private consumed;
|
|
54
|
+
private deadlineAt;
|
|
55
|
+
private timer;
|
|
56
|
+
private readonly window;
|
|
57
|
+
private readonly timeoutMs;
|
|
58
|
+
private readonly onAbort;
|
|
59
|
+
constructor(host: StreamHost, name: string, payload: unknown, options: StreamOptions);
|
|
60
|
+
/** The request id; empty until the request is sent. */
|
|
61
|
+
get id(): string;
|
|
62
|
+
/** @internal chunks received and not yet read */
|
|
63
|
+
get buffered(): number;
|
|
64
|
+
[Symbol.asyncIterator](): this;
|
|
65
|
+
/** Reads one item. Calls must not overlap: a second next() while one is pending rejects with a TypeError. */
|
|
66
|
+
next(): Promise<IteratorResult<T>>;
|
|
67
|
+
/** `for await` calls it on break or throw: the server is told to stop and its generator's `finally` runs. */
|
|
68
|
+
return(): Promise<IteratorResult<T>>;
|
|
69
|
+
/** @internal sends the request now, or again once online for a held stream */
|
|
70
|
+
transmit(): void;
|
|
71
|
+
/** @internal */
|
|
72
|
+
onChunk(frame: Chunk): void;
|
|
73
|
+
/** @internal */
|
|
74
|
+
onEnd(frame: StreamEnd): void;
|
|
75
|
+
/** @internal the chunks received before the failure are still delivered */
|
|
76
|
+
onFail(error: SocketError): void;
|
|
77
|
+
/** @internal the connection dropped or the client closed; the chunks received are still delivered */
|
|
78
|
+
abandon(error: SocketError): void;
|
|
79
|
+
private start;
|
|
80
|
+
private onReply;
|
|
81
|
+
private take;
|
|
82
|
+
/** Grants in batches of at least half the window, so a fast consumer does not send one frame per chunk. */
|
|
83
|
+
private replenish;
|
|
84
|
+
/** Ends the stream from this side: buffered items are dropped and the server is told to stop. */
|
|
85
|
+
private stop;
|
|
86
|
+
private finish;
|
|
87
|
+
private arm;
|
|
88
|
+
private disarm;
|
|
89
|
+
}
|
|
90
|
+
export {};
|
|
91
|
+
//# sourceMappingURL=streams.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streams.d.ts","sourceRoot":"","sources":["../../src/streams.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { SocketException, WIRE_EVENTS, isChunk, isSocketError, isStreamEnd, isStreamFail } from '@spinajs/http-socket-common';
|
|
2
|
+
import { assertTimeoutMs } from './timeout.js';
|
|
3
|
+
export const DEFAULT_STREAM_CREDITS = 8;
|
|
4
|
+
const CLOSED = { code: 'unavailable', message: 'the client is closed', retryable: false };
|
|
5
|
+
const OFFLINE = { code: 'unavailable', message: 'the client is offline', retryable: true };
|
|
6
|
+
const STAYED_OFFLINE = { code: 'unavailable', message: 'the client stayed offline until the timeout', retryable: true };
|
|
7
|
+
const CONNECTION_LOST = { code: 'unavailable', message: 'the connection dropped during the stream', retryable: true };
|
|
8
|
+
const NO_REPLY = { code: 'deadline_exceeded', message: 'no reply before the timeout', retryable: true };
|
|
9
|
+
const NO_FRAME = { code: 'deadline_exceeded', message: 'no stream frame before the timeout', retryable: true };
|
|
10
|
+
const CANCELLED = { code: 'cancelled', message: 'the stream was cancelled', retryable: false };
|
|
11
|
+
const NOT_A_STREAM = { code: 'failed_precondition', message: 'the command does not reply with a stream; use command()', retryable: false };
|
|
12
|
+
const MALFORMED_REPLY = { code: 'internal', message: 'malformed reply', retryable: false };
|
|
13
|
+
const MALFORMED_FAIL = { code: 'internal', message: 'malformed stream fail frame', retryable: false };
|
|
14
|
+
const OUT_OF_ORDER = { code: 'internal', message: 'stream frames arrived out of order', retryable: false };
|
|
15
|
+
const OVER_CREDIT = { code: 'internal', message: 'the server sent more chunks than it had credit for', retryable: false };
|
|
16
|
+
function assertCredits(value) {
|
|
17
|
+
if (!(Number.isSafeInteger(value) && value > 0)) {
|
|
18
|
+
throw new RangeError(`credits must be a positive integer, got ${value}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Routes stream frames to their ClientStream and fails or resumes streams on connection changes. */
|
|
22
|
+
export class StreamDispatcher {
|
|
23
|
+
constructor(connection, ids, defaultTimeoutMs) {
|
|
24
|
+
this.connection = connection;
|
|
25
|
+
this.ids = ids;
|
|
26
|
+
this.defaultTimeoutMs = defaultTimeoutMs;
|
|
27
|
+
this.waiting = new Set();
|
|
28
|
+
this.open = new Map();
|
|
29
|
+
assertTimeoutMs('defaultTimeoutMs', defaultTimeoutMs);
|
|
30
|
+
connection.listen(WIRE_EVENTS.chunk, (frame) => {
|
|
31
|
+
if (isChunk(frame))
|
|
32
|
+
this.open.get(frame.id)?.onChunk(frame);
|
|
33
|
+
});
|
|
34
|
+
connection.listen(WIRE_EVENTS.end, (frame) => {
|
|
35
|
+
if (isStreamEnd(frame))
|
|
36
|
+
this.open.get(frame.id)?.onEnd(frame);
|
|
37
|
+
});
|
|
38
|
+
connection.listen(WIRE_EVENTS.fail, (frame) => {
|
|
39
|
+
if (isStreamFail(frame))
|
|
40
|
+
this.open.get(frame.id)?.onFail(frame.error);
|
|
41
|
+
else if (typeof frame?.id === 'string')
|
|
42
|
+
this.open.get(frame.id)?.onFail(MALFORMED_FAIL);
|
|
43
|
+
});
|
|
44
|
+
connection.events.on('state', (state, previous) => this.onState(state, previous));
|
|
45
|
+
}
|
|
46
|
+
/** @internal streams held offline plus streams sent or open; 0 once every stream has settled */
|
|
47
|
+
get activeStreams() {
|
|
48
|
+
return this.waiting.size + this.open.size;
|
|
49
|
+
}
|
|
50
|
+
stream(name, payload, options = {}) {
|
|
51
|
+
return new ClientStream(this, name, payload, options);
|
|
52
|
+
}
|
|
53
|
+
nextId() {
|
|
54
|
+
return this.ids();
|
|
55
|
+
}
|
|
56
|
+
hold(stream) {
|
|
57
|
+
this.waiting.add(stream);
|
|
58
|
+
}
|
|
59
|
+
register(id, stream) {
|
|
60
|
+
this.open.set(id, stream);
|
|
61
|
+
}
|
|
62
|
+
release(stream) {
|
|
63
|
+
this.waiting.delete(stream);
|
|
64
|
+
if (this.open.get(stream.id) === stream)
|
|
65
|
+
this.open.delete(stream.id);
|
|
66
|
+
}
|
|
67
|
+
onState(state, previous) {
|
|
68
|
+
if (state === 'closed') {
|
|
69
|
+
for (const stream of [...this.waiting, ...this.open.values()])
|
|
70
|
+
stream.abandon(CLOSED);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (previous === 'online')
|
|
74
|
+
for (const stream of [...this.open.values()])
|
|
75
|
+
stream.abandon(CONNECTION_LOST);
|
|
76
|
+
if (state === 'online')
|
|
77
|
+
for (const stream of [...this.waiting])
|
|
78
|
+
stream.transmit();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* One stream reply as an async iterator. It starts on the first `next()`. It keeps
|
|
83
|
+
* `granted − consumed ≤ credits`, so no more than `credits` chunks are ever in flight or buffered.
|
|
84
|
+
*/
|
|
85
|
+
export class ClientStream {
|
|
86
|
+
constructor(host, name, payload, options) {
|
|
87
|
+
this.host = host;
|
|
88
|
+
this.name = name;
|
|
89
|
+
this.payload = payload;
|
|
90
|
+
this.options = options;
|
|
91
|
+
this.phase = 'idle';
|
|
92
|
+
this.requestId = '';
|
|
93
|
+
this.buffer = [];
|
|
94
|
+
this.reader = null;
|
|
95
|
+
this.failure = null;
|
|
96
|
+
this.received = 0;
|
|
97
|
+
this.granted = 0;
|
|
98
|
+
this.consumed = 0;
|
|
99
|
+
this.deadlineAt = 0;
|
|
100
|
+
this.onAbort = () => this.stop(CANCELLED);
|
|
101
|
+
this.window = options.credits ?? DEFAULT_STREAM_CREDITS;
|
|
102
|
+
this.timeoutMs = options.timeoutMs ?? host.defaultTimeoutMs;
|
|
103
|
+
}
|
|
104
|
+
/** The request id; empty until the request is sent. */
|
|
105
|
+
get id() {
|
|
106
|
+
return this.requestId;
|
|
107
|
+
}
|
|
108
|
+
/** @internal chunks received and not yet read */
|
|
109
|
+
get buffered() {
|
|
110
|
+
return this.buffer.length;
|
|
111
|
+
}
|
|
112
|
+
[Symbol.asyncIterator]() {
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
/** Reads one item. Calls must not overlap: a second next() while one is pending rejects with a TypeError. */
|
|
116
|
+
next() {
|
|
117
|
+
if (this.phase === 'idle')
|
|
118
|
+
this.start();
|
|
119
|
+
if (this.buffer.length > 0)
|
|
120
|
+
return Promise.resolve({ value: this.take(), done: false });
|
|
121
|
+
if (this.phase === 'done')
|
|
122
|
+
return this.failure === null ? Promise.resolve({ value: undefined, done: true }) : Promise.reject(this.failure);
|
|
123
|
+
if (this.reader)
|
|
124
|
+
return Promise.reject(new TypeError('next() called before the previous next() settled'));
|
|
125
|
+
return new Promise((resolve, reject) => {
|
|
126
|
+
this.reader = { resolve, reject };
|
|
127
|
+
if (this.phase === 'open')
|
|
128
|
+
this.arm(this.timeoutMs, NO_FRAME);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/** `for await` calls it on break or throw: the server is told to stop and its generator's `finally` runs. */
|
|
132
|
+
async return() {
|
|
133
|
+
this.stop(null);
|
|
134
|
+
this.failure = null;
|
|
135
|
+
return { value: undefined, done: true };
|
|
136
|
+
}
|
|
137
|
+
/** @internal sends the request now, or again once online for a held stream */
|
|
138
|
+
transmit() {
|
|
139
|
+
if (this.phase !== 'idle' && this.phase !== 'waiting')
|
|
140
|
+
return;
|
|
141
|
+
this.host.release(this);
|
|
142
|
+
this.requestId = this.host.nextId();
|
|
143
|
+
this.granted = this.window;
|
|
144
|
+
this.phase = 'sent';
|
|
145
|
+
this.host.register(this.requestId, this);
|
|
146
|
+
const remaining = Math.max(1, this.deadlineAt - Date.now());
|
|
147
|
+
// deadline: relative, so client/server clock skew cannot expire it; it bounds the reply only
|
|
148
|
+
const request = { id: this.requestId, name: this.name, payload: this.payload, credits: this.window, deadline: remaining };
|
|
149
|
+
if (this.options.traceparent !== undefined)
|
|
150
|
+
request.traceparent = this.options.traceparent;
|
|
151
|
+
this.arm(remaining, NO_REPLY);
|
|
152
|
+
const sent = this.host.connection.request(WIRE_EVENTS.command, request, (reply) => this.onReply(reply));
|
|
153
|
+
if (!sent)
|
|
154
|
+
this.finish(CONNECTION_LOST);
|
|
155
|
+
}
|
|
156
|
+
/** @internal */
|
|
157
|
+
onChunk(frame) {
|
|
158
|
+
if (this.phase !== 'sent' && this.phase !== 'open')
|
|
159
|
+
return;
|
|
160
|
+
if (frame.seq !== this.received)
|
|
161
|
+
return this.stop(OUT_OF_ORDER);
|
|
162
|
+
if (this.received >= this.granted)
|
|
163
|
+
return this.stop(OVER_CREDIT);
|
|
164
|
+
this.received++;
|
|
165
|
+
const value = frame.data;
|
|
166
|
+
const reader = this.reader;
|
|
167
|
+
if (!reader) {
|
|
168
|
+
this.buffer.push(value);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this.reader = null;
|
|
172
|
+
// before the ack the armed timer is the reply timeout, which must keep running
|
|
173
|
+
if (this.phase === 'open')
|
|
174
|
+
this.disarm();
|
|
175
|
+
this.consumed++;
|
|
176
|
+
this.replenish();
|
|
177
|
+
reader.resolve({ value, done: false });
|
|
178
|
+
}
|
|
179
|
+
/** @internal */
|
|
180
|
+
onEnd(frame) {
|
|
181
|
+
if (this.phase !== 'sent' && this.phase !== 'open')
|
|
182
|
+
return;
|
|
183
|
+
if (frame.seq !== this.received)
|
|
184
|
+
return this.stop(OUT_OF_ORDER);
|
|
185
|
+
this.finish(null);
|
|
186
|
+
}
|
|
187
|
+
/** @internal the chunks received before the failure are still delivered */
|
|
188
|
+
onFail(error) {
|
|
189
|
+
if (this.phase !== 'sent' && this.phase !== 'open')
|
|
190
|
+
return;
|
|
191
|
+
this.finish(error);
|
|
192
|
+
}
|
|
193
|
+
/** @internal the connection dropped or the client closed; the chunks received are still delivered */
|
|
194
|
+
abandon(error) {
|
|
195
|
+
this.finish(error);
|
|
196
|
+
}
|
|
197
|
+
start() {
|
|
198
|
+
try {
|
|
199
|
+
assertTimeoutMs('timeoutMs', this.timeoutMs);
|
|
200
|
+
assertCredits(this.window);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
this.phase = 'done';
|
|
204
|
+
this.failure = error;
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
const connection = this.host.connection;
|
|
208
|
+
if (connection.state === 'closed')
|
|
209
|
+
return this.finish(CLOSED);
|
|
210
|
+
if (this.options.signal?.aborted)
|
|
211
|
+
return this.finish(CANCELLED);
|
|
212
|
+
if (!connection.connected && (this.options.whenOffline ?? 'fail') === 'fail')
|
|
213
|
+
return this.finish(OFFLINE);
|
|
214
|
+
this.deadlineAt = Date.now() + this.timeoutMs;
|
|
215
|
+
this.options.signal?.addEventListener('abort', this.onAbort, { once: true });
|
|
216
|
+
if (connection.connected)
|
|
217
|
+
return this.transmit();
|
|
218
|
+
this.phase = 'waiting';
|
|
219
|
+
this.host.hold(this);
|
|
220
|
+
this.arm(this.timeoutMs, STAYED_OFFLINE);
|
|
221
|
+
}
|
|
222
|
+
onReply(reply) {
|
|
223
|
+
if (this.phase !== 'sent')
|
|
224
|
+
return;
|
|
225
|
+
if (typeof reply !== 'object' || reply === null || typeof reply.ok !== 'boolean')
|
|
226
|
+
return this.stop(MALFORMED_REPLY);
|
|
227
|
+
if (!reply.ok)
|
|
228
|
+
return this.finish(isSocketError(reply.error) ? reply.error : MALFORMED_REPLY);
|
|
229
|
+
if (!('stream' in reply) || reply.stream !== true)
|
|
230
|
+
return this.finish(NOT_A_STREAM);
|
|
231
|
+
this.phase = 'open';
|
|
232
|
+
this.disarm();
|
|
233
|
+
// chunks read before the ack were not credited back
|
|
234
|
+
this.replenish();
|
|
235
|
+
if (this.reader)
|
|
236
|
+
this.arm(this.timeoutMs, NO_FRAME);
|
|
237
|
+
}
|
|
238
|
+
take() {
|
|
239
|
+
const value = this.buffer.shift();
|
|
240
|
+
this.consumed++;
|
|
241
|
+
this.replenish();
|
|
242
|
+
return value;
|
|
243
|
+
}
|
|
244
|
+
/** Grants in batches of at least half the window, so a fast consumer does not send one frame per chunk. */
|
|
245
|
+
replenish() {
|
|
246
|
+
if (this.phase !== 'open')
|
|
247
|
+
return;
|
|
248
|
+
const free = this.window - (this.granted - this.consumed);
|
|
249
|
+
if (free < Math.max(1, Math.floor(this.window / 2)))
|
|
250
|
+
return;
|
|
251
|
+
const credit = { id: this.requestId, credits: free };
|
|
252
|
+
if (this.host.connection.send(WIRE_EVENTS.credit, credit))
|
|
253
|
+
this.granted += free;
|
|
254
|
+
}
|
|
255
|
+
/** Ends the stream from this side: buffered items are dropped and the server is told to stop. */
|
|
256
|
+
stop(error) {
|
|
257
|
+
this.buffer.length = 0;
|
|
258
|
+
if (this.phase === 'sent' || this.phase === 'open') {
|
|
259
|
+
const cancel = { id: this.requestId };
|
|
260
|
+
this.host.connection.send(WIRE_EVENTS.cancel, cancel);
|
|
261
|
+
}
|
|
262
|
+
this.finish(error);
|
|
263
|
+
}
|
|
264
|
+
finish(error) {
|
|
265
|
+
if (this.phase === 'done')
|
|
266
|
+
return;
|
|
267
|
+
this.phase = 'done';
|
|
268
|
+
this.disarm();
|
|
269
|
+
this.options.signal?.removeEventListener('abort', this.onAbort);
|
|
270
|
+
this.host.release(this);
|
|
271
|
+
if (error !== null)
|
|
272
|
+
this.failure = SocketException.fromWire(error);
|
|
273
|
+
// a waiting reader means the buffer is empty
|
|
274
|
+
const reader = this.reader;
|
|
275
|
+
if (!reader)
|
|
276
|
+
return;
|
|
277
|
+
this.reader = null;
|
|
278
|
+
if (this.failure === null)
|
|
279
|
+
reader.resolve({ value: undefined, done: true });
|
|
280
|
+
else
|
|
281
|
+
reader.reject(this.failure);
|
|
282
|
+
}
|
|
283
|
+
arm(ms, error) {
|
|
284
|
+
this.disarm();
|
|
285
|
+
this.timer = setTimeout(() => {
|
|
286
|
+
this.timer = undefined;
|
|
287
|
+
this.stop(error);
|
|
288
|
+
}, ms);
|
|
289
|
+
}
|
|
290
|
+
disarm() {
|
|
291
|
+
if (this.timer === undefined)
|
|
292
|
+
return;
|
|
293
|
+
clearTimeout(this.timer);
|
|
294
|
+
this.timer = undefined;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=streams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streams.js","sourceRoot":"","sources":["../../src/streams.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout.d.ts","sourceRoot":"","sources":["../../src/timeout.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,eAAO,MAAM,YAAY,aAAgB,CAAC;AAE1C,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** setTimeout fires immediately for a delay above this (a 32-bit signed integer). */
|
|
2
|
+
export const MAX_TIMER_MS = 2_147_483_647;
|
|
3
|
+
export function assertTimeoutMs(name, value) {
|
|
4
|
+
if (!(Number.isFinite(value) && value > 0 && value <= MAX_TIMER_MS)) {
|
|
5
|
+
throw new RangeError(`${name} must be a finite number within (0, ${MAX_TIMER_MS}], got ${value}`);
|
|
6
|
+
}
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=timeout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeout.js","sourceRoot":"","sources":["../../src/timeout.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC;AAE1C,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAa;IACzD,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,YAAY,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,UAAU,CAAC,GAAG,IAAI,uCAAuC,YAAY,UAAU,KAAK,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|