@blaxel/core 0.2.83-preview.150 → 0.2.83
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/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/common/h2fetch.js +31 -11
- package/dist/cjs/common/h2ref.js +33 -0
- package/dist/cjs/common/h2warm.js +4 -3
- package/dist/cjs/common/settings.js +2 -2
- package/dist/cjs/types/common/h2ref.d.ts +3 -0
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/common/h2ref.js +33 -0
- package/dist/cjs-browser/common/settings.js +2 -2
- package/dist/cjs-browser/types/common/h2ref.d.ts +3 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/common/h2fetch.js +31 -11
- package/dist/esm/common/h2ref.js +29 -0
- package/dist/esm/common/h2warm.js +4 -3
- package/dist/esm/common/settings.js +2 -2
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/common/h2ref.js +29 -0
- package/dist/esm-browser/common/settings.js +2 -2
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { refH2SessionForActiveRequest } from "./h2ref.js";
|
|
1
2
|
const MIN_H2_SESSION_MAX_LISTENERS = 64;
|
|
2
3
|
const sessionsWithListenerBudget = new WeakSet();
|
|
3
4
|
/**
|
|
@@ -156,6 +157,8 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
156
157
|
let streamController = null;
|
|
157
158
|
let streamClosed = false;
|
|
158
159
|
let req = null;
|
|
160
|
+
let releaseSessionRef = () => { };
|
|
161
|
+
let abort = null;
|
|
159
162
|
try {
|
|
160
163
|
req = session.request(h2Headers);
|
|
161
164
|
}
|
|
@@ -165,6 +168,7 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
165
168
|
globalThis.fetch(fallbackUrl, fallbackInit).then(resolve, reject);
|
|
166
169
|
return;
|
|
167
170
|
}
|
|
171
|
+
releaseSessionRef = refH2SessionForActiveRequest(session);
|
|
168
172
|
options?.onH2RequestCreated?.();
|
|
169
173
|
ensureH2SessionListenerBudget(session);
|
|
170
174
|
const cleanupBeforeResponseListeners = () => {
|
|
@@ -172,11 +176,17 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
172
176
|
session.off("goaway", onSessionGoaway);
|
|
173
177
|
session.off("error", onSessionError);
|
|
174
178
|
};
|
|
179
|
+
const cleanupActiveRequest = () => {
|
|
180
|
+
if (abort)
|
|
181
|
+
signal?.removeEventListener("abort", abort);
|
|
182
|
+
releaseSessionRef();
|
|
183
|
+
};
|
|
175
184
|
const rejectBeforeResponse = (err) => {
|
|
176
185
|
if (settled)
|
|
177
186
|
return;
|
|
178
187
|
settled = true;
|
|
179
188
|
cleanupBeforeResponseListeners();
|
|
189
|
+
cleanupActiveRequest();
|
|
180
190
|
req?.close();
|
|
181
191
|
reject(err);
|
|
182
192
|
};
|
|
@@ -192,19 +202,21 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
192
202
|
session.once("close", onSessionClose);
|
|
193
203
|
session.once("goaway", onSessionGoaway);
|
|
194
204
|
session.once("error", onSessionError);
|
|
195
|
-
|
|
205
|
+
abort = () => {
|
|
196
206
|
req?.close();
|
|
197
207
|
const abortError = new DOMException("The operation was aborted.", "AbortError");
|
|
198
208
|
if (!responded) {
|
|
199
209
|
if (!settled) {
|
|
200
210
|
settled = true;
|
|
201
211
|
cleanupBeforeResponseListeners();
|
|
212
|
+
cleanupActiveRequest();
|
|
202
213
|
reject(abortError);
|
|
203
214
|
}
|
|
204
215
|
return;
|
|
205
216
|
}
|
|
206
217
|
if (!streamClosed) {
|
|
207
218
|
streamClosed = true;
|
|
219
|
+
cleanupActiveRequest();
|
|
208
220
|
streamController?.error(abortError);
|
|
209
221
|
}
|
|
210
222
|
};
|
|
@@ -213,6 +225,7 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
213
225
|
req.close();
|
|
214
226
|
cleanupBeforeResponseListeners();
|
|
215
227
|
settled = true;
|
|
228
|
+
cleanupActiveRequest();
|
|
216
229
|
reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
217
230
|
return;
|
|
218
231
|
}
|
|
@@ -236,25 +249,31 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
236
249
|
const readable = new ReadableStream({
|
|
237
250
|
start(controller) {
|
|
238
251
|
streamController = controller;
|
|
252
|
+
const finishStream = (finish) => {
|
|
253
|
+
if (streamClosed)
|
|
254
|
+
return;
|
|
255
|
+
streamClosed = true;
|
|
256
|
+
cleanupActiveRequest();
|
|
257
|
+
finish();
|
|
258
|
+
};
|
|
239
259
|
req.on("data", (chunk) => {
|
|
240
260
|
if (!streamClosed)
|
|
241
261
|
controller.enqueue(new Uint8Array(chunk));
|
|
242
262
|
});
|
|
243
263
|
req.on("end", () => {
|
|
244
|
-
|
|
245
|
-
streamClosed = true;
|
|
246
|
-
signal?.removeEventListener("abort", abort);
|
|
247
|
-
controller.close();
|
|
248
|
-
}
|
|
264
|
+
finishStream(() => controller.close());
|
|
249
265
|
});
|
|
250
266
|
req.on("error", (err) => {
|
|
251
|
-
|
|
252
|
-
streamClosed = true;
|
|
253
|
-
signal?.removeEventListener("abort", abort);
|
|
254
|
-
controller.error(err);
|
|
255
|
-
}
|
|
267
|
+
finishStream(() => controller.error(err));
|
|
256
268
|
});
|
|
257
269
|
},
|
|
270
|
+
cancel() {
|
|
271
|
+
req?.close();
|
|
272
|
+
if (streamClosed)
|
|
273
|
+
return;
|
|
274
|
+
streamClosed = true;
|
|
275
|
+
cleanupActiveRequest();
|
|
276
|
+
},
|
|
258
277
|
});
|
|
259
278
|
resolve(new Response(readable, { status, headers: resHeaders }));
|
|
260
279
|
});
|
|
@@ -263,6 +282,7 @@ function _h2Send(session, h2Headers, body, signal, fallbackUrl, fallbackInit, op
|
|
|
263
282
|
return;
|
|
264
283
|
settled = true;
|
|
265
284
|
cleanupBeforeResponseListeners();
|
|
285
|
+
cleanupActiveRequest();
|
|
266
286
|
reject(err);
|
|
267
287
|
});
|
|
268
288
|
if (body) {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const idleUnrefSessions = new WeakSet();
|
|
2
|
+
const activeRequestCounts = new WeakMap();
|
|
3
|
+
export function markH2SessionIdleUnref(session) {
|
|
4
|
+
idleUnrefSessions.add(session);
|
|
5
|
+
if ((activeRequestCounts.get(session) ?? 0) === 0) {
|
|
6
|
+
session.unref();
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function refH2SessionForActiveRequest(session) {
|
|
10
|
+
if (!idleUnrefSessions.has(session))
|
|
11
|
+
return () => { };
|
|
12
|
+
const previousActiveRequests = activeRequestCounts.get(session) ?? 0;
|
|
13
|
+
activeRequestCounts.set(session, previousActiveRequests + 1);
|
|
14
|
+
if (previousActiveRequests === 0)
|
|
15
|
+
session.ref();
|
|
16
|
+
let released = false;
|
|
17
|
+
return () => {
|
|
18
|
+
if (released)
|
|
19
|
+
return;
|
|
20
|
+
released = true;
|
|
21
|
+
const activeRequests = activeRequestCounts.get(session);
|
|
22
|
+
if (activeRequests === undefined || activeRequests <= 1) {
|
|
23
|
+
activeRequestCounts.delete(session);
|
|
24
|
+
session.unref();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
activeRequestCounts.set(session, activeRequests - 1);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import dns from "dns/promises";
|
|
2
2
|
import http2 from "http2";
|
|
3
3
|
import tls from "tls";
|
|
4
|
+
import { markH2SessionIdleUnref } from "./h2ref.js";
|
|
4
5
|
export async function establishH2(sniHostname) {
|
|
5
6
|
let timedOut = false;
|
|
6
7
|
let timer;
|
|
@@ -36,13 +37,13 @@ async function _establishH2(sniHostname) {
|
|
|
36
37
|
// Ensure the TLS socket is cleaned up on connection error
|
|
37
38
|
if (!tlsSocket.destroyed)
|
|
38
39
|
tlsSocket.destroy();
|
|
39
|
-
reject(err);
|
|
40
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
40
41
|
});
|
|
41
42
|
});
|
|
42
43
|
// Complete the SETTINGS exchange so the first real request has zero
|
|
43
44
|
// protocol overhead. This RTT is hidden by the parallel createSandbox() call.
|
|
44
45
|
await new Promise((resolve) => session.ping(() => resolve()));
|
|
45
|
-
// Unref so the session doesn't prevent process exit
|
|
46
|
-
session
|
|
46
|
+
// Unref so the idle session doesn't prevent process exit.
|
|
47
|
+
markH2SessionIdleUnref(session);
|
|
47
48
|
return session;
|
|
48
49
|
}
|
|
@@ -5,8 +5,8 @@ import { authentication } from "../authentication/index.js";
|
|
|
5
5
|
import { env } from "../common/env.js";
|
|
6
6
|
import { fs, os, path } from "../common/node.js";
|
|
7
7
|
// Build info - these placeholders are replaced at build time by build:replace-imports
|
|
8
|
-
const BUILD_VERSION = "0.2.83
|
|
9
|
-
const BUILD_COMMIT = "
|
|
8
|
+
const BUILD_VERSION = "0.2.83";
|
|
9
|
+
const BUILD_COMMIT = "d6f07458e0f766e5ef3c547eec3b0e00cf3297f7";
|
|
10
10
|
const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
|
|
11
11
|
const BLAXEL_API_VERSION = "2026-04-16";
|
|
12
12
|
// Cache for config.yaml tracking value
|