run402 1.34.1 → 1.34.2
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/lib/deploy.mjs +14 -4
- package/package.json +1 -1
package/lib/deploy.mjs
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { readFileSync } from "fs";
|
|
2
2
|
import { dirname, resolve } from "path";
|
|
3
|
-
import { Agent } from "undici";
|
|
3
|
+
import { Agent, fetch as undiciFetch } from "undici";
|
|
4
4
|
import { API, allowanceAuthHeaders, findProject } from "./config.mjs";
|
|
5
5
|
import { resolveFilePathsInManifest, resolveMigrationsFile } from "./manifest.mjs";
|
|
6
6
|
|
|
7
7
|
// Custom undici dispatcher with longer timeouts for large-batch deploys.
|
|
8
8
|
// Default Node undici headersTimeout is ~5 min; large image uploads can exceed it.
|
|
9
|
+
// We MUST pair this Agent (from the installed undici major) with undici.fetch
|
|
10
|
+
// — not globalThis.fetch — because Node's built-in fetch ships its own bundled
|
|
11
|
+
// undici whose Dispatcher interface may differ by major version, which would
|
|
12
|
+
// cause UND_ERR_INVALID_ARG ("invalid onRequestStart method") at dispatch time.
|
|
9
13
|
const deployDispatcher = new Agent({
|
|
10
14
|
headersTimeout: 600_000, // 10 min
|
|
11
15
|
bodyTimeout: 600_000,
|
|
@@ -25,6 +29,12 @@ const RETRY_CAUSE_CODES = new Set([
|
|
|
25
29
|
]);
|
|
26
30
|
const RETRY_HTTP_STATUSES = new Set([502, 503, 504]);
|
|
27
31
|
|
|
32
|
+
// Test-only injection seam. Tests can replace the fetch implementation used by
|
|
33
|
+
// run() without monkey-patching globalThis.fetch (which would not intercept
|
|
34
|
+
// undici.fetch anyway). Pass null/undefined to reset.
|
|
35
|
+
let _runFetchImpl = undiciFetch;
|
|
36
|
+
export function _setFetchImpl(fn) { _runFetchImpl = fn ?? undiciFetch; }
|
|
37
|
+
|
|
28
38
|
function isRetriableError(err) {
|
|
29
39
|
if (!err) return false;
|
|
30
40
|
const code = err.code || (err.cause && err.cause.code);
|
|
@@ -42,10 +52,10 @@ function sleep(ms) {
|
|
|
42
52
|
* - Retries on RETRY_CAUSE_CODES network errors and RETRY_HTTP_STATUSES
|
|
43
53
|
* - Silent: no stdout noise on retry (CLI is agent-first)
|
|
44
54
|
*/
|
|
45
|
-
export async function fetchWithRetry(url, init, { attempts = 3 } = {}) {
|
|
55
|
+
export async function fetchWithRetry(url, init, { attempts = 3, fetchImpl = undiciFetch } = {}) {
|
|
46
56
|
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
47
57
|
try {
|
|
48
|
-
const res = await
|
|
58
|
+
const res = await fetchImpl(url, init);
|
|
49
59
|
if (attempt < attempts && RETRY_HTTP_STATUSES.has(res.status)) {
|
|
50
60
|
// Drain body so the connection can be reused, then retry.
|
|
51
61
|
try { await res.arrayBuffer(); } catch { /* noop */ }
|
|
@@ -183,7 +193,7 @@ export async function run(args) {
|
|
|
183
193
|
headers: { "Content-Type": "application/json", ...authHeaders },
|
|
184
194
|
body,
|
|
185
195
|
dispatcher: deployDispatcher,
|
|
186
|
-
});
|
|
196
|
+
}, { fetchImpl: _runFetchImpl });
|
|
187
197
|
|
|
188
198
|
// Content-type aware parsing: gateways (ALB, CloudFront, etc.) return HTML on
|
|
189
199
|
// 504/413/etc., which would otherwise crash res.json() with SyntaxError.
|
package/package.json
CHANGED