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