@blaxel/core 0.2.88 → 0.2.89-preview.179

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.
@@ -8,6 +8,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
10
  const h2ref_js_1 = require("./h2ref.js");
11
+ const settings_js_1 = require("./settings.js");
11
12
  async function establishH2(sniHostname) {
12
13
  let timedOut = false;
13
14
  let timer;
@@ -34,8 +35,13 @@ async function _establishH2(sniHostname) {
34
35
  servername: sniHostname,
35
36
  ALPNProtocols: ["h2"],
36
37
  });
38
+ // Raise the per-stream receive window (SETTINGS_INITIAL_WINDOW_SIZE) well above
39
+ // Node's 64KB default. With the default, the server can only send one 64KB
40
+ // burst per round trip, capping a single download at window/RTT (~3MB/s at
41
+ // 20ms RTT) no matter the payload size.
37
42
  const session = http2_1.default.connect(`https://${sniHostname}:443`, {
38
43
  createConnection: () => tlsSocket,
44
+ settings: { initialWindowSize: settings_js_1.settings.h2StreamWindowSize },
39
45
  });
40
46
  await new Promise((resolve, reject) => {
41
47
  session.on("connect", resolve);
@@ -46,6 +52,17 @@ async function _establishH2(sniHostname) {
46
52
  reject(err instanceof Error ? err : new Error(String(err)));
47
53
  });
48
54
  });
55
+ // Raise the connection-level receive window too. Node defaults it to 64KB and
56
+ // never grows it, so it throttles the entire session (shared across every
57
+ // stream) — which is why adding read concurrency does not help. setLocalWindowSize
58
+ // is best-effort: guard it so an older runtime without it never breaks warm-up.
59
+ try {
60
+ session
61
+ .setLocalWindowSize?.(settings_js_1.settings.h2ConnectionWindowSize);
62
+ }
63
+ catch {
64
+ // ignore — fall back to the default window
65
+ }
49
66
  // Complete the SETTINGS exchange so the first real request has zero
50
67
  // protocol overhead. This RTT is hidden by the parallel createSandbox() call.
51
68
  await new Promise((resolve) => session.ping(() => resolve()));
@@ -28,8 +28,8 @@ function missingCredentialsMessage() {
28
28
  return "No Blaxel credentials found. Set the BL_API_KEY and BL_WORKSPACE environment variables, or run `bl login`.";
29
29
  }
30
30
  // Build info - these placeholders are replaced at build time by build:replace-imports
31
- const BUILD_VERSION = "0.2.88";
32
- const BUILD_COMMIT = "3d4dcbfdf0ac479adef35da9cd8523954af3e7f7";
31
+ const BUILD_VERSION = "0.2.89-preview.179";
32
+ const BUILD_COMMIT = "c481e2f6670b3cef6832875dbc9f2bc6b0b198f4";
33
33
  const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
34
34
  const BLAXEL_API_VERSION = "2026-04-16";
35
35
  // Cache for config.yaml tracking value
@@ -276,6 +276,32 @@ class Settings {
276
276
  }
277
277
  return 2;
278
278
  }
279
+ get h2StreamWindowSize() {
280
+ if (typeof this.config.h2StreamWindowSize === "number") {
281
+ return this.config.h2StreamWindowSize;
282
+ }
283
+ const value = env_js_1.env.BL_H2_STREAM_WINDOW;
284
+ if (value) {
285
+ const parsed = parseInt(value, 10);
286
+ if (!Number.isNaN(parsed) && parsed > 0) {
287
+ return parsed;
288
+ }
289
+ }
290
+ return 16 * 1024 * 1024;
291
+ }
292
+ get h2ConnectionWindowSize() {
293
+ if (typeof this.config.h2ConnectionWindowSize === "number") {
294
+ return this.config.h2ConnectionWindowSize;
295
+ }
296
+ const value = env_js_1.env.BL_H2_CONNECTION_WINDOW;
297
+ if (value) {
298
+ const parsed = parseInt(value, 10);
299
+ if (!Number.isNaN(parsed) && parsed > 0) {
300
+ return parsed;
301
+ }
302
+ }
303
+ return 32 * 1024 * 1024;
304
+ }
279
305
  get fsPartRetries() {
280
306
  if (typeof this.config.fsPartRetries === "number") {
281
307
  return this.config.fsPartRetries;
@@ -40,6 +40,20 @@ export type Config = {
40
40
  * (process.exec, drives.mount, etc.).
41
41
  */
42
42
  sandboxReadRetries?: number;
43
+ /**
44
+ * Per-stream HTTP/2 flow-control window in bytes, advertised to the server as
45
+ * SETTINGS_INITIAL_WINDOW_SIZE. Node defaults this to 64KB, which caps a single
46
+ * download at window/RTT (~3MB/s at 20ms RTT) regardless of payload size.
47
+ * Defaults to 16MB so large reads are bandwidth-bound, not latency-bound.
48
+ */
49
+ h2StreamWindowSize?: number;
50
+ /**
51
+ * Connection-level HTTP/2 flow-control window in bytes, applied via
52
+ * session.setLocalWindowSize(). Node defaults this to 64KB and never grows it,
53
+ * so it throttles the WHOLE session (shared across all streams) — which is why
54
+ * adding read concurrency does not help. Defaults to 32MB.
55
+ */
56
+ h2ConnectionWindowSize?: number;
43
57
  /**
44
58
  * Client credentials for OAuth2 client_credentials flow.
45
59
  *
@@ -81,6 +95,8 @@ declare class Settings {
81
95
  get disableH2(): boolean;
82
96
  get maxConcurrentH2Requests(): number;
83
97
  get maxConcurrentUploadH2Requests(): number;
98
+ get h2StreamWindowSize(): number;
99
+ get h2ConnectionWindowSize(): number;
84
100
  get fsPartRetries(): number;
85
101
  get sandboxReadRetries(): number;
86
102
  /**