@milaboratories/pl-client 2.16.12 → 2.16.14
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/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.cjs.map +1 -1
- package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.js.map +1 -1
- package/dist/core/client.cjs +31 -16
- package/dist/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts +3 -2
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +31 -16
- package/dist/core/client.js.map +1 -1
- package/dist/core/default_client.cjs +1 -1
- package/dist/core/default_client.cjs.map +1 -1
- package/dist/core/default_client.js +1 -1
- package/dist/core/default_client.js.map +1 -1
- package/dist/core/driver.cjs +1 -1
- package/dist/core/driver.cjs.map +1 -1
- package/dist/core/driver.js +1 -1
- package/dist/core/driver.js.map +1 -1
- package/dist/core/errors.cjs +15 -4
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +15 -4
- package/dist/core/errors.js.map +1 -1
- package/dist/core/ll_client.cjs +61 -21
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +12 -3
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +62 -22
- package/dist/core/ll_client.js.map +1 -1
- package/dist/core/transaction.cjs +1 -1
- package/dist/core/transaction.js +1 -1
- package/dist/core/unauth_client.cjs +6 -2
- package/dist/core/unauth_client.cjs.map +1 -1
- package/dist/core/unauth_client.d.ts +2 -1
- package/dist/core/unauth_client.d.ts.map +1 -1
- package/dist/core/unauth_client.js +6 -2
- package/dist/core/unauth_client.js.map +1 -1
- package/dist/core/websocket_stream.cjs +147 -129
- package/dist/core/websocket_stream.cjs.map +1 -1
- package/dist/core/websocket_stream.d.ts +29 -22
- package/dist/core/websocket_stream.d.ts.map +1 -1
- package/dist/core/websocket_stream.js +148 -130
- package/dist/core/websocket_stream.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +136 -0
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +75 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +135 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
- package/dist/proto-rest/index.cjs +16 -2
- package/dist/proto-rest/index.cjs.map +1 -1
- package/dist/proto-rest/index.d.ts.map +1 -1
- package/dist/proto-rest/index.js +16 -2
- package/dist/proto-rest/index.js.map +1 -1
- package/dist/test/test_config.cjs +13 -3
- package/dist/test/test_config.cjs.map +1 -1
- package/dist/test/test_config.d.ts +4 -0
- package/dist/test/test_config.d.ts.map +1 -1
- package/dist/test/test_config.js +12 -4
- package/dist/test/test_config.js.map +1 -1
- package/package.json +6 -6
- package/src/core/client.ts +40 -21
- package/src/core/default_client.ts +1 -1
- package/src/core/driver.ts +1 -1
- package/src/core/errors.ts +14 -4
- package/src/core/ll_client.test.ts +9 -3
- package/src/core/ll_client.ts +81 -26
- package/src/core/unauth_client.test.ts +4 -4
- package/src/core/unauth_client.ts +7 -2
- package/src/core/websocket_stream.test.ts +19 -8
- package/src/core/websocket_stream.ts +173 -164
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +179 -1
- package/src/proto-rest/index.ts +17 -2
- package/src/test/test_config.ts +13 -4
- /package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.cjs +0 -0
- /package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.js +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LLPlClient } from './ll_client';
|
|
2
|
-
import { getTestConfig, getTestLLClient, getTestClientConf } from '../test/test_config';
|
|
2
|
+
import { getTestConfig, plAddressToTestConfig, getTestLLClient, getTestClientConf } from '../test/test_config';
|
|
3
3
|
import { TxAPI_Open_Request_WritableTx } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';
|
|
4
4
|
import { request } from 'undici';
|
|
5
5
|
import * as tp from 'node:timers/promises';
|
|
@@ -29,7 +29,7 @@ test('unauthenticated status change', async () => {
|
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const client =
|
|
32
|
+
const client = await LLPlClient.build(plAddressToTestConfig(cfg.address));
|
|
33
33
|
expect(client.status).toBe('OK');
|
|
34
34
|
|
|
35
35
|
const tx = client.createTx(true);
|
|
@@ -54,10 +54,16 @@ test('unauthenticated status change', async () => {
|
|
|
54
54
|
});
|
|
55
55
|
|
|
56
56
|
test('automatic token update', async () => {
|
|
57
|
+
const cfg = getTestConfig();
|
|
58
|
+
if (cfg.test_password === undefined) {
|
|
59
|
+
console.log("skipping test because target server doesn't support authentication");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
57
63
|
const { conf, auth } = await getTestClientConf();
|
|
58
64
|
conf.authMaxRefreshSeconds = 1;
|
|
59
65
|
let numberOfAuthUpdates = 0;
|
|
60
|
-
const client =
|
|
66
|
+
const client = await LLPlClient.build(conf, {
|
|
61
67
|
auth: {
|
|
62
68
|
authInformation: auth.authInformation,
|
|
63
69
|
onUpdate: (auth) => {
|
package/src/core/ll_client.ts
CHANGED
|
@@ -26,9 +26,10 @@ import type { WireClientProvider, WireClientProviderFactory, WireConnection } fr
|
|
|
26
26
|
import { parseHttpAuth } from '@milaboratories/pl-model-common';
|
|
27
27
|
import type * as grpcTypes from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';
|
|
28
28
|
import { type PlApiPaths, type PlRestClientType, createClient, parseResponseError } from '../proto-rest';
|
|
29
|
-
import { notEmpty } from '@milaboratories/ts-helpers';
|
|
29
|
+
import { notEmpty, retry, withTimeout, type RetryOptions } from '@milaboratories/ts-helpers';
|
|
30
30
|
import { Code } from '../proto-grpc/google/rpc/code';
|
|
31
31
|
import { WebSocketBiDiStream } from './websocket_stream';
|
|
32
|
+
import { TxAPI_ClientMessage, TxAPI_ServerMessage } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';
|
|
32
33
|
|
|
33
34
|
export interface PlCallOps {
|
|
34
35
|
timeout?: number;
|
|
@@ -53,8 +54,6 @@ class WireClientProviderImpl<Client> implements WireClientProvider<Client> {
|
|
|
53
54
|
|
|
54
55
|
/** Abstract out low level networking and authorization details */
|
|
55
56
|
export class LLPlClient implements WireClientProviderFactory {
|
|
56
|
-
public readonly conf: PlClientConfig;
|
|
57
|
-
|
|
58
57
|
/** Initial authorization information */
|
|
59
58
|
private authInformation?: AuthInformation;
|
|
60
59
|
/** Will be executed by the client when it is required */
|
|
@@ -69,7 +68,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
69
68
|
private _status: PlConnectionStatus = 'OK';
|
|
70
69
|
private readonly statusListener?: PlConnectionStatusListener;
|
|
71
70
|
|
|
72
|
-
private _wireProto: wireProtocol
|
|
71
|
+
private _wireProto: wireProtocol = 'grpc';
|
|
73
72
|
private _wireConn!: WireConnection;
|
|
74
73
|
|
|
75
74
|
private readonly _restInterceptors: Dispatcher.DispatcherComposeInterceptor[];
|
|
@@ -81,18 +80,29 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
81
80
|
|
|
82
81
|
public readonly httpDispatcher: Dispatcher;
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
public static async build(
|
|
85
84
|
configOrAddress: PlClientConfig | string,
|
|
86
|
-
|
|
85
|
+
ops: {
|
|
87
86
|
auth?: AuthOps;
|
|
88
87
|
statusListener?: PlConnectionStatusListener;
|
|
89
88
|
shouldUseGzip?: boolean;
|
|
90
89
|
} = {},
|
|
91
90
|
) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
const conf = typeof configOrAddress === 'string' ? plAddressToConfig(configOrAddress) : configOrAddress;
|
|
92
|
+
|
|
93
|
+
const pl = new LLPlClient(conf, ops);
|
|
94
|
+
await pl.detectOptimalWireProtocol();
|
|
95
|
+
return pl;
|
|
96
|
+
}
|
|
95
97
|
|
|
98
|
+
private constructor(
|
|
99
|
+
public readonly conf: PlClientConfig,
|
|
100
|
+
private readonly ops: {
|
|
101
|
+
auth?: AuthOps;
|
|
102
|
+
statusListener?: PlConnectionStatusListener;
|
|
103
|
+
shouldUseGzip?: boolean;
|
|
104
|
+
} = {},
|
|
105
|
+
) {
|
|
96
106
|
const { auth, statusListener } = ops;
|
|
97
107
|
|
|
98
108
|
if (auth !== undefined) {
|
|
@@ -119,8 +129,11 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
119
129
|
this._grpcInterceptors.push(this.createGrpcErrorInterceptor());
|
|
120
130
|
|
|
121
131
|
this.httpDispatcher = defaultHttpDispatcher(this.conf.httpProxy);
|
|
132
|
+
if (this.conf.wireProtocol) {
|
|
133
|
+
this._wireProto = this.conf.wireProtocol;
|
|
134
|
+
}
|
|
122
135
|
|
|
123
|
-
this.initWireConnection();
|
|
136
|
+
this.initWireConnection(this._wireProto);
|
|
124
137
|
|
|
125
138
|
if (statusListener !== undefined) {
|
|
126
139
|
this.statusListener = statusListener;
|
|
@@ -141,13 +154,8 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
141
154
|
});
|
|
142
155
|
}
|
|
143
156
|
|
|
144
|
-
private initWireConnection() {
|
|
145
|
-
|
|
146
|
-
// TODO: implement automatic server mode detection
|
|
147
|
-
this._wireProto = this.conf.wireProtocol ?? 'grpc';
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
switch (this._wireProto) {
|
|
157
|
+
private initWireConnection(protocol: wireProtocol) {
|
|
158
|
+
switch (protocol) {
|
|
151
159
|
case 'rest':
|
|
152
160
|
this.initRestConnection();
|
|
153
161
|
return;
|
|
@@ -157,12 +165,12 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
157
165
|
default:
|
|
158
166
|
((v: never) => {
|
|
159
167
|
throw new Error(`Unsupported wire protocol '${v as string}'. Use one of: ${SUPPORTED_WIRE_PROTOCOLS.join(', ')}`);
|
|
160
|
-
})(
|
|
168
|
+
})(protocol);
|
|
161
169
|
}
|
|
162
170
|
}
|
|
163
171
|
|
|
164
172
|
private initRestConnection(): void {
|
|
165
|
-
const dispatcher = defaultHttpDispatcher(this.conf.
|
|
173
|
+
const dispatcher = defaultHttpDispatcher(this.conf.grpcProxy, this._restInterceptors);
|
|
166
174
|
this._replaceWireConnection({ type: 'rest', Config: this.conf, Dispatcher: dispatcher, Middlewares: this._restMiddlewares });
|
|
167
175
|
}
|
|
168
176
|
|
|
@@ -220,6 +228,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
220
228
|
private _replaceWireConnection(newConn: WireConnection): void {
|
|
221
229
|
const oldConn = this._wireConn;
|
|
222
230
|
this._wireConn = newConn;
|
|
231
|
+
this._wireProto = newConn.type;
|
|
223
232
|
|
|
224
233
|
// Reset all providers to let them reinitialize their clients
|
|
225
234
|
for (let i = 0; i < this.providers.length; i++) {
|
|
@@ -268,6 +277,10 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
268
277
|
return this._wireConn;
|
|
269
278
|
}
|
|
270
279
|
|
|
280
|
+
public get wireProtocol(): wireProtocol | undefined {
|
|
281
|
+
return this._wireProto;
|
|
282
|
+
}
|
|
283
|
+
|
|
271
284
|
/** Returns true if client is authenticated. Even with anonymous auth information
|
|
272
285
|
* connection is considered authenticated. Unauthenticated clients are used for
|
|
273
286
|
* login and similar tasks, see {@link UnauthenticatedPlClient}. */
|
|
@@ -443,6 +456,32 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
443
456
|
}
|
|
444
457
|
}
|
|
445
458
|
|
|
459
|
+
/**
|
|
460
|
+
* Detects the best available wire protocol.
|
|
461
|
+
* If wireProtocol is explicitly configured, does nothing.
|
|
462
|
+
* Otherwise probes the current protocol via ping; if it fails, switches to the alternative.
|
|
463
|
+
*/
|
|
464
|
+
private async detectOptimalWireProtocol() {
|
|
465
|
+
if (this.conf.wireProtocol) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const retryOptions: RetryOptions = {
|
|
470
|
+
type: 'exponentialBackoff',
|
|
471
|
+
maxAttempts: 80,
|
|
472
|
+
initialDelay: 30,
|
|
473
|
+
backoffMultiplier: 1.3,
|
|
474
|
+
jitter: 0.2,
|
|
475
|
+
maxDelay: 500,
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
await retry(() => withTimeout(this.ping(), 500), retryOptions, () => {
|
|
479
|
+
const protocol = this._wireProto === 'grpc' ? 'rest' : 'grpc';
|
|
480
|
+
this.initWireConnection(protocol);
|
|
481
|
+
return true;
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
|
|
446
485
|
public async license(): Promise<grpcTypes.MaintenanceAPI_License_Response> {
|
|
447
486
|
const cl = this.clientProvider.get();
|
|
448
487
|
if (cl instanceof GrpcPlApiClient) {
|
|
@@ -490,22 +529,38 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
490
529
|
});
|
|
491
530
|
}
|
|
492
531
|
|
|
493
|
-
|
|
532
|
+
const wireConn = this.wireConnection;
|
|
533
|
+
if (wireConn.type === 'rest') {
|
|
494
534
|
// For REST/WebSocket protocol, timeout needs to be converted to AbortSignal
|
|
495
535
|
if (timeout !== undefined) {
|
|
496
536
|
totalAbortSignal = AbortSignal.any([totalAbortSignal, AbortSignal.timeout(timeout)]);
|
|
497
537
|
}
|
|
538
|
+
|
|
539
|
+
// The gRPC transport has the auth interceptor that already handles it, but here we need to refresh the auth information to be safe.
|
|
540
|
+
this.refreshAuthInformationIfNeeded();
|
|
541
|
+
|
|
498
542
|
const wsUrl = this.conf.ssl
|
|
499
543
|
? `wss://${this.conf.hostAndPort}/v1/ws/tx`
|
|
500
544
|
: `ws://${this.conf.hostAndPort}/v1/ws/tx`;
|
|
501
545
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
546
|
+
return new WebSocketBiDiStream(wsUrl,
|
|
547
|
+
(msg) => TxAPI_ClientMessage.toBinary(msg),
|
|
548
|
+
(data) => TxAPI_ServerMessage.fromBinary(new Uint8Array(data)),
|
|
549
|
+
{
|
|
550
|
+
abortSignal: totalAbortSignal,
|
|
551
|
+
jwtToken: this.authInformation?.jwtToken,
|
|
552
|
+
dispatcher: wireConn.Dispatcher,
|
|
553
|
+
|
|
554
|
+
onComplete: async (stream) => stream.requests.send({
|
|
555
|
+
// Ask server to gracefully close the stream on its side, if not done yet.
|
|
556
|
+
requestId: 0,
|
|
557
|
+
request: { oneofKind: 'streamClose', streamClose: {} },
|
|
558
|
+
}),
|
|
559
|
+
},
|
|
560
|
+
);
|
|
507
561
|
}
|
|
508
|
-
|
|
562
|
+
|
|
563
|
+
throw new Error(`transactions are not supported for wire protocol ${this._wireProto}`);
|
|
509
564
|
});
|
|
510
565
|
}
|
|
511
566
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { UnauthenticatedPlClient } from './unauth_client';
|
|
2
|
-
import { getTestConfig } from '../test/test_config';
|
|
2
|
+
import { getTestConfig, plAddressToTestConfig } from '../test/test_config';
|
|
3
3
|
import { UnauthenticatedError } from './errors';
|
|
4
4
|
import { test, expect } from 'vitest';
|
|
5
5
|
|
|
6
6
|
test('ping test', async () => {
|
|
7
|
-
const client =
|
|
7
|
+
const client = await UnauthenticatedPlClient.build(plAddressToTestConfig(getTestConfig().address));
|
|
8
8
|
const response = await client.ping();
|
|
9
9
|
expect(response).toHaveProperty('coreVersion');
|
|
10
10
|
});
|
|
11
11
|
|
|
12
12
|
test('get auth methods', async () => {
|
|
13
|
-
const client =
|
|
13
|
+
const client = await UnauthenticatedPlClient.build(plAddressToTestConfig(getTestConfig().address));
|
|
14
14
|
const response = await client.authMethods();
|
|
15
15
|
expect(response).toHaveProperty('methods');
|
|
16
16
|
});
|
|
@@ -21,7 +21,7 @@ test('wrong login', async () => {
|
|
|
21
21
|
console.log('skipped');
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
-
const client =
|
|
24
|
+
const client = await UnauthenticatedPlClient.build(plAddressToTestConfig(testConfig.address));
|
|
25
25
|
await expect(client.login(testConfig.test_user, testConfig.test_password + 'A')).rejects.toThrow(
|
|
26
26
|
UnauthenticatedError
|
|
27
27
|
);
|
|
@@ -11,8 +11,13 @@ import { UnauthenticatedError } from './errors';
|
|
|
11
11
|
export class UnauthenticatedPlClient {
|
|
12
12
|
public readonly ll: LLPlClient;
|
|
13
13
|
|
|
14
|
-
constructor(
|
|
15
|
-
this.ll =
|
|
14
|
+
private constructor(ll: LLPlClient) {
|
|
15
|
+
this.ll = ll;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
public static async build(configOrAddress: PlClientConfig | string): Promise<UnauthenticatedPlClient> {
|
|
19
|
+
const ll = await LLPlClient.build(configOrAddress);
|
|
20
|
+
return new UnauthenticatedPlClient(ll);
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
public async ping(): Promise<MaintenanceAPI_Ping_Response> {
|
|
@@ -82,7 +82,7 @@ import type { RetryConfig } from '../helpers/retry_strategy';
|
|
|
82
82
|
type MockWS = InstanceType<typeof MockWebSocket>;
|
|
83
83
|
|
|
84
84
|
interface StreamContext {
|
|
85
|
-
stream: WebSocketBiDiStream
|
|
85
|
+
stream: WebSocketBiDiStream<ClientMessageType, ServerMessageType>;
|
|
86
86
|
ws: MockWS;
|
|
87
87
|
controller: AbortController;
|
|
88
88
|
}
|
|
@@ -91,9 +91,13 @@ function createStream(token?: string, retryConfig?: Partial<RetryConfig>): Strea
|
|
|
91
91
|
const controller = new AbortController();
|
|
92
92
|
const stream = new WebSocketBiDiStream(
|
|
93
93
|
'ws://localhost:8080',
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
(message: ClientMessageType) => ClientMessageType.toBinary(message),
|
|
95
|
+
(data) => ServerMessageType.fromBinary(data),
|
|
96
|
+
{
|
|
97
|
+
abortSignal: controller.signal,
|
|
98
|
+
jwtToken: token,
|
|
99
|
+
retryConfig: retryConfig,
|
|
100
|
+
},
|
|
97
101
|
);
|
|
98
102
|
const ws = MockWebSocket.instances[MockWebSocket.instances.length - 1];
|
|
99
103
|
return { stream, ws, controller };
|
|
@@ -115,7 +119,7 @@ function createClientMessage(): ClientMessageType {
|
|
|
115
119
|
}
|
|
116
120
|
|
|
117
121
|
async function collectMessages(
|
|
118
|
-
stream: WebSocketBiDiStream,
|
|
122
|
+
stream: WebSocketBiDiStream<ClientMessageType, ServerMessageType>,
|
|
119
123
|
count: number,
|
|
120
124
|
): Promise<ServerMessageType[]> {
|
|
121
125
|
const messages: ServerMessageType[] = [];
|
|
@@ -149,7 +153,14 @@ describe('WebSocketBiDiStream', () => {
|
|
|
149
153
|
const controller = new AbortController();
|
|
150
154
|
controller.abort();
|
|
151
155
|
|
|
152
|
-
new WebSocketBiDiStream(
|
|
156
|
+
new WebSocketBiDiStream(
|
|
157
|
+
'ws://localhost:8080',
|
|
158
|
+
(message: ClientMessageType) => ClientMessageType.toBinary(message),
|
|
159
|
+
(data) => ServerMessageType.fromBinary(data),
|
|
160
|
+
{
|
|
161
|
+
abortSignal: controller.signal,
|
|
162
|
+
},
|
|
163
|
+
);
|
|
153
164
|
|
|
154
165
|
expect(MockWebSocket.instances).toHaveLength(0);
|
|
155
166
|
});
|
|
@@ -332,7 +343,7 @@ describe('WebSocketBiDiStream', () => {
|
|
|
332
343
|
maxAttempts: 5,
|
|
333
344
|
};
|
|
334
345
|
|
|
335
|
-
test('should attempt reconnection on unexpected close', async () => {
|
|
346
|
+
test('should not attempt reconnection on unexpected close', async () => {
|
|
336
347
|
const { ws } = createStream(undefined, retryConfig);
|
|
337
348
|
|
|
338
349
|
await openConnection(ws);
|
|
@@ -341,7 +352,7 @@ describe('WebSocketBiDiStream', () => {
|
|
|
341
352
|
ws.emit('close');
|
|
342
353
|
await vi.advanceTimersByTimeAsync(150);
|
|
343
354
|
|
|
344
|
-
expect(MockWebSocket.instances.length).
|
|
355
|
+
expect(MockWebSocket.instances.length).toBe(1);
|
|
345
356
|
});
|
|
346
357
|
|
|
347
358
|
test('should stop reconnecting after max attempts', async () => {
|