@blaxel/core 0.2.88 → 0.2.89

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.
@@ -2,6 +2,7 @@ import dns from "dns/promises";
2
2
  import http2 from "http2";
3
3
  import tls from "tls";
4
4
  import { markH2SessionIdleUnref } from "./h2ref.js";
5
+ import { settings } from "./settings.js";
5
6
  export async function establishH2(sniHostname) {
6
7
  let timedOut = false;
7
8
  let timer;
@@ -28,8 +29,13 @@ async function _establishH2(sniHostname) {
28
29
  servername: sniHostname,
29
30
  ALPNProtocols: ["h2"],
30
31
  });
32
+ // Raise the per-stream receive window (SETTINGS_INITIAL_WINDOW_SIZE) well above
33
+ // Node's 64KB default. With the default, the server can only send one 64KB
34
+ // burst per round trip, capping a single download at window/RTT (~3MB/s at
35
+ // 20ms RTT) no matter the payload size.
31
36
  const session = http2.connect(`https://${sniHostname}:443`, {
32
37
  createConnection: () => tlsSocket,
38
+ settings: { initialWindowSize: settings.h2StreamWindowSize },
33
39
  });
34
40
  await new Promise((resolve, reject) => {
35
41
  session.on("connect", resolve);
@@ -40,6 +46,17 @@ async function _establishH2(sniHostname) {
40
46
  reject(err instanceof Error ? err : new Error(String(err)));
41
47
  });
42
48
  });
49
+ // Raise the connection-level receive window too. Node defaults it to 64KB and
50
+ // never grows it, so it throttles the entire session (shared across every
51
+ // stream) — which is why adding read concurrency does not help. setLocalWindowSize
52
+ // is best-effort: guard it so an older runtime without it never breaks warm-up.
53
+ try {
54
+ session
55
+ .setLocalWindowSize?.(settings.h2ConnectionWindowSize);
56
+ }
57
+ catch {
58
+ // ignore — fall back to the default window
59
+ }
43
60
  // Complete the SETTINGS exchange so the first real request has zero
44
61
  // protocol overhead. This RTT is hidden by the parallel createSandbox() call.
45
62
  await new Promise((resolve) => session.ping(() => resolve()));
@@ -22,8 +22,8 @@ function missingCredentialsMessage() {
22
22
  return "No Blaxel credentials found. Set the BL_API_KEY and BL_WORKSPACE environment variables, or run `bl login`.";
23
23
  }
24
24
  // Build info - these placeholders are replaced at build time by build:replace-imports
25
- const BUILD_VERSION = "0.2.88";
26
- const BUILD_COMMIT = "3d4dcbfdf0ac479adef35da9cd8523954af3e7f7";
25
+ const BUILD_VERSION = "0.2.89";
26
+ const BUILD_COMMIT = "c481e2f6670b3cef6832875dbc9f2bc6b0b198f4";
27
27
  const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
28
28
  const BLAXEL_API_VERSION = "2026-04-16";
29
29
  // Cache for config.yaml tracking value
@@ -270,6 +270,32 @@ class Settings {
270
270
  }
271
271
  return 2;
272
272
  }
273
+ get h2StreamWindowSize() {
274
+ if (typeof this.config.h2StreamWindowSize === "number") {
275
+ return this.config.h2StreamWindowSize;
276
+ }
277
+ const value = env.BL_H2_STREAM_WINDOW;
278
+ if (value) {
279
+ const parsed = parseInt(value, 10);
280
+ if (!Number.isNaN(parsed) && parsed > 0) {
281
+ return parsed;
282
+ }
283
+ }
284
+ return 16 * 1024 * 1024;
285
+ }
286
+ get h2ConnectionWindowSize() {
287
+ if (typeof this.config.h2ConnectionWindowSize === "number") {
288
+ return this.config.h2ConnectionWindowSize;
289
+ }
290
+ const value = env.BL_H2_CONNECTION_WINDOW;
291
+ if (value) {
292
+ const parsed = parseInt(value, 10);
293
+ if (!Number.isNaN(parsed) && parsed > 0) {
294
+ return parsed;
295
+ }
296
+ }
297
+ return 32 * 1024 * 1024;
298
+ }
273
299
  get fsPartRetries() {
274
300
  if (typeof this.config.fsPartRetries === "number") {
275
301
  return this.config.fsPartRetries;