@fireproof/core-protocols-cloud 0.22.0-keybag → 0.23.1-dev-issue-1057
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/LICENSE.md +197 -228
- package/README.md +269 -0
- package/http-connection.d.ts +1 -1
- package/http-connection.js.map +1 -1
- package/index.js.map +1 -1
- package/msg-raw-connection-base.js.map +1 -1
- package/msger.js +5 -0
- package/msger.js.map +1 -1
- package/package.json +7 -7
- package/ws-connection.js.map +1 -1
- package/http-connection.ts +0 -204
- package/index.ts +0 -4
- package/msg-raw-connection-base.ts +0 -38
- package/msger.ts +0 -551
- package/tsconfig.json +0 -18
- package/ws-connection.ts +0 -270
package/msger.ts
DELETED
|
@@ -1,551 +0,0 @@
|
|
|
1
|
-
import { BuildURI, CoerceURI, Logger, Result, runtimeFn, URI } from "@adviser/cement";
|
|
2
|
-
import {
|
|
3
|
-
buildReqGestalt,
|
|
4
|
-
defaultGestalt,
|
|
5
|
-
EnDeCoder,
|
|
6
|
-
Gestalt,
|
|
7
|
-
MsgBase,
|
|
8
|
-
MsgerParams,
|
|
9
|
-
MsgIsResGestalt,
|
|
10
|
-
RequestOpts,
|
|
11
|
-
ResGestalt,
|
|
12
|
-
MsgWithError,
|
|
13
|
-
MsgIsError,
|
|
14
|
-
QSId,
|
|
15
|
-
ReqGestalt,
|
|
16
|
-
AuthType,
|
|
17
|
-
FPJWKCloudAuthType,
|
|
18
|
-
MsgWithConn,
|
|
19
|
-
ReqOpen,
|
|
20
|
-
ErrorMsg,
|
|
21
|
-
ReqOpenConn,
|
|
22
|
-
buildReqOpen,
|
|
23
|
-
MsgIsResOpen,
|
|
24
|
-
ResOpen,
|
|
25
|
-
MsgWithOptionalConn,
|
|
26
|
-
MsgIsConnected,
|
|
27
|
-
MsgIsWithConn,
|
|
28
|
-
MsgRawConnection,
|
|
29
|
-
} from "@fireproof/core-types-protocols-cloud";
|
|
30
|
-
import { ensurePath, HttpConnection } from "./http-connection.js";
|
|
31
|
-
import { WSConnection } from "./ws-connection.js";
|
|
32
|
-
import { SuperThis } from "@fireproof/core-types-base";
|
|
33
|
-
import { ensureLogger, sleep } from "@fireproof/core-runtime";
|
|
34
|
-
import pLimit from "@fireproof/vendor/p-limit";
|
|
35
|
-
|
|
36
|
-
// const headers = {
|
|
37
|
-
// "Content-Type": "application/json",
|
|
38
|
-
// "Accept": "application/json",
|
|
39
|
-
// };
|
|
40
|
-
|
|
41
|
-
export function selectRandom<T>(arr: T[]): T {
|
|
42
|
-
return arr[Math.floor(Math.random() * arr.length)];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function timeout<T>(ms: number, promise: Promise<T>): Promise<T> {
|
|
46
|
-
return new Promise((resolve, reject) => {
|
|
47
|
-
const timer = setTimeout(() => {
|
|
48
|
-
reject(new Error(`TIMEOUT after ${ms}ms`));
|
|
49
|
-
}, ms);
|
|
50
|
-
promise
|
|
51
|
-
.then(resolve)
|
|
52
|
-
.catch(reject)
|
|
53
|
-
.finally(() => clearTimeout(timer));
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type OnMsgFn<T extends MsgBase = MsgBase> = (msg: MsgWithError<T>) => void;
|
|
58
|
-
export type UnReg = () => void;
|
|
59
|
-
|
|
60
|
-
export interface ExchangedGestalt {
|
|
61
|
-
readonly my: Gestalt;
|
|
62
|
-
readonly remote: Gestalt;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export type OnErrorFn = (msg: Partial<MsgBase>, err: Error) => Partial<MsgBase>;
|
|
66
|
-
|
|
67
|
-
export interface ActiveStream {
|
|
68
|
-
readonly id: string;
|
|
69
|
-
readonly bind: {
|
|
70
|
-
readonly msg: MsgBase;
|
|
71
|
-
readonly opts: RequestOpts;
|
|
72
|
-
};
|
|
73
|
-
timeout?: unknown;
|
|
74
|
-
controller?: ReadableStreamDefaultController<MsgWithError<MsgBase>>;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export function jsonEnDe(sthis: SuperThis): EnDeCoder {
|
|
78
|
-
return {
|
|
79
|
-
encode: (node: unknown) => sthis.txt.encode(JSON.stringify(node)),
|
|
80
|
-
decode: (data: Uint8Array) => JSON.parse(sthis.txt.decode(data)),
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export type MsgerParamsWithEnDe = MsgerParams & { readonly ende: EnDeCoder };
|
|
85
|
-
|
|
86
|
-
export function defaultMsgParams(sthis: SuperThis, igs: Partial<MsgerParamsWithEnDe>): MsgerParamsWithEnDe {
|
|
87
|
-
return {
|
|
88
|
-
mime: "application/json",
|
|
89
|
-
ende: jsonEnDe(sthis),
|
|
90
|
-
timeout: 3000,
|
|
91
|
-
protocolCapabilities: ["reqRes", "stream"],
|
|
92
|
-
...igs,
|
|
93
|
-
} satisfies MsgerParamsWithEnDe;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export interface OpenParams {
|
|
97
|
-
readonly timeout: number;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export async function applyStart(prC: Promise<Result<MsgRawConnection>>): Promise<Result<MsgRawConnection>> {
|
|
101
|
-
const rC = await prC;
|
|
102
|
-
if (rC.isErr()) {
|
|
103
|
-
return rC;
|
|
104
|
-
}
|
|
105
|
-
const c = rC.Ok();
|
|
106
|
-
const r = await c.start();
|
|
107
|
-
if (r.isErr()) {
|
|
108
|
-
return Result.Err(r.Err());
|
|
109
|
-
}
|
|
110
|
-
return rC;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export async function authTypeFromUri(logger: Logger, curi: CoerceURI): Promise<Result<FPJWKCloudAuthType>> {
|
|
114
|
-
const uri = URI.from(curi);
|
|
115
|
-
const authJWK = uri.getParam("authJWK");
|
|
116
|
-
if (!authJWK) {
|
|
117
|
-
return logger.Error().Url(uri).Msg("authJWK is required").ResultError();
|
|
118
|
-
}
|
|
119
|
-
// const sts = await SessionTokenService.createFromEnv();
|
|
120
|
-
// const fpc = await sts.validate(authJWK);
|
|
121
|
-
// if (fpc.isErr()) {
|
|
122
|
-
// return logger.Error().Err(fpc).Msg("Invalid authJWK").ResultError();
|
|
123
|
-
// }
|
|
124
|
-
return Result.Ok({
|
|
125
|
-
type: "fp-cloud-jwk",
|
|
126
|
-
params: {
|
|
127
|
-
// claim: fpc.Ok().payload,
|
|
128
|
-
jwk: authJWK,
|
|
129
|
-
},
|
|
130
|
-
} satisfies FPJWKCloudAuthType);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function initialFPUri(curl: CoerceURI): URI {
|
|
134
|
-
let gestaltUrl = URI.from(curl);
|
|
135
|
-
if (["", "/"].includes(gestaltUrl.pathname)) {
|
|
136
|
-
gestaltUrl = gestaltUrl.build().appendRelative("/fp").URI();
|
|
137
|
-
}
|
|
138
|
-
return gestaltUrl;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export interface MsgerConnectParams {
|
|
142
|
-
readonly msgerParam: Partial<MsgerParamsWithEnDe>;
|
|
143
|
-
readonly conn: Partial<ReqOpenConn>;
|
|
144
|
-
readonly mowh: MsgOpenWSAndHttp;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
148
|
-
export class Msger {
|
|
149
|
-
static connect(sthis: SuperThis, curl: CoerceURI, mParam: Partial<MsgerConnectParams>): Promise<Result<VirtualConnected>> {
|
|
150
|
-
const vc = new VirtualConnected(sthis, {
|
|
151
|
-
curl,
|
|
152
|
-
conn: mParam.conn,
|
|
153
|
-
openWSorHttp: mParam.mowh,
|
|
154
|
-
msgerParams: mParam.msgerParam ?? {},
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
return Promise.resolve(Result.Ok(vc));
|
|
158
|
-
// return vc.connect();
|
|
159
|
-
}
|
|
160
|
-
private constructor() {
|
|
161
|
-
/* */
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
export class MsgOpenWSAndHttp {
|
|
166
|
-
async openHttp(
|
|
167
|
-
vc: SuperThis,
|
|
168
|
-
urls: URI[],
|
|
169
|
-
msgP: MsgerParamsWithEnDe,
|
|
170
|
-
exGestalt: ExchangedGestalt,
|
|
171
|
-
): Promise<Result<MsgRawConnection>> {
|
|
172
|
-
return Result.Ok(new HttpConnection(vc, urls, msgP, exGestalt));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
async openWS(
|
|
176
|
-
vc: SuperThis,
|
|
177
|
-
// qOpen: ReqOpen,
|
|
178
|
-
url: URI,
|
|
179
|
-
msgP: MsgerParamsWithEnDe,
|
|
180
|
-
exGestalt: ExchangedGestalt,
|
|
181
|
-
): Promise<Result<MsgRawConnection>> {
|
|
182
|
-
// const { encode } = jsonEnDe(sthis);
|
|
183
|
-
url = url.build().defParam("random", vc.nextId().str).URI();
|
|
184
|
-
// console.log("openWS", url.toString());
|
|
185
|
-
// .setParam("reqOpen", sthis.txt.decode(encode(qOpen)))
|
|
186
|
-
const wsUrl = ensurePath(url, "ws");
|
|
187
|
-
let wsFactory: () => WebSocket;
|
|
188
|
-
if (runtimeFn().isNodeIsh) {
|
|
189
|
-
const { WebSocket } = await import("ws");
|
|
190
|
-
wsFactory = () => new WebSocket(wsUrl) as unknown as WebSocket;
|
|
191
|
-
} else {
|
|
192
|
-
wsFactory = () => new WebSocket(wsUrl);
|
|
193
|
-
}
|
|
194
|
-
const wsc = new WSConnection(vc, wsFactory(), msgP, exGestalt);
|
|
195
|
-
return Result.Ok(wsc);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
interface RetryItem {
|
|
200
|
-
readonly retryCount: number;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export interface VirtualConnectedOptionals {
|
|
204
|
-
readonly retryCount: number; // default 3
|
|
205
|
-
readonly retryDelay: number; // default 500ms
|
|
206
|
-
readonly openWSorHttp: MsgOpenWSAndHttp;
|
|
207
|
-
readonly conn: Partial<ReqOpenConn>;
|
|
208
|
-
}
|
|
209
|
-
export interface VirtualConnectedRequired {
|
|
210
|
-
// readonly auth: AuthType;
|
|
211
|
-
readonly curl: CoerceURI;
|
|
212
|
-
readonly msgerParams: Partial<MsgerParamsWithEnDe>;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
export type VirtualConnectedOpts = Partial<VirtualConnectedOptionals> & Required<VirtualConnectedRequired>;
|
|
216
|
-
|
|
217
|
-
interface ActionWhatToDo<S extends MsgBase, X extends MsgWithError<S> | Result<void>> {
|
|
218
|
-
readonly whatToDo: "recurse" | "return" | "action";
|
|
219
|
-
readonly value?: X;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
export class VirtualConnected {
|
|
223
|
-
readonly sthis: SuperThis;
|
|
224
|
-
// readonly actionQueue: ActionsQueue;
|
|
225
|
-
readonly opts: VirtualConnectedOptionals & VirtualConnectedRequired;
|
|
226
|
-
readonly mowh: MsgOpenWSAndHttp;
|
|
227
|
-
readonly logger: Logger;
|
|
228
|
-
readonly id: string;
|
|
229
|
-
exchangedGestalt?: ExchangedGestalt;
|
|
230
|
-
// readonly actionQueue: ActionsQueue;
|
|
231
|
-
|
|
232
|
-
realConn?: MsgRawConnection;
|
|
233
|
-
retries: RetryItem[] = [];
|
|
234
|
-
virtualConn?: QSId;
|
|
235
|
-
|
|
236
|
-
constructor(sthis: SuperThis, opts: VirtualConnectedOpts) {
|
|
237
|
-
this.sthis = sthis;
|
|
238
|
-
this.id = sthis.nextId().str;
|
|
239
|
-
this.logger = ensureLogger(sthis, "VirtualConnected");
|
|
240
|
-
this.opts = {
|
|
241
|
-
...opts,
|
|
242
|
-
openWSorHttp: opts.openWSorHttp || new MsgOpenWSAndHttp(),
|
|
243
|
-
retryCount: opts.retryCount || 3,
|
|
244
|
-
retryDelay: opts.retryDelay || 500,
|
|
245
|
-
conn: { reqId: sthis.nextId().str, ...opts.conn }, // ensure conn has reqId
|
|
246
|
-
} satisfies VirtualConnectedOpts;
|
|
247
|
-
this.mowh = this.opts.openWSorHttp; // simplify the code
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
get conn(): QSId {
|
|
251
|
-
if (!this.virtualConn) {
|
|
252
|
-
const err = new Error("conn is not set");
|
|
253
|
-
throw err;
|
|
254
|
-
}
|
|
255
|
-
return this.virtualConn;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
readonly activeBinds = new Map<string, ActiveStream>();
|
|
259
|
-
|
|
260
|
-
private async handleBindRealConn(realConn: MsgRawConnection, req: MsgWithOptionalConn, as: ActiveStream): Promise<void> {
|
|
261
|
-
const conn = { ...this.conn, ...req.conn } satisfies QSId;
|
|
262
|
-
const stream = realConn.bind<MsgBase, MsgWithConn>({ ...as.bind.msg, auth: req.auth, conn }, as.bind.opts);
|
|
263
|
-
const sreader = stream.getReader();
|
|
264
|
-
while (true) {
|
|
265
|
-
const { done, value: msg } = await sreader.read();
|
|
266
|
-
if (done) {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
try {
|
|
270
|
-
if (MsgIsConnected(msg, this.conn) || MsgIsConnected(msg, conn)) {
|
|
271
|
-
as.controller?.enqueue(msg);
|
|
272
|
-
}
|
|
273
|
-
} catch (err) {
|
|
274
|
-
this.sthis.logger.Error().Err(err).Any({ msg }).Msg("Error in handleBindRealConn callback[ignored]");
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
private ensureOpts(opts: RequestOpts): RequestOpts {
|
|
280
|
-
return {
|
|
281
|
-
...opts,
|
|
282
|
-
timeout: opts.timeout ?? this.opts.msgerParams.timeout ?? 3000,
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
bind<S extends MsgWithConn, Q extends MsgWithOptionalConn>(req: Q, iopts: RequestOpts): ReadableStream<MsgWithError<S>> {
|
|
287
|
-
const opts = this.ensureOpts(iopts);
|
|
288
|
-
const id = this.sthis.nextId().str;
|
|
289
|
-
return new ReadableStream<MsgWithError<S>>({
|
|
290
|
-
cancel: (err) => {
|
|
291
|
-
this.sthis.logger.Debug().Msg("vc-bind-cancel", id, err);
|
|
292
|
-
this.activeBinds.delete(id);
|
|
293
|
-
},
|
|
294
|
-
start: (ctl) => {
|
|
295
|
-
this.getRealConn(req, opts, async (realConn: MsgRawConnection) => {
|
|
296
|
-
const as = {
|
|
297
|
-
id,
|
|
298
|
-
bind: {
|
|
299
|
-
msg: req,
|
|
300
|
-
opts,
|
|
301
|
-
},
|
|
302
|
-
controller: ctl,
|
|
303
|
-
};
|
|
304
|
-
this.activeBinds.set(id, as);
|
|
305
|
-
this.handleBindRealConn(realConn, req, as);
|
|
306
|
-
return Result.Ok(undefined);
|
|
307
|
-
}).catch((err: Error) => {
|
|
308
|
-
ctl.error({
|
|
309
|
-
type: "error",
|
|
310
|
-
src: "VirtualConnection:bind",
|
|
311
|
-
message: err.message,
|
|
312
|
-
tid: req.tid,
|
|
313
|
-
version: req.version,
|
|
314
|
-
auth: req.auth,
|
|
315
|
-
stack: [],
|
|
316
|
-
} satisfies ErrorMsg);
|
|
317
|
-
});
|
|
318
|
-
},
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
request<S extends MsgWithConn, Q extends MsgWithOptionalConn>(req: Q, iopts: RequestOpts): Promise<MsgWithError<S>> {
|
|
323
|
-
const opts = this.ensureOpts(iopts);
|
|
324
|
-
const realFn = (realConn: MsgRawConnection) =>
|
|
325
|
-
realConn.request<S, Q>(
|
|
326
|
-
{
|
|
327
|
-
...req,
|
|
328
|
-
conn: { ...this.virtualConn, ...req.conn },
|
|
329
|
-
},
|
|
330
|
-
opts,
|
|
331
|
-
);
|
|
332
|
-
if (opts.rawConn) {
|
|
333
|
-
// if rawConn is provided, use it directly
|
|
334
|
-
return realFn(opts.rawConn);
|
|
335
|
-
}
|
|
336
|
-
return this.getRealConn(req, opts, realFn);
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
send<S extends MsgWithConn, Q extends MsgWithOptionalConn>(msg: Q): Promise<MsgWithError<S>> {
|
|
340
|
-
return this.getRealConn(
|
|
341
|
-
msg,
|
|
342
|
-
{
|
|
343
|
-
waitFor: () => true,
|
|
344
|
-
},
|
|
345
|
-
async (realConn: MsgRawConnection) => {
|
|
346
|
-
const myMsg = {
|
|
347
|
-
...msg,
|
|
348
|
-
conn: { ...this.conn, ...msg.conn },
|
|
349
|
-
};
|
|
350
|
-
// console.log("VirtualConnected:send", this.id, myMsg);
|
|
351
|
-
const ret = await realConn.send<S, Q>(myMsg);
|
|
352
|
-
return ret;
|
|
353
|
-
},
|
|
354
|
-
);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
close(t: MsgWithOptionalConn): Promise<Result<void>> {
|
|
358
|
-
return this.getRealConn(
|
|
359
|
-
t,
|
|
360
|
-
{
|
|
361
|
-
waitFor: () => true,
|
|
362
|
-
noRetry: true,
|
|
363
|
-
},
|
|
364
|
-
(realConn: MsgRawConnection) => realConn.close(t),
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
369
|
-
onMsg(msgFn: OnMsgFn<MsgWithConn>): UnReg {
|
|
370
|
-
throw new Error("Method not implemented.");
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
private async connect(
|
|
374
|
-
auth: AuthType,
|
|
375
|
-
curl: CoerceURI,
|
|
376
|
-
imsgP: Partial<MsgerParamsWithEnDe> = {},
|
|
377
|
-
): Promise<Result<MsgRawConnection>> {
|
|
378
|
-
// initial exchange with JSON encoding
|
|
379
|
-
const jsMsgP = defaultMsgParams(this.sthis, { ...imsgP, mime: "application/json", ende: jsonEnDe(this.sthis) });
|
|
380
|
-
const gestaltUrl = initialFPUri(curl);
|
|
381
|
-
const gs = defaultGestalt(defaultMsgParams(this.sthis, imsgP), { id: "FP-Universal-Client" });
|
|
382
|
-
/*
|
|
383
|
-
* request Gestalt with Http
|
|
384
|
-
*/
|
|
385
|
-
const rHC = await this.mowh.openHttp(this.sthis, [gestaltUrl], jsMsgP, { my: gs, remote: gs });
|
|
386
|
-
if (rHC.isErr()) {
|
|
387
|
-
return rHC;
|
|
388
|
-
}
|
|
389
|
-
const hc = rHC.Ok();
|
|
390
|
-
// const rAuth = await authTypeFromUri(sthis.logger, url);
|
|
391
|
-
// if (rAuth.isErr()) {
|
|
392
|
-
// return Result.Err(rAuth)
|
|
393
|
-
// }
|
|
394
|
-
const resGestalt = await hc.request<ResGestalt, ReqGestalt>(buildReqGestalt(this.sthis, auth, gs), {
|
|
395
|
-
waitFor: MsgIsResGestalt,
|
|
396
|
-
noConn: true,
|
|
397
|
-
});
|
|
398
|
-
if (!MsgIsResGestalt(resGestalt)) {
|
|
399
|
-
return this.logger.Error().Any({ resGestalt }).Msg("should be ResGestalt").ResultError();
|
|
400
|
-
}
|
|
401
|
-
await hc.close(resGestalt /* as MsgWithConnAuth */);
|
|
402
|
-
const exGt = { my: gs, remote: resGestalt.gestalt } satisfies ExchangedGestalt;
|
|
403
|
-
const msgP = defaultMsgParams(this.sthis, imsgP);
|
|
404
|
-
|
|
405
|
-
this.exchangedGestalt = exGt;
|
|
406
|
-
|
|
407
|
-
let rRealConn: Result<MsgRawConnection>;
|
|
408
|
-
if (exGt.remote.protocolCapabilities.includes("reqRes") && !exGt.remote.protocolCapabilities.includes("stream")) {
|
|
409
|
-
// console.log("openHttp---", exGt.remote.httpEndpoints, curl?.toString(), exGt.remote.httpEndpoints.map((i) => BuildURI.from(curl).resolve(i).URI().toString()));
|
|
410
|
-
rRealConn = await this.mowh.openHttp(
|
|
411
|
-
this.sthis,
|
|
412
|
-
exGt.remote.httpEndpoints.map((i) => BuildURI.from(curl).resolve(i).URI()),
|
|
413
|
-
msgP,
|
|
414
|
-
exGt,
|
|
415
|
-
);
|
|
416
|
-
} else {
|
|
417
|
-
const wsUrl = BuildURI.from(gestaltUrl).resolve(selectRandom(exGt.remote.wsEndpoints)).URI();
|
|
418
|
-
// console.log("openWS---", wsUrl.toString(), "=====", exGt.remote.wsEndpoints);
|
|
419
|
-
rRealConn = await this.mowh.openWS(this.sthis, wsUrl, msgP, exGt);
|
|
420
|
-
}
|
|
421
|
-
if (rRealConn.isErr()) {
|
|
422
|
-
return rRealConn;
|
|
423
|
-
}
|
|
424
|
-
const realConn = rRealConn.Ok();
|
|
425
|
-
const rStart = await realConn.start();
|
|
426
|
-
if (rStart.isErr()) {
|
|
427
|
-
return Result.Err(rStart);
|
|
428
|
-
}
|
|
429
|
-
return rRealConn;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
private async getQSIdWithSideEffect(rawConn: MsgRawConnection, msg: MsgBase, conn: ReqOpenConn): Promise<MsgWithError<ResOpen>> {
|
|
433
|
-
const mOpen = await this.request<ResOpen, ReqOpen>(buildReqOpen(this.sthis, msg.auth, conn), {
|
|
434
|
-
waitFor: MsgIsResOpen,
|
|
435
|
-
noConn: true,
|
|
436
|
-
rawConn,
|
|
437
|
-
});
|
|
438
|
-
if (MsgIsError(mOpen)) {
|
|
439
|
-
return mOpen;
|
|
440
|
-
}
|
|
441
|
-
this.virtualConn = mOpen.conn;
|
|
442
|
-
return mOpen;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
private mutex = pLimit(1);
|
|
446
|
-
|
|
447
|
-
private async getRealConn<S extends MsgBase, Q extends MsgBase, X extends MsgWithError<S> | Result<void>>(
|
|
448
|
-
msg: Q,
|
|
449
|
-
iopts: RequestOpts,
|
|
450
|
-
action: (realConn: MsgRawConnection) => Promise<X>,
|
|
451
|
-
): Promise<X> {
|
|
452
|
-
const opts = this.ensureOpts(iopts);
|
|
453
|
-
// const id = this.sthis.nextId().str;
|
|
454
|
-
const whatToDo = await this.mutex(async (): Promise<ActionWhatToDo<S, X>> => {
|
|
455
|
-
if (!this.realConn) {
|
|
456
|
-
if (this.retries.length >= this.opts.retryCount) {
|
|
457
|
-
return {
|
|
458
|
-
whatToDo: "return",
|
|
459
|
-
value: {
|
|
460
|
-
type: "error",
|
|
461
|
-
src: "VirtualConnection:getRealConn",
|
|
462
|
-
message: "retry count exceeded",
|
|
463
|
-
tid: msg.tid,
|
|
464
|
-
version: msg.version,
|
|
465
|
-
auth: msg.auth,
|
|
466
|
-
stack: [],
|
|
467
|
-
} satisfies ErrorMsg as unknown as X,
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
// needs to connected
|
|
471
|
-
const rConn = await this.connect(msg.auth, this.opts.curl, this.opts.msgerParams);
|
|
472
|
-
if (rConn.isErr()) {
|
|
473
|
-
this.retries.push({ retryCount: this.retries.length + 1 });
|
|
474
|
-
await sleep(this.opts.retryDelay * this.retries.length);
|
|
475
|
-
return {
|
|
476
|
-
whatToDo: "recurse",
|
|
477
|
-
// this.getRealConn(msg, opts, action);
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
this.realConn = rConn.Ok();
|
|
481
|
-
const mQSid = await this.getQSIdWithSideEffect(this.realConn, msg, {
|
|
482
|
-
reqId: this.sthis.nextId().str,
|
|
483
|
-
...this.virtualConn,
|
|
484
|
-
...this.opts.conn,
|
|
485
|
-
});
|
|
486
|
-
if (MsgIsError(mQSid)) {
|
|
487
|
-
return {
|
|
488
|
-
whatToDo: "return",
|
|
489
|
-
value: {
|
|
490
|
-
...mQSid,
|
|
491
|
-
tid: msg.tid,
|
|
492
|
-
// type: msg.type,
|
|
493
|
-
} as unknown as X,
|
|
494
|
-
};
|
|
495
|
-
}
|
|
496
|
-
for (const as of this.activeBinds.values()) {
|
|
497
|
-
// async
|
|
498
|
-
void this.handleBindRealConn(this.realConn, msg, as);
|
|
499
|
-
}
|
|
500
|
-
return {
|
|
501
|
-
whatToDo: "recurse",
|
|
502
|
-
};
|
|
503
|
-
// const ret = await this.getRealConn(msg, opts, action);
|
|
504
|
-
// return ret;
|
|
505
|
-
} else {
|
|
506
|
-
if (!this.realConn.isReady) {
|
|
507
|
-
await this.realConn.close(msg);
|
|
508
|
-
this.realConn = undefined; // trigger reconnect
|
|
509
|
-
this.retries = [];
|
|
510
|
-
return { whatToDo: "recurse" };
|
|
511
|
-
// return this.getRealConn(msg, opts, action);
|
|
512
|
-
}
|
|
513
|
-
if (!opts.noConn && !this.virtualConn) {
|
|
514
|
-
const conn = MsgIsWithConn(msg) ? { conn: msg.conn } : {};
|
|
515
|
-
return {
|
|
516
|
-
whatToDo: "return",
|
|
517
|
-
value: {
|
|
518
|
-
type: "error",
|
|
519
|
-
src: msg,
|
|
520
|
-
message: "virtualConn is not set",
|
|
521
|
-
tid: msg.tid,
|
|
522
|
-
...conn,
|
|
523
|
-
version: msg.version,
|
|
524
|
-
auth: msg.auth,
|
|
525
|
-
stack: [],
|
|
526
|
-
} satisfies ErrorMsg as unknown as X,
|
|
527
|
-
};
|
|
528
|
-
}
|
|
529
|
-
return {
|
|
530
|
-
whatToDo: "action",
|
|
531
|
-
};
|
|
532
|
-
//const ret = await action(this.realConn);
|
|
533
|
-
//return ret;
|
|
534
|
-
}
|
|
535
|
-
});
|
|
536
|
-
// need to not stuck in the mutex
|
|
537
|
-
switch (whatToDo.whatToDo) {
|
|
538
|
-
case "recurse":
|
|
539
|
-
return this.getRealConn(msg, opts, action);
|
|
540
|
-
case "return":
|
|
541
|
-
return whatToDo.value as X;
|
|
542
|
-
case "action":
|
|
543
|
-
if (!this.realConn) {
|
|
544
|
-
throw new Error("realConn is not set, this should not happen");
|
|
545
|
-
}
|
|
546
|
-
return action(this.realConn);
|
|
547
|
-
default:
|
|
548
|
-
throw new Error(`Unknown action: ${whatToDo.whatToDo} for msg: ${msg.type} with id: ${this.id}`);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": [
|
|
3
|
-
"/home/runner/work/fireproof/fireproof/tsconfig.dist.json"
|
|
4
|
-
],
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"noEmit": false,
|
|
7
|
-
"outDir": "./"
|
|
8
|
-
},
|
|
9
|
-
"include": [
|
|
10
|
-
"**/*"
|
|
11
|
-
],
|
|
12
|
-
"exclude": [
|
|
13
|
-
"node_modules",
|
|
14
|
-
"dist",
|
|
15
|
-
".git",
|
|
16
|
-
".vscode"
|
|
17
|
-
]
|
|
18
|
-
}
|