@molecule/api-code-sandbox-flyio 1.0.12 → 1.0.13

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/README.md CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-08-05T16:24:32.555Z
6
+ Generated: 2026-08-08T23:10:20.743Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-code-sandbox-flyio
@@ -609,6 +609,13 @@ interface FlyRequestOptions {
609
609
  * Used for idempotent deletes and existence checks (`[404]`).
610
610
  */
611
611
  nullOn?: number[]
612
+ /**
613
+ * Extra HTTP statuses to treat as transient (retry) beyond the default
614
+ * `429`/`5xx`. The exec endpoint passes `[404]`: a machine-not-found for a
615
+ * Machine we just created and are actively driving is Fly API inconsistency
616
+ * under exec-burst load, not a real absence, so it is worth repeating.
617
+ */
618
+ retryStatuses?: number[]
612
619
  }
613
620
  ```
614
621
 
@@ -1125,6 +1132,10 @@ function encodePrivateRoutes(routes: Record<string, string>): string
1125
1132
  Executes a command on a Machine, choosing the direct or detached strategy
1126
1133
  based on the caller's time budget.
1127
1134
 
1135
+ A command too large to pass inline (over {@link FLY_EXEC_MAX_ARG_BYTES}) is
1136
+ spilled to a file via chunked writes and run from there, so there is no size
1137
+ ceiling the caller must respect.
1138
+
1128
1139
  ```typescript
1129
1140
  function execCommand(
1130
1141
  rawExec: RawExec,
@@ -1751,6 +1762,20 @@ Exit status the capture script uses when `tar` failed outright (as opposed to wa
1751
1762
  const EXIT_TAR_FAILED: 92
1752
1763
  ```
1753
1764
 
1765
+ #### `FLY_EXEC_MAX_ARG_BYTES`
1766
+
1767
+ Hard cap on the `sh -c <script>` argument SENT to Fly's exec endpoint. This is
1768
+ NOT the OS `MAX_ARG_STRLEN` (128 KB) — the Fly Machines exec API rejects a
1769
+ command well below that, and does so INVISIBLY: it answers `200` with
1770
+ `exit_code: 0` and an `Unhandled rejection: Rejection([PayloadTooLarge…])`
1771
+ body, so the command never runs yet reads as success. Measured against the
1772
+ live API: ~15.8 KB scripts run, ~23.7 KB are rejected. 15 KB is the safe
1773
+ ceiling; callers that move bulk data (writeFile, importFiles) chunk beneath it.
1774
+
1775
+ ```typescript
1776
+ const FLY_EXEC_MAX_ARG_BYTES: 15000
1777
+ ```
1778
+
1754
1779
  #### `FLY_EXEC_MAX_TIMEOUT_SECONDS`
1755
1780
 
1756
1781
  Fly's hard ceiling on the exec endpoint's `timeout` field, in seconds.
@@ -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;AAs2DnB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,YAAY,EACrB,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,GACzB,eAAe,CAEjB"}
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;AA83DnB;;;;;;;;;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
@@ -82,6 +82,23 @@ const DEFAULT_PROBE_TIMEOUT_MS = 3000;
82
82
  * like `npm install`, not for un-tarring.
83
83
  */
84
84
  const IMPORT_EXTRACT_TIMEOUT_MS = 55_000;
85
+ /**
86
+ * Attempts for the create's `POST /machines`, retrying the app-propagation 404
87
+ * (see {@link MACHINE_CREATE_RETRY_STATUSES}). Fly propagates a new app to its
88
+ * sub-APIs asynchronously, so `POST /apps` can return before
89
+ * `POST /apps/{app}/machines` sees the app — which 404s "app not found" for a
90
+ * few seconds. Observed live during boot on 2026-08-08 (surfaced to the user as
91
+ * "Failed to start sandbox"). Six attempts span the client's 1+2+4+8+16 s
92
+ * backoff ≈ 31 s, comfortably past the observed window.
93
+ */
94
+ const MACHINE_CREATE_ATTEMPTS = 6;
95
+ /**
96
+ * Retrying a `POST /machines` on 404 is SAFE precisely because "app not found"
97
+ * means no Machine was created — unlike a 5xx/timeout, where one might have
98
+ * been. So only 404 is added here, on top of the client's default retryable
99
+ * set; the retry cannot double-create.
100
+ */
101
+ const MACHINE_CREATE_RETRY_STATUSES = [404];
85
102
  /**
86
103
  * Base64 chunk size for {@link Sandbox.importFiles}'s temp-file write. Bounded by
87
104
  * the same Fly exec payload limit as `WRITE_CHUNK_BASE64` (~15 KB, silently
@@ -397,7 +414,7 @@ class FlyioSandboxProvider {
397
414
  */
398
415
  async destroyStaleMachines(app) {
399
416
  const managedKey = `${this.metadataPrefix}.managed`;
400
- let machines = null;
417
+ let machines;
401
418
  try {
402
419
  machines = await this.client.request(`/apps/${app}/machines`, {
403
420
  nullOn: [404],
@@ -797,6 +814,11 @@ class FlyioSandboxProvider {
797
814
  const machine = await this.client.request(`/apps/${app}/machines`, {
798
815
  method: 'POST',
799
816
  body: { region: this.region(), config: machineConfig },
817
+ // A just-created app propagates to the Machines API asynchronously, so this
818
+ // POST can 404 "app not found" for a few seconds. Retry the 404 (safe: no
819
+ // Machine is created when the app is not found) across the client's backoff.
820
+ attempts: MACHINE_CREATE_ATTEMPTS,
821
+ retryStatuses: MACHINE_CREATE_RETRY_STATUSES,
800
822
  });
801
823
  if (!machine?.id) {
802
824
  throw new Error(t('codeSandbox.flyio.error.createFailed', { app }, { defaultValue: `Fly Machine creation in app "${app}" returned no Machine id.` }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-code-sandbox-flyio",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "Fly.io Machines (Firecracker microVM) code sandbox provider",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",