@milaboratories/pl-client 2.16.26 → 2.16.28
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 +2 -1
- package/dist/core/PromiseTracker.cjs +1 -3
- package/dist/core/PromiseTracker.cjs.map +1 -1
- package/dist/core/PromiseTracker.d.ts.map +1 -1
- package/dist/core/PromiseTracker.js +1 -3
- package/dist/core/PromiseTracker.js.map +1 -1
- package/dist/core/StatefulPromise.cjs +4 -4
- package/dist/core/StatefulPromise.cjs.map +1 -1
- package/dist/core/StatefulPromise.d.ts +1 -1
- package/dist/core/StatefulPromise.d.ts.map +1 -1
- package/dist/core/StatefulPromise.js +4 -4
- package/dist/core/StatefulPromise.js.map +1 -1
- package/dist/core/advisory_locks.cjs +1 -1
- package/dist/core/advisory_locks.cjs.map +1 -1
- package/dist/core/advisory_locks.js +1 -1
- package/dist/core/advisory_locks.js.map +1 -1
- package/dist/core/auth.cjs.map +1 -1
- package/dist/core/auth.d.ts +1 -1
- package/dist/core/auth.js.map +1 -1
- package/dist/core/cache.d.ts +1 -1
- package/dist/core/client.cjs +14 -14
- package/dist/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts +11 -11
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +14 -14
- package/dist/core/client.js.map +1 -1
- package/dist/core/config.cjs +39 -39
- package/dist/core/config.cjs.map +1 -1
- package/dist/core/config.d.ts +5 -5
- package/dist/core/config.js +39 -39
- package/dist/core/config.js.map +1 -1
- package/dist/core/default_client.cjs +23 -23
- package/dist/core/default_client.cjs.map +1 -1
- package/dist/core/default_client.d.ts +3 -3
- package/dist/core/default_client.js +23 -23
- 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.d.ts +5 -5
- package/dist/core/driver.js +1 -1
- package/dist/core/driver.js.map +1 -1
- package/dist/core/error_resource.cjs +2 -2
- package/dist/core/error_resource.cjs.map +1 -1
- package/dist/core/error_resource.d.ts +1 -1
- package/dist/core/error_resource.js +2 -2
- package/dist/core/error_resource.js.map +1 -1
- package/dist/core/errors.cjs +24 -24
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +24 -24
- package/dist/core/errors.js.map +1 -1
- package/dist/core/final.cjs +43 -43
- package/dist/core/final.cjs.map +1 -1
- package/dist/core/final.d.ts +3 -3
- package/dist/core/final.d.ts.map +1 -1
- package/dist/core/final.js +43 -43
- package/dist/core/final.js.map +1 -1
- package/dist/core/ll_client.cjs +50 -43
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +9 -9
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +50 -43
- package/dist/core/ll_client.js.map +1 -1
- package/dist/core/ll_transaction.cjs +9 -9
- package/dist/core/ll_transaction.cjs.map +1 -1
- package/dist/core/ll_transaction.d.ts +7 -7
- package/dist/core/ll_transaction.d.ts.map +1 -1
- package/dist/core/ll_transaction.js +9 -9
- package/dist/core/ll_transaction.js.map +1 -1
- package/dist/core/stat.cjs.map +1 -1
- package/dist/core/stat.d.ts +1 -1
- package/dist/core/stat.js.map +1 -1
- package/dist/core/transaction.cjs +46 -46
- package/dist/core/transaction.cjs.map +1 -1
- package/dist/core/transaction.d.ts +7 -7
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +46 -46
- package/dist/core/transaction.js.map +1 -1
- package/dist/core/type_conversion.cjs +22 -22
- package/dist/core/type_conversion.cjs.map +1 -1
- package/dist/core/type_conversion.d.ts +3 -3
- package/dist/core/type_conversion.d.ts.map +1 -1
- package/dist/core/type_conversion.js +22 -22
- package/dist/core/type_conversion.js.map +1 -1
- package/dist/core/types.cjs +25 -25
- package/dist/core/types.cjs.map +1 -1
- package/dist/core/types.d.ts +7 -7
- package/dist/core/types.js +25 -25
- package/dist/core/types.js.map +1 -1
- package/dist/core/unauth_client.cjs +6 -4
- package/dist/core/unauth_client.cjs.map +1 -1
- package/dist/core/unauth_client.d.ts +4 -4
- package/dist/core/unauth_client.d.ts.map +1 -1
- package/dist/core/unauth_client.js +6 -4
- package/dist/core/unauth_client.js.map +1 -1
- package/dist/core/websocket_stream.cjs +22 -20
- package/dist/core/websocket_stream.cjs.map +1 -1
- package/dist/core/websocket_stream.d.ts +3 -3
- package/dist/core/websocket_stream.d.ts.map +1 -1
- package/dist/core/websocket_stream.js +22 -20
- package/dist/core/websocket_stream.js.map +1 -1
- package/dist/core/wire.d.ts +6 -6
- package/dist/core/wire.d.ts.map +1 -1
- package/dist/helpers/pl.cjs +19 -19
- package/dist/helpers/pl.cjs.map +1 -1
- package/dist/helpers/pl.d.ts +2 -2
- package/dist/helpers/pl.js +19 -19
- package/dist/helpers/pl.js.map +1 -1
- package/dist/helpers/poll.cjs +6 -6
- package/dist/helpers/poll.cjs.map +1 -1
- package/dist/helpers/poll.d.ts +4 -4
- package/dist/helpers/poll.d.ts.map +1 -1
- package/dist/helpers/poll.js +6 -6
- package/dist/helpers/poll.js.map +1 -1
- package/dist/helpers/retry_strategy.cjs +1 -1
- package/dist/helpers/retry_strategy.cjs.map +1 -1
- package/dist/helpers/retry_strategy.d.ts.map +1 -1
- package/dist/helpers/retry_strategy.js +1 -1
- package/dist/helpers/retry_strategy.js.map +1 -1
- package/dist/helpers/state_helpers.d.ts +2 -2
- package/dist/helpers/tx_helpers.cjs +2 -2
- package/dist/helpers/tx_helpers.cjs.map +1 -1
- package/dist/helpers/tx_helpers.d.ts +2 -2
- package/dist/helpers/tx_helpers.d.ts.map +1 -1
- package/dist/helpers/tx_helpers.js +2 -2
- package/dist/helpers/tx_helpers.js.map +1 -1
- package/dist/index.d.ts +16 -16
- package/dist/proto-grpc/google/protobuf/struct.d.ts +1 -1
- package/dist/proto-grpc/google/protobuf/struct.d.ts.map +1 -1
- package/dist/proto-rest/index.cjs +4 -5
- package/dist/proto-rest/index.cjs.map +1 -1
- package/dist/proto-rest/index.d.ts +4 -4
- package/dist/proto-rest/index.d.ts.map +1 -1
- package/dist/proto-rest/index.js +4 -5
- package/dist/proto-rest/index.js.map +1 -1
- package/dist/proto-rest/plapi.d.ts.map +1 -1
- package/dist/test/tcp-proxy.cjs +11 -10
- package/dist/test/tcp-proxy.cjs.map +1 -1
- package/dist/test/tcp-proxy.d.ts +1 -1
- package/dist/test/tcp-proxy.d.ts.map +1 -1
- package/dist/test/tcp-proxy.js +11 -10
- package/dist/test/tcp-proxy.js.map +1 -1
- package/dist/test/test_config.cjs +21 -17
- package/dist/test/test_config.cjs.map +1 -1
- package/dist/test/test_config.d.ts +6 -6
- package/dist/test/test_config.d.ts.map +1 -1
- package/dist/test/test_config.js +21 -17
- package/dist/test/test_config.js.map +1 -1
- package/dist/util/pl.cjs +1 -1
- package/dist/util/pl.cjs.map +1 -1
- package/dist/util/pl.js +1 -1
- package/dist/util/pl.js.map +1 -1
- package/dist/util/util.cjs +1 -1
- package/dist/util/util.cjs.map +1 -1
- package/dist/util/util.js +1 -1
- package/dist/util/util.js.map +1 -1
- package/package.json +23 -23
- package/src/core/PromiseTracker.ts +3 -4
- package/src/core/StatefulPromise.ts +17 -8
- package/src/core/abstract_stream.ts +3 -4
- package/src/core/advisory_locks.ts +1 -1
- package/src/core/auth.ts +2 -2
- package/src/core/cache.ts +1 -1
- package/src/core/client.test.ts +25 -21
- package/src/core/client.ts +54 -45
- package/src/core/config.test.ts +44 -44
- package/src/core/config.ts +49 -49
- package/src/core/connectivity.test.ts +69 -63
- package/src/core/default_client.ts +46 -46
- package/src/core/driver.ts +6 -6
- package/src/core/error.test.ts +5 -5
- package/src/core/error_resource.ts +3 -3
- package/src/core/errors.ts +39 -31
- package/src/core/final.ts +48 -55
- package/src/core/ll_client.test.ts +53 -36
- package/src/core/ll_client.ts +125 -81
- package/src/core/ll_transaction.test.ts +75 -49
- package/src/core/ll_transaction.ts +37 -35
- package/src/core/stat.ts +1 -1
- package/src/core/transaction.test.ts +65 -65
- package/src/core/transaction.ts +91 -84
- package/src/core/type_conversion.ts +30 -31
- package/src/core/types.test.ts +6 -6
- package/src/core/types.ts +35 -35
- package/src/core/unauth_client.test.ts +18 -14
- package/src/core/unauth_client.ts +14 -12
- package/src/core/websocket_stream.test.ts +52 -52
- package/src/core/websocket_stream.ts +41 -37
- package/src/core/wire.ts +10 -8
- package/src/helpers/pl.ts +22 -22
- package/src/helpers/poll.ts +13 -27
- package/src/helpers/retry_strategy.ts +2 -4
- package/src/helpers/rich_resource_types.test.ts +2 -2
- package/src/helpers/state_helpers.ts +3 -3
- package/src/helpers/tx_helpers.ts +9 -7
- package/src/index.ts +16 -16
- package/src/proto-grpc/google/protobuf/struct.ts +1 -1
- package/src/proto-rest/index.ts +17 -18
- package/src/proto-rest/plapi.ts +1472 -1472
- package/src/test/tcp-proxy.ts +55 -54
- package/src/test/test_config.test.ts +3 -3
- package/src/test/test_config.ts +51 -46
- package/src/util/pl.ts +1 -1
- package/src/util/util.test.ts +5 -5
- package/src/util/util.ts +1 -1
- package/dist/helpers/rich_resource_types.d.ts +0 -2
- package/dist/helpers/rich_resource_types.d.ts.map +0 -1
- package/dist/helpers/smart_accessors.d.ts +0 -2
- package/dist/helpers/smart_accessors.d.ts.map +0 -1
- package/src/helpers/rich_resource_types.ts +0 -84
- package/src/helpers/smart_accessors.ts +0 -146
package/src/core/ll_client.ts
CHANGED
|
@@ -1,37 +1,45 @@
|
|
|
1
|
-
import { PlatformClient as GrpcPlApiClient } from
|
|
2
|
-
import type { ClientOptions, Interceptor } from
|
|
1
|
+
import { PlatformClient as GrpcPlApiClient } from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client";
|
|
2
|
+
import type { ClientOptions, Interceptor } from "@grpc/grpc-js";
|
|
3
3
|
import {
|
|
4
4
|
ChannelCredentials,
|
|
5
5
|
InterceptingCall,
|
|
6
6
|
status as GrpcStatus,
|
|
7
7
|
compressionAlgorithms,
|
|
8
|
-
} from
|
|
8
|
+
} from "@grpc/grpc-js";
|
|
9
9
|
import type {
|
|
10
10
|
AuthInformation,
|
|
11
11
|
AuthOps,
|
|
12
12
|
PlClientConfig,
|
|
13
13
|
PlConnectionStatus,
|
|
14
14
|
PlConnectionStatusListener,
|
|
15
|
-
} from
|
|
16
|
-
import { plAddressToConfig, type wireProtocol, SUPPORTED_WIRE_PROTOCOLS } from
|
|
17
|
-
import type { GrpcOptions } from
|
|
18
|
-
import { GrpcTransport } from
|
|
19
|
-
import { LLPlTransaction } from
|
|
20
|
-
import { parsePlJwt } from
|
|
21
|
-
import { type Dispatcher, interceptors } from
|
|
22
|
-
import type { Middleware } from
|
|
23
|
-
import { inferAuthRefreshTime } from
|
|
24
|
-
import { defaultHttpDispatcher } from
|
|
25
|
-
import type { WireClientProvider, WireClientProviderFactory, WireConnection } from
|
|
26
|
-
import { parseHttpAuth } from
|
|
27
|
-
import type * as grpcTypes from
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
import {
|
|
15
|
+
} from "./config";
|
|
16
|
+
import { plAddressToConfig, type wireProtocol, SUPPORTED_WIRE_PROTOCOLS } from "./config";
|
|
17
|
+
import type { GrpcOptions } from "@protobuf-ts/grpc-transport";
|
|
18
|
+
import { GrpcTransport } from "@protobuf-ts/grpc-transport";
|
|
19
|
+
import { LLPlTransaction } from "./ll_transaction";
|
|
20
|
+
import { parsePlJwt } from "../util/pl";
|
|
21
|
+
import { type Dispatcher, interceptors } from "undici";
|
|
22
|
+
import type { Middleware } from "openapi-fetch";
|
|
23
|
+
import { inferAuthRefreshTime } from "./auth";
|
|
24
|
+
import { defaultHttpDispatcher } from "@milaboratories/pl-http";
|
|
25
|
+
import type { WireClientProvider, WireClientProviderFactory, WireConnection } from "./wire";
|
|
26
|
+
import { parseHttpAuth } from "@milaboratories/pl-model-common";
|
|
27
|
+
import type * as grpcTypes from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api";
|
|
28
|
+
import {
|
|
29
|
+
type PlApiPaths,
|
|
30
|
+
type PlRestClientType,
|
|
31
|
+
createClient,
|
|
32
|
+
parseResponseError,
|
|
33
|
+
} from "../proto-rest";
|
|
34
|
+
import { notEmpty, retry, withTimeout, type RetryOptions } from "@milaboratories/ts-helpers";
|
|
35
|
+
import { Code } from "../proto-grpc/google/rpc/code";
|
|
36
|
+
import { WebSocketBiDiStream } from "./websocket_stream";
|
|
37
|
+
import {
|
|
38
|
+
TxAPI_ClientMessage,
|
|
39
|
+
TxAPI_ServerMessage,
|
|
40
|
+
} from "../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api";
|
|
41
|
+
import type { MiLogger } from "@milaboratories/ts-helpers";
|
|
42
|
+
import { isAbortedError } from "./errors";
|
|
35
43
|
|
|
36
44
|
export interface PlCallOps {
|
|
37
45
|
timeout?: number;
|
|
@@ -41,15 +49,17 @@ export interface PlCallOps {
|
|
|
41
49
|
class WireClientProviderImpl<Client> implements WireClientProvider<Client> {
|
|
42
50
|
private client: Client | undefined = undefined;
|
|
43
51
|
|
|
44
|
-
constructor(
|
|
52
|
+
constructor(
|
|
53
|
+
private readonly wireOpts: () => WireConnection,
|
|
54
|
+
private readonly clientConstructor: (wireOpts: WireConnection) => Client,
|
|
55
|
+
) {}
|
|
45
56
|
|
|
46
57
|
public reset(): void {
|
|
47
58
|
this.client = undefined;
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
public get(): Client {
|
|
51
|
-
if (this.client === undefined)
|
|
52
|
-
this.client = this.clientConstructor(this.wireOpts());
|
|
62
|
+
if (this.client === undefined) this.client = this.clientConstructor(this.wireOpts());
|
|
53
63
|
return this.client;
|
|
54
64
|
}
|
|
55
65
|
}
|
|
@@ -67,10 +77,10 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
67
77
|
/** Threshold after which auth info refresh is required */
|
|
68
78
|
private refreshTimestamp?: number;
|
|
69
79
|
|
|
70
|
-
private _status: PlConnectionStatus =
|
|
80
|
+
private _status: PlConnectionStatus = "OK";
|
|
71
81
|
private readonly statusListener?: PlConnectionStatusListener;
|
|
72
82
|
|
|
73
|
-
private _wireProto: wireProtocol =
|
|
83
|
+
private _wireProto: wireProtocol = "grpc";
|
|
74
84
|
private _wireConn!: WireConnection;
|
|
75
85
|
|
|
76
86
|
private readonly _restInterceptors: Dispatcher.DispatcherComposeInterceptor[];
|
|
@@ -92,7 +102,8 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
92
102
|
useAutoDetectWireProtocol?: boolean;
|
|
93
103
|
} = {},
|
|
94
104
|
) {
|
|
95
|
-
const conf =
|
|
105
|
+
const conf =
|
|
106
|
+
typeof configOrAddress === "string" ? plAddressToConfig(configOrAddress) : configOrAddress;
|
|
96
107
|
|
|
97
108
|
const pl = new LLPlClient(conf, ops);
|
|
98
109
|
|
|
@@ -150,7 +161,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
150
161
|
}
|
|
151
162
|
|
|
152
163
|
this.clientProvider = this.createWireClientProvider((wireConn) => {
|
|
153
|
-
if (wireConn.type ===
|
|
164
|
+
if (wireConn.type === "grpc") {
|
|
154
165
|
return new GrpcPlApiClient(wireConn.Transport);
|
|
155
166
|
} else {
|
|
156
167
|
return createClient<PlApiPaths>({
|
|
@@ -165,22 +176,29 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
165
176
|
|
|
166
177
|
private initWireConnection(protocol: wireProtocol) {
|
|
167
178
|
switch (protocol) {
|
|
168
|
-
case
|
|
179
|
+
case "rest":
|
|
169
180
|
this.initRestConnection();
|
|
170
181
|
return;
|
|
171
|
-
case
|
|
182
|
+
case "grpc":
|
|
172
183
|
this.initGrpcConnection(this.ops.shouldUseGzip ?? false);
|
|
173
184
|
return;
|
|
174
185
|
default:
|
|
175
186
|
((v: never) => {
|
|
176
|
-
throw new Error(
|
|
187
|
+
throw new Error(
|
|
188
|
+
`Unsupported wire protocol '${v as string}'. Use one of: ${SUPPORTED_WIRE_PROTOCOLS.join(", ")}`,
|
|
189
|
+
);
|
|
177
190
|
})(protocol);
|
|
178
191
|
}
|
|
179
192
|
}
|
|
180
193
|
|
|
181
194
|
private initRestConnection(): void {
|
|
182
195
|
const dispatcher = defaultHttpDispatcher(this.conf.grpcProxy, this._restInterceptors);
|
|
183
|
-
this._replaceWireConnection({
|
|
196
|
+
this._replaceWireConnection({
|
|
197
|
+
type: "rest",
|
|
198
|
+
Config: this.conf,
|
|
199
|
+
Dispatcher: dispatcher,
|
|
200
|
+
Middlewares: this._restMiddlewares,
|
|
201
|
+
});
|
|
184
202
|
}
|
|
185
203
|
|
|
186
204
|
/**
|
|
@@ -189,12 +207,12 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
189
207
|
*/
|
|
190
208
|
private initGrpcConnection(gzip: boolean) {
|
|
191
209
|
const clientOptions: ClientOptions = {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
210
|
+
"grpc.keepalive_time_ms": 30_000, // 30 seconds
|
|
211
|
+
"grpc.service_config_disable_resolution": 1, // Disable DNS TXT lookups for service config
|
|
212
|
+
interceptors: this._grpcInterceptors,
|
|
195
213
|
};
|
|
196
214
|
|
|
197
|
-
if (gzip) clientOptions[
|
|
215
|
+
if (gzip) clientOptions["grpc.default_compression_algorithm"] = compressionAlgorithms.gzip;
|
|
198
216
|
|
|
199
217
|
//
|
|
200
218
|
// Leaving it here for now
|
|
@@ -212,15 +230,14 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
212
230
|
clientOptions,
|
|
213
231
|
};
|
|
214
232
|
|
|
215
|
-
const grpcProxy =
|
|
216
|
-
? { url: this.conf.grpcProxy }
|
|
217
|
-
: this.conf.grpcProxy;
|
|
233
|
+
const grpcProxy =
|
|
234
|
+
typeof this.conf.grpcProxy === "string" ? { url: this.conf.grpcProxy } : this.conf.grpcProxy;
|
|
218
235
|
|
|
219
236
|
if (grpcProxy?.url) {
|
|
220
237
|
const url = new URL(grpcProxy.url);
|
|
221
238
|
if (grpcProxy.auth) {
|
|
222
239
|
const parsed = parseHttpAuth(grpcProxy.auth);
|
|
223
|
-
if (parsed.scheme !==
|
|
240
|
+
if (parsed.scheme !== "Basic") {
|
|
224
241
|
throw new Error(`Unsupported auth scheme: ${parsed.scheme as string}.`);
|
|
225
242
|
}
|
|
226
243
|
url.username = parsed.username;
|
|
@@ -231,7 +248,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
231
248
|
delete process.env.grpc_proxy;
|
|
232
249
|
}
|
|
233
250
|
|
|
234
|
-
this._replaceWireConnection({ type:
|
|
251
|
+
this._replaceWireConnection({ type: "grpc", Transport: new GrpcTransport(grpcOptions) });
|
|
235
252
|
}
|
|
236
253
|
|
|
237
254
|
private _replaceWireConnection(newConn: WireConnection): void {
|
|
@@ -251,7 +268,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
251
268
|
}
|
|
252
269
|
}
|
|
253
270
|
|
|
254
|
-
if (oldConn !== undefined && oldConn.type ===
|
|
271
|
+
if (oldConn !== undefined && oldConn.type === "grpc") oldConn.Transport.close();
|
|
255
272
|
}
|
|
256
273
|
|
|
257
274
|
private providerCleanupCounter = 0;
|
|
@@ -261,7 +278,9 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
261
278
|
*
|
|
262
279
|
* @param clientConstructor - a factory function that creates a grpc client
|
|
263
280
|
*/
|
|
264
|
-
public createWireClientProvider<Client>(
|
|
281
|
+
public createWireClientProvider<Client>(
|
|
282
|
+
clientConstructor: (transport: WireConnection) => Client,
|
|
283
|
+
): WireClientProvider<Client> {
|
|
265
284
|
// We need to cleanup providers periodically to avoid memory leaks.
|
|
266
285
|
// This is a simple heuristic to avoid memory leaks.
|
|
267
286
|
// We could use a more sophisticated algorithm, but this is good enough for now.
|
|
@@ -299,7 +318,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
299
318
|
|
|
300
319
|
/** null means anonymous connection */
|
|
301
320
|
public get authUser(): string | null {
|
|
302
|
-
if (!this.authenticated) throw new Error(
|
|
321
|
+
if (!this.authenticated) throw new Error("Client is not authenticated");
|
|
303
322
|
if (this.authInformation?.jwtToken)
|
|
304
323
|
return parsePlJwt(this.authInformation?.jwtToken).user.login;
|
|
305
324
|
else return null;
|
|
@@ -323,10 +342,10 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
323
342
|
|
|
324
343
|
private refreshAuthInformationIfNeeded(): void {
|
|
325
344
|
if (
|
|
326
|
-
this.refreshTimestamp === undefined
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
345
|
+
this.refreshTimestamp === undefined ||
|
|
346
|
+
Date.now() < this.refreshTimestamp ||
|
|
347
|
+
this.authRefreshInProgress ||
|
|
348
|
+
this._status === "Unauthenticated"
|
|
330
349
|
)
|
|
331
350
|
return;
|
|
332
351
|
|
|
@@ -357,11 +376,11 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
357
376
|
private createRestErrorMiddleware(): Middleware {
|
|
358
377
|
return {
|
|
359
378
|
onResponse: async ({ request: _request, response, options: _options }) => {
|
|
360
|
-
const { body
|
|
379
|
+
const { body, ...resOptions } = response;
|
|
361
380
|
|
|
362
381
|
if ([502, 503, 504].includes(response.status)) {
|
|
363
382
|
// Service unavailable, bad gateway, gateway timeout
|
|
364
|
-
this.updateStatus(
|
|
383
|
+
this.updateStatus("Disconnected");
|
|
365
384
|
return new Response(body, { ...resOptions, status: response.status });
|
|
366
385
|
}
|
|
367
386
|
|
|
@@ -371,13 +390,13 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
371
390
|
return new Response(respErr.origBody ?? body, { ...resOptions, status: response.status });
|
|
372
391
|
}
|
|
373
392
|
|
|
374
|
-
if (typeof respErr.error ===
|
|
393
|
+
if (typeof respErr.error === "string") {
|
|
375
394
|
// Non-standard error or normal response: let later middleware to deal wit it.
|
|
376
395
|
return new Response(respErr.error, { ...resOptions, status: response.status });
|
|
377
396
|
}
|
|
378
397
|
|
|
379
398
|
if (respErr.error.code === Code.UNAUTHENTICATED) {
|
|
380
|
-
this.updateStatus(
|
|
399
|
+
this.updateStatus("Unauthenticated");
|
|
381
400
|
}
|
|
382
401
|
|
|
383
402
|
// Let later middleware to deal with standard gRPC error.
|
|
@@ -395,10 +414,10 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
395
414
|
onReceiveStatus: (status, next) => {
|
|
396
415
|
if (status.code == GrpcStatus.UNAUTHENTICATED)
|
|
397
416
|
// (!!!) don't change to "==="
|
|
398
|
-
this.updateStatus(
|
|
417
|
+
this.updateStatus("Unauthenticated");
|
|
399
418
|
if (status.code == GrpcStatus.UNAVAILABLE)
|
|
400
419
|
// (!!!) don't change to "==="
|
|
401
|
-
this.updateStatus(
|
|
420
|
+
this.updateStatus("Disconnected");
|
|
402
421
|
next(status);
|
|
403
422
|
},
|
|
404
423
|
});
|
|
@@ -412,7 +431,10 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
412
431
|
return (options, handler) => {
|
|
413
432
|
if (this.authInformation?.jwtToken !== undefined) {
|
|
414
433
|
// TODO: check this magic really works and gets called
|
|
415
|
-
options.headers = {
|
|
434
|
+
options.headers = {
|
|
435
|
+
...options.headers,
|
|
436
|
+
authorization: "Bearer " + this.authInformation.jwtToken,
|
|
437
|
+
};
|
|
416
438
|
this.refreshAuthInformationIfNeeded();
|
|
417
439
|
}
|
|
418
440
|
|
|
@@ -427,7 +449,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
427
449
|
return new InterceptingCall(nextCall(options), {
|
|
428
450
|
start: (metadata, listener, next) => {
|
|
429
451
|
if (this.authInformation?.jwtToken !== undefined) {
|
|
430
|
-
metadata.set(
|
|
452
|
+
metadata.set("authorization", "Bearer " + this.authInformation.jwtToken);
|
|
431
453
|
this.refreshAuthInformationIfNeeded();
|
|
432
454
|
next(metadata, listener);
|
|
433
455
|
} else {
|
|
@@ -438,21 +460,26 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
438
460
|
};
|
|
439
461
|
}
|
|
440
462
|
|
|
441
|
-
public async getJwtToken(
|
|
463
|
+
public async getJwtToken(
|
|
464
|
+
ttlSeconds: bigint,
|
|
465
|
+
options?: { authorization?: string },
|
|
466
|
+
): Promise<string> {
|
|
442
467
|
const cl = this.clientProvider.get();
|
|
443
468
|
|
|
444
469
|
if (cl instanceof GrpcPlApiClient) {
|
|
445
470
|
const meta: Record<string, string> = {};
|
|
446
471
|
if (options?.authorization) meta.authorization = options.authorization;
|
|
447
|
-
return (
|
|
472
|
+
return (
|
|
473
|
+
await cl.getJWTToken({ expiration: { seconds: ttlSeconds, nanos: 0 } }, { meta }).response
|
|
474
|
+
).token;
|
|
448
475
|
} else {
|
|
449
476
|
const headers: Record<string, string> = {};
|
|
450
477
|
if (options?.authorization) headers.authorization = options.authorization;
|
|
451
|
-
const resp = cl.POST(
|
|
478
|
+
const resp = cl.POST("/v1/auth/jwt-token", {
|
|
452
479
|
body: { expiration: `${ttlSeconds}s` },
|
|
453
480
|
headers,
|
|
454
481
|
});
|
|
455
|
-
return notEmpty((await resp).data,
|
|
482
|
+
return notEmpty((await resp).data, "REST: empty response for JWT token request").token;
|
|
456
483
|
}
|
|
457
484
|
}
|
|
458
485
|
|
|
@@ -461,7 +488,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
461
488
|
if (cl instanceof GrpcPlApiClient) {
|
|
462
489
|
return (await cl.ping({})).response;
|
|
463
490
|
} else {
|
|
464
|
-
return notEmpty((await cl.GET(
|
|
491
|
+
return notEmpty((await cl.GET("/v1/ping")).data, "REST: empty response for ping request");
|
|
465
492
|
}
|
|
466
493
|
}
|
|
467
494
|
|
|
@@ -485,7 +512,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
485
512
|
const pingTimeoutFactor = 1.3;
|
|
486
513
|
const maxPingTimeoutMs = 3_000;
|
|
487
514
|
const retryOptions: RetryOptions = {
|
|
488
|
-
type:
|
|
515
|
+
type: "exponentialBackoff",
|
|
489
516
|
maxAttempts: 30,
|
|
490
517
|
initialDelay: 30,
|
|
491
518
|
backoffMultiplier: 1.3,
|
|
@@ -500,7 +527,9 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
500
527
|
retryOptions,
|
|
501
528
|
(e: unknown) => {
|
|
502
529
|
if (isAbortedError(e)) {
|
|
503
|
-
this.ops.logger?.info(
|
|
530
|
+
this.ops.logger?.info(
|
|
531
|
+
`Wire proto autodetect: ping timed out after ${pingTimeoutMs}ms: attempt=${attempt}, wire=${this._wireProto}`,
|
|
532
|
+
);
|
|
504
533
|
|
|
505
534
|
if (attempt % 2 === 0) {
|
|
506
535
|
// We have 2 wire protocols to check. Increase timeout each 2 attempts.
|
|
@@ -510,15 +539,20 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
510
539
|
);
|
|
511
540
|
}
|
|
512
541
|
} else {
|
|
513
|
-
this.ops.logger?.info(
|
|
542
|
+
this.ops.logger?.info(
|
|
543
|
+
`Wire proto autodetect: ping failed: attempt=${attempt}, wire=${this._wireProto}, err=${String(e)}`,
|
|
544
|
+
);
|
|
514
545
|
}
|
|
515
546
|
|
|
516
547
|
attempt++;
|
|
517
|
-
const protocol = this._wireProto ===
|
|
518
|
-
this.ops.logger?.info(
|
|
548
|
+
const protocol = this._wireProto === "grpc" ? "rest" : "grpc";
|
|
549
|
+
this.ops.logger?.info(
|
|
550
|
+
`Wire protocol autodetect next attempt: will try wire '${protocol}' with timeout ${pingTimeoutMs}ms`,
|
|
551
|
+
);
|
|
519
552
|
this.initWireConnection(protocol);
|
|
520
553
|
return true;
|
|
521
|
-
}
|
|
554
|
+
},
|
|
555
|
+
);
|
|
522
556
|
}
|
|
523
557
|
|
|
524
558
|
public async license(): Promise<grpcTypes.MaintenanceAPI_License_Response> {
|
|
@@ -526,7 +560,10 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
526
560
|
if (cl instanceof GrpcPlApiClient) {
|
|
527
561
|
return (await cl.license({})).response;
|
|
528
562
|
} else {
|
|
529
|
-
const resp = notEmpty(
|
|
563
|
+
const resp = notEmpty(
|
|
564
|
+
(await cl.GET("/v1/license")).data,
|
|
565
|
+
"REST: empty response for license request",
|
|
566
|
+
);
|
|
530
567
|
return {
|
|
531
568
|
status: resp.status,
|
|
532
569
|
isOk: resp.isOk,
|
|
@@ -540,7 +577,10 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
540
577
|
if (cl instanceof GrpcPlApiClient) {
|
|
541
578
|
return (await cl.authMethods({})).response;
|
|
542
579
|
} else {
|
|
543
|
-
return notEmpty(
|
|
580
|
+
return notEmpty(
|
|
581
|
+
(await cl.GET("/v1/auth/methods")).data,
|
|
582
|
+
"REST: empty response for auth methods request",
|
|
583
|
+
);
|
|
544
584
|
}
|
|
545
585
|
}
|
|
546
586
|
|
|
@@ -549,7 +589,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
549
589
|
if (cl instanceof GrpcPlApiClient) {
|
|
550
590
|
await cl.txSync({ txId: BigInt(txId) });
|
|
551
591
|
} else {
|
|
552
|
-
|
|
592
|
+
await cl.POST("/v1/tx-sync", { body: { txId: txId.toString() } });
|
|
553
593
|
}
|
|
554
594
|
}
|
|
555
595
|
|
|
@@ -558,7 +598,9 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
558
598
|
let totalAbortSignal = abortSignal;
|
|
559
599
|
if (ops.abortSignal) totalAbortSignal = AbortSignal.any([totalAbortSignal, ops.abortSignal]);
|
|
560
600
|
|
|
561
|
-
const timeout =
|
|
601
|
+
const timeout =
|
|
602
|
+
ops.timeout ??
|
|
603
|
+
(rw ? this.conf.defaultRWTransactionTimeout : this.conf.defaultROTransactionTimeout);
|
|
562
604
|
|
|
563
605
|
const cl = this.clientProvider.get();
|
|
564
606
|
if (cl instanceof GrpcPlApiClient) {
|
|
@@ -569,7 +611,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
569
611
|
}
|
|
570
612
|
|
|
571
613
|
const wireConn = this.wireConnection;
|
|
572
|
-
if (wireConn.type ===
|
|
614
|
+
if (wireConn.type === "rest") {
|
|
573
615
|
// For REST/WebSocket protocol, timeout needs to be converted to AbortSignal
|
|
574
616
|
if (timeout !== undefined) {
|
|
575
617
|
totalAbortSignal = AbortSignal.any([totalAbortSignal, AbortSignal.timeout(timeout)]);
|
|
@@ -582,7 +624,8 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
582
624
|
? `wss://${this.conf.hostAndPort}/v1/ws/tx`
|
|
583
625
|
: `ws://${this.conf.hostAndPort}/v1/ws/tx`;
|
|
584
626
|
|
|
585
|
-
return new WebSocketBiDiStream(
|
|
627
|
+
return new WebSocketBiDiStream(
|
|
628
|
+
wsUrl,
|
|
586
629
|
(msg) => TxAPI_ClientMessage.toBinary(msg),
|
|
587
630
|
(data) => TxAPI_ServerMessage.fromBinary(new Uint8Array(data)),
|
|
588
631
|
{
|
|
@@ -590,11 +633,12 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
590
633
|
jwtToken: this.authInformation?.jwtToken,
|
|
591
634
|
dispatcher: wireConn.Dispatcher,
|
|
592
635
|
|
|
593
|
-
onComplete: async (stream) =>
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
636
|
+
onComplete: async (stream) =>
|
|
637
|
+
stream.requests.send({
|
|
638
|
+
// Ask server to gracefully close the stream on its side, if not done yet.
|
|
639
|
+
requestId: 0,
|
|
640
|
+
request: { oneofKind: "streamClose", streamClose: {} },
|
|
641
|
+
}),
|
|
598
642
|
},
|
|
599
643
|
);
|
|
600
644
|
}
|
|
@@ -605,7 +649,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
605
649
|
|
|
606
650
|
/** Closes underlying transport */
|
|
607
651
|
public async close() {
|
|
608
|
-
if (this.wireConnection.type ===
|
|
652
|
+
if (this.wireConnection.type === "grpc") {
|
|
609
653
|
this.wireConnection.Transport.close();
|
|
610
654
|
} else {
|
|
611
655
|
// TODO: close all WS connections
|