@promigence/sdk 0.1.0-beta.12 → 0.1.0-beta.13
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/caller.js +10 -0
- package/dist/cjs/caller.js +10 -0
- package/dist/cjs/client.d.ts +16 -6
- package/dist/cjs/client.js +1180 -1129
- package/dist/cjs/core.d.ts +1 -1
- package/dist/cjs/core.js +1 -1
- package/dist/cjs/dispatcher.d.ts +2 -0
- package/dist/cjs/dispatcher.js +5 -0
- package/dist/cjs/http2.d.ts +10 -0
- package/dist/cjs/http2.js +143 -51
- package/dist/cjs/keyed.d.ts +6 -0
- package/dist/cjs/keyed.js +59 -0
- package/dist/cjs/proxy.js +11 -0
- package/dist/cjs/sandbox.d.ts +3 -1
- package/dist/cjs/sandbox.js +33 -20
- package/dist/cjs/transport-worker.js +11 -2
- package/dist/client.d.ts +16 -6
- package/dist/client.js +1179 -1127
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/dispatcher.d.ts +2 -0
- package/dist/dispatcher.js +5 -0
- package/dist/http2.d.ts +10 -0
- package/dist/http2.js +142 -51
- package/dist/keyed.d.ts +6 -0
- package/dist/keyed.js +55 -0
- package/dist/proxy.js +11 -0
- package/dist/sandbox.d.ts +3 -1
- package/dist/sandbox.js +33 -20
- package/dist/transport-worker.js +11 -2
- package/package.json +1 -1
package/dist/cjs/core.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Promigence SDK — constants, error hierarchy and shared types. */
|
|
2
|
-
export declare const VERSION = "0.1.0-beta.
|
|
2
|
+
export declare const VERSION = "0.1.0-beta.13";
|
|
3
3
|
export declare const DOCS_URL = "https://promigence.ai";
|
|
4
4
|
/** The error reference; each code is an anchor on it (the API's `docs` link has the same form). */
|
|
5
5
|
export declare const ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
|
package/dist/cjs/core.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.fixBeyondMessage = fixBeyondMessage;
|
|
|
7
7
|
exports.previewsOff = previewsOff;
|
|
8
8
|
exports.exitForCode = exitForCode;
|
|
9
9
|
const hint_js_1 = require("./hint.js");
|
|
10
|
-
exports.VERSION = "0.1.0-beta.
|
|
10
|
+
exports.VERSION = "0.1.0-beta.13";
|
|
11
11
|
exports.DOCS_URL = "https://promigence.ai";
|
|
12
12
|
exports.ERRORS_DOCS_URL = "https://www.promigence.ai/docs/errors";
|
|
13
13
|
exports.DEFAULT_API_URL = "https://api.promigence.ai/v1";
|
package/dist/cjs/dispatcher.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ interface Timeouts {
|
|
|
48
48
|
export declare function longRequestDispatcher(timeoutMs: number, base?: object | undefined): object | undefined;
|
|
49
49
|
/** Test and diagnostics view. Not part of the public API. */
|
|
50
50
|
export declare const __dispatcherInternals: {
|
|
51
|
+
/** How many times `longRequestDispatcher` has been asked (each request on the `fetch` path asks once). */
|
|
52
|
+
lookups(): number;
|
|
51
53
|
/** The timeouts a dispatcher of ours sets, or `undefined` for any other value. */
|
|
52
54
|
timeoutsOf(d: unknown): Timeouts | undefined;
|
|
53
55
|
/** The process's global dispatcher composed with exactly these timeouts (never cached). */
|
package/dist/cjs/dispatcher.js
CHANGED
|
@@ -52,7 +52,9 @@ function composeWith(base, ms) {
|
|
|
52
52
|
timeouts.set(d, { headersTimeout: ms, bodyTimeout: ms });
|
|
53
53
|
return d;
|
|
54
54
|
}
|
|
55
|
+
let lookups = 0;
|
|
55
56
|
function longRequestDispatcher(timeoutMs, base = firstGlobalDispatcher()) {
|
|
57
|
+
lookups++;
|
|
56
58
|
try {
|
|
57
59
|
const needed = timeoutMs + exports.LONG_REQUEST_SLACK_MS;
|
|
58
60
|
if (!(needed > exports.FETCH_DEFAULT_TIMEOUT_MS))
|
|
@@ -78,6 +80,9 @@ function longRequestDispatcher(timeoutMs, base = firstGlobalDispatcher()) {
|
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
exports.__dispatcherInternals = {
|
|
83
|
+
lookups() {
|
|
84
|
+
return lookups;
|
|
85
|
+
},
|
|
81
86
|
timeoutsOf(d) {
|
|
82
87
|
return d !== null && typeof d === "object" ? timeouts.get(d) : undefined;
|
|
83
88
|
},
|
package/dist/cjs/http2.d.ts
CHANGED
|
@@ -69,6 +69,8 @@ export interface Http2Init {
|
|
|
69
69
|
signal?: AbortSignal;
|
|
70
70
|
/** Read by `fetch` on fallback only. */
|
|
71
71
|
dispatcher?: object;
|
|
72
|
+
/** Worked out on fallback only, when no `dispatcher` was given: the one `fetch` should carry for `timeoutMs`. */
|
|
73
|
+
dispatcherFor?: (timeoutMs: number) => object | undefined;
|
|
72
74
|
/** Phase stamps when `PROMIGENCE_SDK_TRACE=1`. */
|
|
73
75
|
trace?: TraceStamp;
|
|
74
76
|
}
|
|
@@ -142,9 +144,13 @@ export declare class Http2Transport {
|
|
|
142
144
|
*/
|
|
143
145
|
fetch(url: string, init: Http2Init, replayable: boolean): Promise<Response | H2Response>;
|
|
144
146
|
}
|
|
147
|
+
/** The one `Http2Transport` for every client whose fallback is `fallback` (it keeps nothing of a client's). */
|
|
148
|
+
export declare function sharedTransport(fallback: FetchLike): Http2Transport;
|
|
145
149
|
export declare function warmTransport(): void;
|
|
146
150
|
/** Test and diagnostics view of the process-wide pools. Not part of the public API. */
|
|
147
151
|
export declare const __http2Internals: {
|
|
152
|
+
/** How many request URLs have been read (each new URL once; the same URL again is not read again). */
|
|
153
|
+
targetReads(): number;
|
|
148
154
|
pools(): Array<{
|
|
149
155
|
origin: string;
|
|
150
156
|
sessions: number;
|
|
@@ -181,6 +187,8 @@ export declare const __http2Internals: {
|
|
|
181
187
|
answered: number;
|
|
182
188
|
everReady: boolean;
|
|
183
189
|
closedReason: string;
|
|
190
|
+
messages: number;
|
|
191
|
+
posts: number;
|
|
184
192
|
} | undefined;
|
|
185
193
|
/** The transport thread's number of connections and spacing between new requests on one, for an environment (`threadKnobs`). */
|
|
186
194
|
threadKnobs(env: NodeJS.ProcessEnv): {
|
|
@@ -188,6 +196,8 @@ export declare const __http2Internals: {
|
|
|
188
196
|
gapUs: number;
|
|
189
197
|
pace: string;
|
|
190
198
|
};
|
|
199
|
+
/** Tests: make the transport thread stop answering (it reads nothing more), as a stuck one would. */
|
|
200
|
+
wedgeThreadForTest(): void;
|
|
191
201
|
/** Tests: make the transport thread fail as a crash would. */
|
|
192
202
|
crashThreadForTest(): void;
|
|
193
203
|
/** The early lookup, for tests: start one with a platform, DNS servers and hosts file of the test's own. */
|
package/dist/cjs/http2.js
CHANGED
|
@@ -6,6 +6,7 @@ exports.warmTls = warmTls;
|
|
|
6
6
|
exports.parseSessions = parseSessions;
|
|
7
7
|
exports.extraOrders = extraOrders;
|
|
8
8
|
exports.lookupApiName = lookupApiName;
|
|
9
|
+
exports.sharedTransport = sharedTransport;
|
|
9
10
|
exports.warmTransport = warmTransport;
|
|
10
11
|
const http2 = require("node:http2");
|
|
11
12
|
const node_net_1 = require("node:net");
|
|
@@ -855,18 +856,18 @@ const earlies = new Map();
|
|
|
855
856
|
const MAX_EARLIES = 4;
|
|
856
857
|
const EARLY_MAX_AGE_MS = 60_000;
|
|
857
858
|
const EARLY_TIMEOUT_MS = 2_000;
|
|
858
|
-
const
|
|
859
|
+
const DNS_AT_LOAD = (() => {
|
|
859
860
|
try {
|
|
860
|
-
return nodeDns()
|
|
861
|
+
return nodeDns();
|
|
861
862
|
}
|
|
862
863
|
catch {
|
|
863
864
|
return undefined;
|
|
864
865
|
}
|
|
865
866
|
})();
|
|
867
|
+
const LOOKUP_AT_LOAD = DNS_AT_LOAD?.lookup;
|
|
866
868
|
function lookupReplaced() {
|
|
867
869
|
try {
|
|
868
|
-
|
|
869
|
-
return d !== undefined && d.lookup !== LOOKUP_AT_LOAD;
|
|
870
|
+
return DNS_AT_LOAD !== undefined && DNS_AT_LOAD.lookup !== LOOKUP_AT_LOAD;
|
|
870
871
|
}
|
|
871
872
|
catch {
|
|
872
873
|
return true;
|
|
@@ -1300,12 +1301,13 @@ function targetOf(url, known, remember) {
|
|
|
1300
1301
|
}
|
|
1301
1302
|
function fetchInit(init, deadline) {
|
|
1302
1303
|
const timeout = AbortSignal.timeout(Math.max(0, Math.ceil(deadline - performance.now())));
|
|
1304
|
+
const dispatcher = init.dispatcher ?? init.dispatcherFor?.(init.timeoutMs);
|
|
1303
1305
|
return {
|
|
1304
1306
|
method: init.method,
|
|
1305
1307
|
headers: init.headers,
|
|
1306
1308
|
signal: init.signal === undefined ? timeout : AbortSignal.any([timeout, init.signal]),
|
|
1307
1309
|
...(init.body === undefined ? {} : { body: init.body }),
|
|
1308
|
-
...(
|
|
1310
|
+
...(dispatcher === undefined ? {} : { dispatcher }),
|
|
1309
1311
|
};
|
|
1310
1312
|
}
|
|
1311
1313
|
function fetchFailed(cause) {
|
|
@@ -1322,11 +1324,14 @@ class HandBack {
|
|
|
1322
1324
|
const UNSENT = new HandBack(0, 0);
|
|
1323
1325
|
const VIA_FETCH = Symbol("via-fetch");
|
|
1324
1326
|
const THREAD_GRACE_MS = 1_000;
|
|
1327
|
+
const THREAD_SWEEP_MS = 250;
|
|
1328
|
+
const THREAD_MARKS = 4096;
|
|
1325
1329
|
const THREAD_PHASES = ["w.got", "w.sent", "w.head", "w.end"];
|
|
1326
1330
|
class TransportThread {
|
|
1327
1331
|
origin;
|
|
1328
1332
|
worker;
|
|
1329
1333
|
port;
|
|
1334
|
+
acks;
|
|
1330
1335
|
state = "starting";
|
|
1331
1336
|
sessions = 0;
|
|
1332
1337
|
limit = DEFAULT_STREAM_LIMIT;
|
|
@@ -1336,13 +1341,26 @@ class TransportThread {
|
|
|
1336
1341
|
inflight = new Map();
|
|
1337
1342
|
nextId = 1;
|
|
1338
1343
|
listening = false;
|
|
1344
|
+
refd = false;
|
|
1345
|
+
sweep;
|
|
1346
|
+
freeMarks = [];
|
|
1347
|
+
messages = 0;
|
|
1348
|
+
outbox = [];
|
|
1349
|
+
turnOpen = false;
|
|
1350
|
+
posts = 0;
|
|
1339
1351
|
answered = 0;
|
|
1340
1352
|
pace = THREAD_DEFAULTS.pace;
|
|
1341
1353
|
hrOffset = Number(process.hrtime.bigint()) / 1e6 - performance.now();
|
|
1342
|
-
constructor(origin, worker, port) {
|
|
1354
|
+
constructor(origin, worker, port, acks) {
|
|
1343
1355
|
this.origin = origin;
|
|
1344
1356
|
this.worker = worker;
|
|
1345
1357
|
this.port = port;
|
|
1358
|
+
this.acks = acks;
|
|
1359
|
+
for (let i = acks.length - 1; i >= 0; i--)
|
|
1360
|
+
this.freeMarks.push(i);
|
|
1361
|
+
}
|
|
1362
|
+
acked(p) {
|
|
1363
|
+
return Atomics.load(this.acks, p.mark) === p.id;
|
|
1346
1364
|
}
|
|
1347
1365
|
poll() {
|
|
1348
1366
|
for (;;) {
|
|
@@ -1359,12 +1377,13 @@ class TransportThread {
|
|
|
1359
1377
|
}
|
|
1360
1378
|
}
|
|
1361
1379
|
ready() {
|
|
1362
|
-
if (this.state !== "closed")
|
|
1380
|
+
if (!this.listening && this.state !== "closed")
|
|
1363
1381
|
this.poll();
|
|
1364
|
-
return this.state === "ready" && this.sessions > 0 && this.inflight.size < this.sessions * this.limit;
|
|
1382
|
+
return this.state === "ready" && this.sessions > 0 && this.inflight.size < this.sessions * this.limit && this.freeMarks.length > 0;
|
|
1365
1383
|
}
|
|
1366
1384
|
onMessage(m) {
|
|
1367
1385
|
const msg = m;
|
|
1386
|
+
this.messages++;
|
|
1368
1387
|
switch (msg?.t) {
|
|
1369
1388
|
case "ready":
|
|
1370
1389
|
if (this.state === "starting" || this.state === "ready") {
|
|
@@ -1401,12 +1420,6 @@ class TransportThread {
|
|
|
1401
1420
|
case "closed":
|
|
1402
1421
|
this.close(msg.reason ?? "closed");
|
|
1403
1422
|
return;
|
|
1404
|
-
case "ack": {
|
|
1405
|
-
const p = this.inflight.get(msg.id ?? -1);
|
|
1406
|
-
if (p !== undefined)
|
|
1407
|
-
p.acked = true;
|
|
1408
|
-
return;
|
|
1409
|
-
}
|
|
1410
1423
|
case "res":
|
|
1411
1424
|
case "err":
|
|
1412
1425
|
this.settle(m);
|
|
@@ -1490,10 +1503,12 @@ class TransportThread {
|
|
|
1490
1503
|
if (this.closedReason === "")
|
|
1491
1504
|
this.closedReason = reason;
|
|
1492
1505
|
(0, trace_js_1.traceEvent)("thread:closed");
|
|
1506
|
+
this.outbox = [];
|
|
1493
1507
|
for (const [id, p] of [...this.inflight]) {
|
|
1508
|
+
const sent = this.acked(p);
|
|
1494
1509
|
this.inflight.delete(id);
|
|
1495
1510
|
this.release(p);
|
|
1496
|
-
if (!
|
|
1511
|
+
if (!sent)
|
|
1497
1512
|
p.resolve(UNSENT);
|
|
1498
1513
|
else if (p.replayable)
|
|
1499
1514
|
p.resolve(new HandBack(0, 1));
|
|
@@ -1515,18 +1530,49 @@ class TransportThread {
|
|
|
1515
1530
|
this.poll();
|
|
1516
1531
|
this.port.on("message", (m) => { this.onMessage(m); });
|
|
1517
1532
|
}
|
|
1533
|
+
if (this.refd)
|
|
1534
|
+
return;
|
|
1535
|
+
this.refd = true;
|
|
1518
1536
|
safely(() => { this.port.ref(); });
|
|
1519
1537
|
safely(() => { this.worker.ref(); });
|
|
1538
|
+
this.sweep = setInterval(() => { this.sweepBackstops(); }, THREAD_SWEEP_MS);
|
|
1539
|
+
safely(() => { this.sweep?.unref?.(); });
|
|
1520
1540
|
}
|
|
1521
1541
|
unref() {
|
|
1542
|
+
if (this.sweep !== undefined) {
|
|
1543
|
+
clearInterval(this.sweep);
|
|
1544
|
+
this.sweep = undefined;
|
|
1545
|
+
}
|
|
1546
|
+
if (!this.refd)
|
|
1547
|
+
return;
|
|
1548
|
+
this.refd = false;
|
|
1522
1549
|
safely(() => { this.port.unref(); });
|
|
1523
1550
|
safely(() => { this.worker.unref(); });
|
|
1524
1551
|
}
|
|
1552
|
+
sweepBackstops() {
|
|
1553
|
+
this.poll();
|
|
1554
|
+
const now = performance.now();
|
|
1555
|
+
let late = false;
|
|
1556
|
+
for (const [id, p] of [...this.inflight]) {
|
|
1557
|
+
if (p.backstopAt > now)
|
|
1558
|
+
continue;
|
|
1559
|
+
late = true;
|
|
1560
|
+
this.inflight.delete(id);
|
|
1561
|
+
this.release(p);
|
|
1562
|
+
try {
|
|
1563
|
+
this.port.postMessage({ t: "cancel", id });
|
|
1564
|
+
}
|
|
1565
|
+
catch { }
|
|
1566
|
+
p.reject(timeoutReason());
|
|
1567
|
+
}
|
|
1568
|
+
if (late)
|
|
1569
|
+
this.close("no answer from the transport thread");
|
|
1570
|
+
}
|
|
1525
1571
|
release(p) {
|
|
1526
1572
|
if (p.signal !== undefined && p.onAbort !== undefined)
|
|
1527
1573
|
p.signal.removeEventListener("abort", p.onAbort);
|
|
1528
|
-
|
|
1529
|
-
|
|
1574
|
+
Atomics.store(this.acks, p.mark, 0);
|
|
1575
|
+
this.freeMarks.push(p.mark);
|
|
1530
1576
|
if (this.inflight.size === 0)
|
|
1531
1577
|
this.unref();
|
|
1532
1578
|
}
|
|
@@ -1551,8 +1597,11 @@ class TransportThread {
|
|
|
1551
1597
|
headers["content-length"] = Buffer.byteLength(init.body, "utf8");
|
|
1552
1598
|
const id = this.nextId++;
|
|
1553
1599
|
const tr = init.trace;
|
|
1600
|
+
const place = this.freeMarks.pop();
|
|
1601
|
+
if (place === undefined)
|
|
1602
|
+
return Promise.resolve(UNSENT);
|
|
1554
1603
|
return new Promise((resolve, reject) => {
|
|
1555
|
-
const p = { resolve, reject, method: init.method, replayable,
|
|
1604
|
+
const p = { id, resolve, reject, method: init.method, replayable, mark: place, backstopAt: performance.now() + remaining + THREAD_GRACE_MS, trace: tr };
|
|
1556
1605
|
const signal = init.signal;
|
|
1557
1606
|
if (signal !== undefined) {
|
|
1558
1607
|
p.signal = signal;
|
|
@@ -1561,47 +1610,59 @@ class TransportThread {
|
|
|
1561
1610
|
return;
|
|
1562
1611
|
this.inflight.delete(id);
|
|
1563
1612
|
this.release(p);
|
|
1564
|
-
|
|
1565
|
-
|
|
1613
|
+
const queued = this.outbox.findIndex((b) => b.id === id);
|
|
1614
|
+
if (queued >= 0)
|
|
1615
|
+
this.outbox.splice(queued, 1);
|
|
1616
|
+
else {
|
|
1617
|
+
try {
|
|
1618
|
+
this.port.postMessage({ t: "cancel", id });
|
|
1619
|
+
}
|
|
1620
|
+
catch { }
|
|
1566
1621
|
}
|
|
1567
|
-
catch { }
|
|
1568
1622
|
reject(signal.reason);
|
|
1569
1623
|
};
|
|
1570
1624
|
signal.addEventListener("abort", p.onAbort, { once: true });
|
|
1571
1625
|
}
|
|
1572
|
-
p.backstop = setTimeout(() => {
|
|
1573
|
-
this.poll();
|
|
1574
|
-
if (!this.inflight.has(id))
|
|
1575
|
-
return;
|
|
1576
|
-
this.inflight.delete(id);
|
|
1577
|
-
this.release(p);
|
|
1578
|
-
try {
|
|
1579
|
-
this.port.postMessage({ t: "cancel", id });
|
|
1580
|
-
}
|
|
1581
|
-
catch { }
|
|
1582
|
-
reject(timeoutReason());
|
|
1583
|
-
this.close("no answer from the transport thread");
|
|
1584
|
-
}, remaining + THREAD_GRACE_MS);
|
|
1585
|
-
safely(() => { p.backstop?.unref?.(); });
|
|
1586
1626
|
this.inflight.set(id, p);
|
|
1587
1627
|
this.ref();
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1628
|
+
const paced = this.pace === "all" || (this.pace === "creates" && init.method === "POST" && CREATE_PATH.test(target.path));
|
|
1629
|
+
this.outbox.push({ id, msg: { t: "req", id, mark: place, headers, sensitive: ["authorization"], body: init.body, timeoutMs: remaining, replayable, paced }, p, resolve, trace: tr });
|
|
1630
|
+
if (!this.turnOpen) {
|
|
1631
|
+
this.turnOpen = true;
|
|
1632
|
+
queueMicrotask(() => { this.turnOpen = false; this.handOver(); });
|
|
1633
|
+
this.handOver();
|
|
1591
1634
|
}
|
|
1592
|
-
|
|
1593
|
-
this.
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1635
|
+
else if (this.outbox.length >= OUTBOX_GROUP)
|
|
1636
|
+
this.handOver();
|
|
1637
|
+
});
|
|
1638
|
+
}
|
|
1639
|
+
handOver() {
|
|
1640
|
+
if (this.outbox.length === 0)
|
|
1641
|
+
return;
|
|
1642
|
+
const batch = this.outbox;
|
|
1643
|
+
this.outbox = [];
|
|
1644
|
+
try {
|
|
1645
|
+
this.port.postMessage(batch.length === 1 ? batch[0].msg : { t: "reqs", list: batch.map((b) => b.msg) });
|
|
1646
|
+
this.posts++;
|
|
1647
|
+
}
|
|
1648
|
+
catch {
|
|
1649
|
+
for (const b of batch) {
|
|
1650
|
+
if (!this.inflight.has(b.id))
|
|
1651
|
+
continue;
|
|
1652
|
+
this.inflight.delete(b.id);
|
|
1653
|
+
this.release(b.p);
|
|
1654
|
+
b.resolve(UNSENT);
|
|
1597
1655
|
}
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
for (const b of batch)
|
|
1659
|
+
if (b.trace !== undefined) {
|
|
1660
|
+
(0, trace_js_1.mark)(b.trace, "sub");
|
|
1661
|
+
b.trace.via = "thread";
|
|
1601
1662
|
}
|
|
1602
|
-
});
|
|
1603
1663
|
}
|
|
1604
1664
|
}
|
|
1665
|
+
const OUTBOX_GROUP = 8;
|
|
1605
1666
|
let transportThread;
|
|
1606
1667
|
function threadFor(origin) {
|
|
1607
1668
|
const t = transportThread;
|
|
@@ -1646,9 +1707,10 @@ function startTransportThread(origin, onFail) {
|
|
|
1646
1707
|
const knobs = threadKnobs();
|
|
1647
1708
|
const file = typeof seam.transportFile === "string" ? seam.transportFile : here.replace(/http2\.js$/, "transport-worker.js");
|
|
1648
1709
|
const { port1, port2 } = new node_worker_threads_1.MessageChannel();
|
|
1710
|
+
const acks = new Int32Array(new SharedArrayBuffer(4 * THREAD_MARKS));
|
|
1649
1711
|
const worker = new node_worker_threads_1.Worker(file.startsWith("file:") ? new URL(file) : file, {
|
|
1650
1712
|
workerData: {
|
|
1651
|
-
promigenceTransport: true, port: port2, origin: origin.origin, sessions: knobs.sessions, gapUs: knobs.gapUs,
|
|
1713
|
+
promigenceTransport: true, port: port2, acks, origin: origin.origin, sessions: knobs.sessions, gapUs: knobs.gapUs,
|
|
1652
1714
|
firstUseMs: exports.tuning.loadFirstUseMs, idleMs: IDLE_CLOSE_MS, connectTimeoutMs: CONNECT_TIMEOUT_MS,
|
|
1653
1715
|
lookupTimeoutMs: EARLY_TIMEOUT_MS, trace: trace_js_1.TRACE_ON,
|
|
1654
1716
|
servers: exports.tuning.earlyServers ?? (Array.isArray(seam.servers) ? seam.servers : undefined),
|
|
@@ -1661,7 +1723,7 @@ function startTransportThread(origin, onFail) {
|
|
|
1661
1723
|
});
|
|
1662
1724
|
worker.unref();
|
|
1663
1725
|
port1.unref();
|
|
1664
|
-
const t = new TransportThread(origin.origin, worker, port1);
|
|
1726
|
+
const t = new TransportThread(origin.origin, worker, port1, acks);
|
|
1665
1727
|
t.pace = knobs.pace;
|
|
1666
1728
|
t.onFail = onFail;
|
|
1667
1729
|
worker.on("error", () => { t.poll(); t.close("error"); });
|
|
@@ -1683,6 +1745,18 @@ function knownPrefix(url) {
|
|
|
1683
1745
|
}
|
|
1684
1746
|
return undefined;
|
|
1685
1747
|
}
|
|
1748
|
+
let lastTargetUrl;
|
|
1749
|
+
let lastTargetRead;
|
|
1750
|
+
let targetReads = 0;
|
|
1751
|
+
function lastTarget(url) {
|
|
1752
|
+
if (url === lastTargetUrl)
|
|
1753
|
+
return lastTargetRead;
|
|
1754
|
+
targetReads++;
|
|
1755
|
+
const target = targetOf(url, knownPrefix(url), remember);
|
|
1756
|
+
lastTargetUrl = url;
|
|
1757
|
+
lastTargetRead = target;
|
|
1758
|
+
return target;
|
|
1759
|
+
}
|
|
1686
1760
|
function remember(p) {
|
|
1687
1761
|
for (let i = 0; i < prefixes.length; i++)
|
|
1688
1762
|
if (prefixes[i].text === p.text)
|
|
@@ -1718,7 +1792,7 @@ class Http2Transport {
|
|
|
1718
1792
|
const deadline = performance.now() + init.timeoutMs;
|
|
1719
1793
|
let target;
|
|
1720
1794
|
try {
|
|
1721
|
-
target =
|
|
1795
|
+
target = lastTarget(url);
|
|
1722
1796
|
}
|
|
1723
1797
|
catch {
|
|
1724
1798
|
return this.viaFetch(url, init, deadline);
|
|
@@ -1779,6 +1853,15 @@ class Http2Transport {
|
|
|
1779
1853
|
}
|
|
1780
1854
|
}
|
|
1781
1855
|
exports.Http2Transport = Http2Transport;
|
|
1856
|
+
let sharedFallback;
|
|
1857
|
+
let shared;
|
|
1858
|
+
function sharedTransport(fallback) {
|
|
1859
|
+
if (shared === undefined || sharedFallback !== fallback) {
|
|
1860
|
+
shared = new Http2Transport(fallback);
|
|
1861
|
+
sharedFallback = fallback;
|
|
1862
|
+
}
|
|
1863
|
+
return shared;
|
|
1864
|
+
}
|
|
1782
1865
|
function warmTransport() {
|
|
1783
1866
|
const res = toResponse(200, { "content-type": "application/json" }, Buffer.from("{}"), "POST");
|
|
1784
1867
|
res.header("server-timing");
|
|
@@ -1791,6 +1874,9 @@ function warmTransport() {
|
|
|
1791
1874
|
exchange({ end() { } }, undefined, { origin: none, host: none, path: none }, undefined, 0).catch(() => { });
|
|
1792
1875
|
}
|
|
1793
1876
|
exports.__http2Internals = {
|
|
1877
|
+
targetReads() {
|
|
1878
|
+
return targetReads;
|
|
1879
|
+
},
|
|
1794
1880
|
pools() {
|
|
1795
1881
|
return [...pools.values()].map((p) => ({
|
|
1796
1882
|
origin: p.origin.origin,
|
|
@@ -1831,11 +1917,17 @@ exports.__http2Internals = {
|
|
|
1831
1917
|
if (t === undefined)
|
|
1832
1918
|
return undefined;
|
|
1833
1919
|
t.poll();
|
|
1834
|
-
return { state: t.state, sessions: t.sessions, limit: t.limit, answered: t.answered, everReady: t.everReady, closedReason: t.closedReason };
|
|
1920
|
+
return { state: t.state, sessions: t.sessions, limit: t.limit, answered: t.answered, everReady: t.everReady, closedReason: t.closedReason, messages: t.messages, posts: t.posts };
|
|
1835
1921
|
},
|
|
1836
1922
|
threadKnobs(env) {
|
|
1837
1923
|
return threadKnobs(env);
|
|
1838
1924
|
},
|
|
1925
|
+
wedgeThreadForTest() {
|
|
1926
|
+
try {
|
|
1927
|
+
transportThread?.port.postMessage({ t: "wedge-for-test" });
|
|
1928
|
+
}
|
|
1929
|
+
catch { }
|
|
1930
|
+
},
|
|
1839
1931
|
crashThreadForTest() {
|
|
1840
1932
|
try {
|
|
1841
1933
|
transportThread?.port.postMessage({ t: "crash-for-test" });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is `method path` a create that takes an `Idempotency-Key`? `path` is relative to `/v1` and may
|
|
3
|
+
* carry a query string. The list is the API reference's (generated from the operations that
|
|
4
|
+
* document the header), so a create the API keys is never sent unkeyed by this client.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isKeyedCreate(method: string, path: string): boolean;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.__keyedInternals = void 0;
|
|
4
|
+
exports.isKeyedCreate = isKeyedCreate;
|
|
5
|
+
const keyed_gen_js_1 = require("./keyed.gen.js");
|
|
6
|
+
const KEYED_PATTERNS = keyed_gen_js_1.KEYED_CREATES.map(([m, p]) => [m, p.split("/").filter(Boolean)]);
|
|
7
|
+
const KEYED_METHODS = new Set(keyed_gen_js_1.KEYED_CREATES.map(([m]) => m));
|
|
8
|
+
let keyedLastMethod = "";
|
|
9
|
+
let keyedLastPath = "";
|
|
10
|
+
let keyedLastAnswer = false;
|
|
11
|
+
let keyedReads = 0;
|
|
12
|
+
function isKeyedCreate(method, path) {
|
|
13
|
+
if (!KEYED_METHODS.has(method))
|
|
14
|
+
return false;
|
|
15
|
+
if (path === keyedLastPath && method === keyedLastMethod)
|
|
16
|
+
return keyedLastAnswer;
|
|
17
|
+
const answer = keyedCreateOf(method, path);
|
|
18
|
+
keyedLastMethod = method;
|
|
19
|
+
keyedLastPath = path;
|
|
20
|
+
keyedLastAnswer = answer;
|
|
21
|
+
return answer;
|
|
22
|
+
}
|
|
23
|
+
function keyedCreateOf(method, path) {
|
|
24
|
+
keyedReads++;
|
|
25
|
+
let end = path.indexOf("?");
|
|
26
|
+
if (end < 0)
|
|
27
|
+
end = path.length;
|
|
28
|
+
for (let p = 0; p < KEYED_PATTERNS.length; p++) {
|
|
29
|
+
const entry = KEYED_PATTERNS[p];
|
|
30
|
+
if (entry[0] === method && segmentsMatch(path, end, entry[1]))
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
function segmentsMatch(path, end, pat) {
|
|
36
|
+
let i = 0;
|
|
37
|
+
let k = 0;
|
|
38
|
+
for (;;) {
|
|
39
|
+
while (i < end && path.charCodeAt(i) === 0x2f)
|
|
40
|
+
i++;
|
|
41
|
+
if (i >= end)
|
|
42
|
+
return k === pat.length;
|
|
43
|
+
if (k >= pat.length)
|
|
44
|
+
return false;
|
|
45
|
+
let j = i;
|
|
46
|
+
while (j < end && path.charCodeAt(j) !== 0x2f)
|
|
47
|
+
j++;
|
|
48
|
+
const s = pat[k];
|
|
49
|
+
if (s.charCodeAt(0) !== 0x7b && (j - i !== s.length || !path.startsWith(s, i)))
|
|
50
|
+
return false;
|
|
51
|
+
k++;
|
|
52
|
+
i = j;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.__keyedInternals = {
|
|
56
|
+
reads() {
|
|
57
|
+
return keyedReads;
|
|
58
|
+
},
|
|
59
|
+
};
|
package/dist/cjs/proxy.js
CHANGED
|
@@ -65,12 +65,23 @@ function noProxy(host, port, env = process.env) {
|
|
|
65
65
|
}
|
|
66
66
|
return false;
|
|
67
67
|
}
|
|
68
|
+
let proxyLastInputs;
|
|
69
|
+
let proxyLast;
|
|
68
70
|
function proxyFor(url, env = process.env) {
|
|
69
71
|
const https = envOf(env, "HTTPS_PROXY");
|
|
70
72
|
const http = envOf(env, "HTTP_PROXY");
|
|
71
73
|
const all = envOf(env, "ALL_PROXY");
|
|
72
74
|
if (https === undefined && http === undefined && all === undefined)
|
|
73
75
|
return undefined;
|
|
76
|
+
const inputs = `${url}\n${https ?? "\0"}\n${http ?? "\0"}\n${all ?? "\0"}\n${envOf(env, "NO_PROXY") ?? "\0"}`;
|
|
77
|
+
if (inputs === proxyLastInputs)
|
|
78
|
+
return proxyLast;
|
|
79
|
+
const found = proxyForOf(url, env, https, http, all);
|
|
80
|
+
proxyLastInputs = inputs;
|
|
81
|
+
proxyLast = found;
|
|
82
|
+
return found;
|
|
83
|
+
}
|
|
84
|
+
function proxyForOf(url, env, https, http, all) {
|
|
74
85
|
let u;
|
|
75
86
|
try {
|
|
76
87
|
u = new URL(url);
|
package/dist/cjs/sandbox.d.ts
CHANGED
|
@@ -396,7 +396,9 @@ export declare class Sandbox {
|
|
|
396
396
|
}>;
|
|
397
397
|
/**
|
|
398
398
|
* `forkHandles`, plus what `create` needs to end a run it was interrupted starting: the key the
|
|
399
|
-
* create is sent under, a signal for it and its waits, and the start options as sent
|
|
399
|
+
* create is sent under, a signal for it and its waits, and the start options as sent (`onStart`
|
|
400
|
+
* is handed the very options sent, the signal included); `client` and `count` stand in for the
|
|
401
|
+
* options' own.
|
|
400
402
|
*/
|
|
401
403
|
private static forkHandlesWith;
|
|
402
404
|
/** Attach to a running sandbox (`GET /sandboxes/:id`). */
|