@molecule/api-code-sandbox-flyio 1.0.6 → 1.0.8
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/api.d.ts +7 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +2 -1
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +24 -4
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -57,6 +57,13 @@ export interface FlyRequestOptions {
|
|
|
57
57
|
* Used for idempotent deletes and existence checks (`[404]`).
|
|
58
58
|
*/
|
|
59
59
|
nullOn?: number[];
|
|
60
|
+
/**
|
|
61
|
+
* Extra HTTP statuses to treat as transient (retry) beyond the default
|
|
62
|
+
* `429`/`5xx`. The exec endpoint passes `[404]`: a machine-not-found for a
|
|
63
|
+
* Machine we just created and are actively driving is Fly API inconsistency
|
|
64
|
+
* under exec-burst load, not a real absence, so it is worth repeating.
|
|
65
|
+
*/
|
|
66
|
+
retryStatuses?: number[];
|
|
60
67
|
}
|
|
61
68
|
/**
|
|
62
69
|
* Decides whether a failed attempt is worth repeating.
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAgBH;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB;;;;;;;OAOG;gBAED,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAgBhC;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAgBH;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB;;;;;;;OAOG;gBAED,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAgBhC;AAED,4CAA4C;AAC5C,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAQhF;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAoBjE;AAED,oDAAoD;AACpD,MAAM,WAAW,mBAAmB;IAClC,gFAAgF;IAChF,KAAK,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;IAC/B,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mEAAmE;IACnE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtC;AAED;;;;;;GAMG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IAErD;;;OAGG;gBACS,OAAO,EAAE,mBAAmB;IASxC;;;;;;;;;;OAUG;IACG,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;CA8EnF"}
|
package/dist/api.js
CHANGED
|
@@ -210,7 +210,8 @@ export class FlyApiClient {
|
|
|
210
210
|
finally {
|
|
211
211
|
clearTimeout(timer);
|
|
212
212
|
}
|
|
213
|
-
|
|
213
|
+
const retryable = isRetryableStatus(status) || (options.retryStatuses?.includes(status) ?? false);
|
|
214
|
+
if (!retryable || attempt === attempts)
|
|
214
215
|
break;
|
|
215
216
|
const delay = retryDelayMs(attempt, retryAfter);
|
|
216
217
|
logger.warn(`Fly API transient failure on ${method} ${path} — retrying`, {
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAUV,eAAe,EAEhB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EAAE,YAAY,EAAgC,MAAM,UAAU,CAAA;AAsBrE,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAEhG,OAAO,KAAK,EAEV,WAAW,EAUZ,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAUV,eAAe,EAEhB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EAAE,YAAY,EAAgC,MAAM,UAAU,CAAA;AAsBrE,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAEhG,OAAO,KAAK,EAEV,WAAW,EAUZ,MAAM,YAAY,CAAA;AA6yDnB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,YAAY,EACrB,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,GACzB,eAAe,CAEjB"}
|
package/dist/provider.js
CHANGED
|
@@ -80,6 +80,16 @@ const DEFAULT_PROBE_TIMEOUT_MS = 3000;
|
|
|
80
80
|
* like `npm install`, not for un-tarring.
|
|
81
81
|
*/
|
|
82
82
|
const IMPORT_EXTRACT_TIMEOUT_MS = 55_000;
|
|
83
|
+
/**
|
|
84
|
+
* Base64 chunk size for {@link Sandbox.importFiles}'s temp-file write. Larger
|
|
85
|
+
* than `WRITE_CHUNK_BASE64` (which is tuned for small single files) so a
|
|
86
|
+
* multi-megabyte scaffold moves in fewer exec calls — each exec spends Fly's
|
|
87
|
+
* per-action rate-limit budget, and a burst of small chunks trips 429s (and, on
|
|
88
|
+
* a busy API, transient 404s). Kept well under the 128 KB `MAX_ARG_STRLEN`
|
|
89
|
+
* ceiling once the `printf … | base64 -d` wrapper and `buildScript` prefix are
|
|
90
|
+
* added.
|
|
91
|
+
*/
|
|
92
|
+
const IMPORT_WRITE_CHUNK_BASE64 = 100_000;
|
|
83
93
|
/** Extra seconds allowed for the probe exec beyond its connection budget. */
|
|
84
94
|
const PROBE_EXEC_HEADROOM_SECONDS = 10;
|
|
85
95
|
/**
|
|
@@ -1268,6 +1278,10 @@ class FlyioSandboxProvider {
|
|
|
1268
1278
|
// The API's own timeout bounds the command; allow the HTTP request a
|
|
1269
1279
|
// little longer so the transport never fires first.
|
|
1270
1280
|
timeoutMs: (timeoutSeconds + 15) * 1000,
|
|
1281
|
+
// A 404 on a Machine we created and are actively driving (e.g. the
|
|
1282
|
+
// exec burst importFiles issues) is Fly API inconsistency under load,
|
|
1283
|
+
// not a real absence — retry it alongside the default 429/5xx.
|
|
1284
|
+
retryStatuses: [404],
|
|
1271
1285
|
});
|
|
1272
1286
|
return response ?? {};
|
|
1273
1287
|
};
|
|
@@ -1476,7 +1490,13 @@ class FlyioSandboxProvider {
|
|
|
1476
1490
|
for await (const chunk of archive)
|
|
1477
1491
|
parts.push(Buffer.from(chunk));
|
|
1478
1492
|
const base64 = gzipSync(Buffer.concat(parts)).toString('base64');
|
|
1479
|
-
|
|
1493
|
+
// The temp tar lives on the WORKSPACE VOLUME, not /tmp. The chunked
|
|
1494
|
+
// write and the extract are separate exec calls, and a Machine with
|
|
1495
|
+
// autostop=suspend can cold-start between them — which recreates the
|
|
1496
|
+
// rootfs from the image (wiping /tmp) while the ext4 volume at
|
|
1497
|
+
// /workspace persists. A /tmp temp file vanished mid-import; the volume
|
|
1498
|
+
// one survives.
|
|
1499
|
+
const tmp = `${WORKSPACE_PATH}/.mol-import-${machineId}.tgz`;
|
|
1480
1500
|
const quotedTmp = shellQuote(tmp);
|
|
1481
1501
|
const quotedPath = shellQuote(path);
|
|
1482
1502
|
const failIfError = (result, step) => {
|
|
@@ -1488,9 +1508,9 @@ class FlyioSandboxProvider {
|
|
|
1488
1508
|
};
|
|
1489
1509
|
// First chunk truncates the temp file; the rest append. Each chunk is a
|
|
1490
1510
|
// multiple of 4 base64 chars so it decodes standalone (see writeFile).
|
|
1491
|
-
failIfError(await this.exec(`printf %s ${shellQuote(base64.slice(0,
|
|
1492
|
-
for (let i =
|
|
1493
|
-
failIfError(await this.exec(`printf %s ${shellQuote(base64.slice(i, i +
|
|
1511
|
+
failIfError(await this.exec(`printf %s ${shellQuote(base64.slice(0, IMPORT_WRITE_CHUNK_BASE64))} | base64 -d > ${quotedTmp}`, { timeout: FILE_OP_TIMEOUT_MS }), 'write');
|
|
1512
|
+
for (let i = IMPORT_WRITE_CHUNK_BASE64; i < base64.length; i += IMPORT_WRITE_CHUNK_BASE64) {
|
|
1513
|
+
failIfError(await this.exec(`printf %s ${shellQuote(base64.slice(i, i + IMPORT_WRITE_CHUNK_BASE64))} | base64 -d >> ${quotedTmp}`, { timeout: FILE_OP_TIMEOUT_MS }), 'write');
|
|
1494
1514
|
}
|
|
1495
1515
|
failIfError(await this.exec(`mkdir -p ${quotedPath} && tar -xzf ${quotedTmp} -C ${quotedPath} --no-same-owner --no-same-permissions && rm -f ${quotedTmp}`, { timeout: IMPORT_EXTRACT_TIMEOUT_MS }), 'extract');
|
|
1496
1516
|
},
|