@molecule/api-code-sandbox-flyio 1.2.9 → 1.3.0
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 +53 -23
- package/dist/provider.d.ts +38 -11
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +202 -47
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,15 +3,11 @@ 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-10-
|
|
6
|
+
Generated: 2026-10-17T03:41:21.100Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-code-sandbox-flyio
|
|
10
10
|
|
|
11
|
-
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
-
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
-
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
-
|
|
15
11
|
Fly.io Machines code-sandbox provider for molecule.dev.
|
|
16
12
|
|
|
17
13
|
Runs each sandbox as a Fly Machine — a Firecracker microVM — managed over the
|
|
@@ -20,6 +16,10 @@ SCALE-TO-ZERO: `sleep()` maps to Fly's `suspend`, which snapshots the microVM's
|
|
|
20
16
|
memory to disk, and a suspended Machine bills for storage only. Waking is a
|
|
21
17
|
resume from that snapshot rather than a cold boot.
|
|
22
18
|
|
|
19
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
20
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
21
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
22
|
+
|
|
23
23
|
## Quick Start
|
|
24
24
|
|
|
25
25
|
```typescript
|
|
@@ -384,6 +384,12 @@ interface FlyioConfig {
|
|
|
384
384
|
* `suspend` is the scale-to-zero mapping (resume from a memory snapshot on the
|
|
385
385
|
* next request) and `stop` is a full stop with a cold boot on wake; opt into
|
|
386
386
|
* either deliberately.
|
|
387
|
+
*
|
|
388
|
+
* This is the provider's STEADY-STATE policy, reported as
|
|
389
|
+
* `SandboxProvider.defaultIdleAction`. A caller can override it for one sandbox
|
|
390
|
+
* with `SandboxConfig.idleAction` and restore this value afterwards with
|
|
391
|
+
* `Sandbox.setIdleAction` — which is what a production deploy does so its
|
|
392
|
+
* destination cannot suspend mid-copy (m103, 2026-10-17).
|
|
387
393
|
*/
|
|
388
394
|
autostop?: 'off' | 'stop' | 'suspend'
|
|
389
395
|
/**
|
|
@@ -440,12 +446,6 @@ interface FlyioConfig {
|
|
|
440
446
|
* Falls back to `FLY_SANDBOX_PRIVATE_SERVICES` (`<app>:<port>` pairs).
|
|
441
447
|
*
|
|
442
448
|
* Without this, a project with a database DOES NOT WORK on Fly: per-project
|
|
443
|
-
* 6PNs are what stop tenants reaching each other, and the same isolation stops
|
|
444
|
-
* a sandbox reaching the database it is supposed to use. Flycast is the only
|
|
445
|
-
* mechanism Fly documents that grants ONE directed edge without exposing
|
|
446
|
-
* anything publicly — see the `flycast.ts` module description.
|
|
447
|
-
*
|
|
448
|
-
* The declared PORT is load-bearing twice: it is unioned into
|
|
449
449
|
// … truncated — the full declaration is in node_modules/@molecule/api-code-sandbox-flyio/dist/types.d.ts
|
|
450
450
|
```
|
|
451
451
|
|
|
@@ -1527,28 +1527,58 @@ function isFailedState(state: FlyMachineState): boolean
|
|
|
1527
1527
|
|
|
1528
1528
|
**Returns:** `true` for `failed` and `launch_failed`.
|
|
1529
1529
|
|
|
1530
|
-
#### `isTransientExecPrecondition(error)`
|
|
1530
|
+
#### `isTransientExecPrecondition(error, machineState)`
|
|
1531
1531
|
|
|
1532
|
-
Whether a failed exec is Fly's TRANSIENT precondition —
|
|
1533
|
-
|
|
1534
|
-
ran (`412 failed_precondition: exec request failed: EOF`) — rather than the
|
|
1535
|
-
Machine being in a state an exec cannot run in.
|
|
1532
|
+
Whether a failed exec is Fly's TRANSIENT precondition — one a repeat (after a
|
|
1533
|
+
short wait) can clear, rather than a Machine state the exec has to wait out.
|
|
1536
1534
|
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1535
|
+
Fly answers the exec endpoint with 412 in two different situations, and only
|
|
1536
|
+
the BODY and the Machine's own reported state separate them:
|
|
1537
|
+
|
|
1538
|
+
1. `failed_precondition: exec request failed: EOF` — the request reached the
|
|
1539
|
+
Machine's exec agent and the connection dropped before the command ran.
|
|
1540
|
+
Always transient: the Machine is `started` and its agent recovers in
|
|
1541
|
+
seconds.
|
|
1542
|
+
2. `failed_precondition: machine not running` — transient ONLY while Fly's
|
|
1543
|
+
own Machines API reports the Machine `started`, `starting` or `replacing`
|
|
1544
|
+
(`machineState`). The exec endpoint lags the state Fly reports: a Machine
|
|
1545
|
+
whose config or image was just updated, or that is seconds past boot,
|
|
1546
|
+
reads `started` in `GET /machines/{id}` while its exec endpoint still
|
|
1547
|
+
refuses requests. Against a Machine Fly reports `stopped`/`suspended`/
|
|
1548
|
+
`destroyed` the same body is the REAL precondition — the Machine is not
|
|
1549
|
+
running, and {@link FlyioSandboxProvider.startMachine} is what answers it;
|
|
1550
|
+
repeating the exec would only burn the caller's budget.
|
|
1543
1551
|
|
|
1544
1552
|
```typescript
|
|
1545
|
-
function isTransientExecPrecondition(error: unknown): boolean
|
|
1553
|
+
function isTransientExecPrecondition(error: unknown, machineState?: string | null): boolean
|
|
1546
1554
|
```
|
|
1547
1555
|
|
|
1548
1556
|
- `error` — The failure an exec attempt raised.
|
|
1557
|
+
- `machineState` — The state `GET /machines/{id}` reports for the Machine, or `null`/`undefined` when it could not be read (which classifies case 2 as NOT transient — an unknown state is never assumed recoverable).
|
|
1549
1558
|
|
|
1550
1559
|
**Returns:** `true` when repeating the exec is the right recovery.
|
|
1551
1560
|
|
|
1561
|
+
#### `isMachineWarmingUp(state)`
|
|
1562
|
+
|
|
1563
|
+
Whether a state Fly reports for a Machine means the Machine is up, or on its
|
|
1564
|
+
way up — the states in which an exec that was refused for `machine not
|
|
1565
|
+
running` is the exec endpoint lagging the state, not the truth.
|
|
1566
|
+
|
|
1567
|
+
A deliberate allow-list rather than "anything but stopped/suspended": the
|
|
1568
|
+
three states here are the ones a refused exec was observed to recover from,
|
|
1569
|
+
and every other state — `stopped`, `suspended`, `destroyed`, `failed`,
|
|
1570
|
+
`created`, unreadable — keeps today's immediate throw. Widening it without
|
|
1571
|
+
that evidence would turn a real precondition into a retry budget spent
|
|
1572
|
+
against a Machine that is not coming up.
|
|
1573
|
+
|
|
1574
|
+
```typescript
|
|
1575
|
+
function isMachineWarmingUp(state: string | null | undefined): boolean
|
|
1576
|
+
```
|
|
1577
|
+
|
|
1578
|
+
- `state` — The Machine state from `GET /machines/{id}`, if readable.
|
|
1579
|
+
|
|
1580
|
+
**Returns:** `true` when waiting and repeating the exec can clear the refusal.
|
|
1581
|
+
|
|
1552
1582
|
#### `createProvider(config, client, store)`
|
|
1553
1583
|
|
|
1554
1584
|
Creates a Fly.io Machines sandbox provider.
|
package/dist/provider.d.ts
CHANGED
|
@@ -11,22 +11,49 @@ import { FlyApiClient } from './api.js';
|
|
|
11
11
|
import { type ObjectStore } from './storage.js';
|
|
12
12
|
import type { FlyioConfig } from './types.js';
|
|
13
13
|
/**
|
|
14
|
-
* Whether a failed exec is Fly's TRANSIENT precondition —
|
|
15
|
-
*
|
|
16
|
-
* ran (`412 failed_precondition: exec request failed: EOF`) — rather than the
|
|
17
|
-
* Machine being in a state an exec cannot run in.
|
|
14
|
+
* Whether a failed exec is Fly's TRANSIENT precondition — one a repeat (after a
|
|
15
|
+
* short wait) can clear, rather than a Machine state the exec has to wait out.
|
|
18
16
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
17
|
+
* Fly answers the exec endpoint with 412 in two different situations, and only
|
|
18
|
+
* the BODY and the Machine's own reported state separate them:
|
|
19
|
+
*
|
|
20
|
+
* 1. `failed_precondition: exec request failed: EOF` — the request reached the
|
|
21
|
+
* Machine's exec agent and the connection dropped before the command ran.
|
|
22
|
+
* Always transient: the Machine is `started` and its agent recovers in
|
|
23
|
+
* seconds.
|
|
24
|
+
* 2. `failed_precondition: machine not running` — transient ONLY while Fly's
|
|
25
|
+
* own Machines API reports the Machine `started`, `starting` or `replacing`
|
|
26
|
+
* (`machineState`). The exec endpoint lags the state Fly reports: a Machine
|
|
27
|
+
* whose config or image was just updated, or that is seconds past boot,
|
|
28
|
+
* reads `started` in `GET /machines/{id}` while its exec endpoint still
|
|
29
|
+
* refuses requests. Against a Machine Fly reports `stopped`/`suspended`/
|
|
30
|
+
* `destroyed` the same body is the REAL precondition — the Machine is not
|
|
31
|
+
* running, and {@link FlyioSandboxProvider.startMachine} is what answers it;
|
|
32
|
+
* repeating the exec would only burn the caller's budget.
|
|
25
33
|
*
|
|
26
34
|
* @param error - The failure an exec attempt raised.
|
|
35
|
+
* @param machineState - The state `GET /machines/{id}` reports for the Machine,
|
|
36
|
+
* or `null`/`undefined` when it could not be read (which classifies case 2 as
|
|
37
|
+
* NOT transient — an unknown state is never assumed recoverable).
|
|
27
38
|
* @returns `true` when repeating the exec is the right recovery.
|
|
28
39
|
*/
|
|
29
|
-
export declare function isTransientExecPrecondition(error: unknown): boolean;
|
|
40
|
+
export declare function isTransientExecPrecondition(error: unknown, machineState?: string | null): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether a state Fly reports for a Machine means the Machine is up, or on its
|
|
43
|
+
* way up — the states in which an exec that was refused for `machine not
|
|
44
|
+
* running` is the exec endpoint lagging the state, not the truth.
|
|
45
|
+
*
|
|
46
|
+
* A deliberate allow-list rather than "anything but stopped/suspended": the
|
|
47
|
+
* three states here are the ones a refused exec was observed to recover from,
|
|
48
|
+
* and every other state — `stopped`, `suspended`, `destroyed`, `failed`,
|
|
49
|
+
* `created`, unreadable — keeps today's immediate throw. Widening it without
|
|
50
|
+
* that evidence would turn a real precondition into a retry budget spent
|
|
51
|
+
* against a Machine that is not coming up.
|
|
52
|
+
*
|
|
53
|
+
* @param state - The Machine state from `GET /machines/{id}`, if readable.
|
|
54
|
+
* @returns `true` when waiting and repeating the exec can clear the refusal.
|
|
55
|
+
*/
|
|
56
|
+
export declare function isMachineWarmingUp(state: string | null | undefined): boolean;
|
|
30
57
|
/**
|
|
31
58
|
* Creates a Fly.io Machines sandbox provider.
|
|
32
59
|
* @param config - Optional Fly configuration: API token/URL, org slug, app
|
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,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAYV,eAAe,EAGhB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EAAE,YAAY,EAAgC,MAAM,UAAU,CAAA;AAwBrE,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAEhG,OAAO,KAAK,EAIV,WAAW,EAUZ,MAAM,YAAY,CAAA;AAkBnB;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAIjG;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE5E;AAkyFD;;;;;;;;;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
|
@@ -32,25 +32,56 @@ function describeDestroyFailure(step, id, error) {
|
|
|
32
32
|
return `Fly sandbox destroy failed at the ${step} for ${id} (${status}): ${reason}`;
|
|
33
33
|
}
|
|
34
34
|
/**
|
|
35
|
-
* Whether a failed exec is Fly's TRANSIENT precondition —
|
|
36
|
-
*
|
|
37
|
-
* ran (`412 failed_precondition: exec request failed: EOF`) — rather than the
|
|
38
|
-
* Machine being in a state an exec cannot run in.
|
|
35
|
+
* Whether a failed exec is Fly's TRANSIENT precondition — one a repeat (after a
|
|
36
|
+
* short wait) can clear, rather than a Machine state the exec has to wait out.
|
|
39
37
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
38
|
+
* Fly answers the exec endpoint with 412 in two different situations, and only
|
|
39
|
+
* the BODY and the Machine's own reported state separate them:
|
|
40
|
+
*
|
|
41
|
+
* 1. `failed_precondition: exec request failed: EOF` — the request reached the
|
|
42
|
+
* Machine's exec agent and the connection dropped before the command ran.
|
|
43
|
+
* Always transient: the Machine is `started` and its agent recovers in
|
|
44
|
+
* seconds.
|
|
45
|
+
* 2. `failed_precondition: machine not running` — transient ONLY while Fly's
|
|
46
|
+
* own Machines API reports the Machine `started`, `starting` or `replacing`
|
|
47
|
+
* (`machineState`). The exec endpoint lags the state Fly reports: a Machine
|
|
48
|
+
* whose config or image was just updated, or that is seconds past boot,
|
|
49
|
+
* reads `started` in `GET /machines/{id}` while its exec endpoint still
|
|
50
|
+
* refuses requests. Against a Machine Fly reports `stopped`/`suspended`/
|
|
51
|
+
* `destroyed` the same body is the REAL precondition — the Machine is not
|
|
52
|
+
* running, and {@link FlyioSandboxProvider.startMachine} is what answers it;
|
|
53
|
+
* repeating the exec would only burn the caller's budget.
|
|
46
54
|
*
|
|
47
55
|
* @param error - The failure an exec attempt raised.
|
|
56
|
+
* @param machineState - The state `GET /machines/{id}` reports for the Machine,
|
|
57
|
+
* or `null`/`undefined` when it could not be read (which classifies case 2 as
|
|
58
|
+
* NOT transient — an unknown state is never assumed recoverable).
|
|
48
59
|
* @returns `true` when repeating the exec is the right recovery.
|
|
49
60
|
*/
|
|
50
|
-
export function isTransientExecPrecondition(error) {
|
|
61
|
+
export function isTransientExecPrecondition(error, machineState) {
|
|
51
62
|
if (!(error instanceof FlyApiError) || error.status !== 412)
|
|
52
63
|
return false;
|
|
53
|
-
|
|
64
|
+
if (EXEC_BODY_DROPPED_CONNECTION.test(error.body))
|
|
65
|
+
return true;
|
|
66
|
+
return EXEC_BODY_MACHINE_NOT_RUNNING.test(error.body) && isMachineWarmingUp(machineState);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Whether a state Fly reports for a Machine means the Machine is up, or on its
|
|
70
|
+
* way up — the states in which an exec that was refused for `machine not
|
|
71
|
+
* running` is the exec endpoint lagging the state, not the truth.
|
|
72
|
+
*
|
|
73
|
+
* A deliberate allow-list rather than "anything but stopped/suspended": the
|
|
74
|
+
* three states here are the ones a refused exec was observed to recover from,
|
|
75
|
+
* and every other state — `stopped`, `suspended`, `destroyed`, `failed`,
|
|
76
|
+
* `created`, unreadable — keeps today's immediate throw. Widening it without
|
|
77
|
+
* that evidence would turn a real precondition into a retry budget spent
|
|
78
|
+
* against a Machine that is not coming up.
|
|
79
|
+
*
|
|
80
|
+
* @param state - The Machine state from `GET /machines/{id}`, if readable.
|
|
81
|
+
* @returns `true` when waiting and repeating the exec can clear the refusal.
|
|
82
|
+
*/
|
|
83
|
+
export function isMachineWarmingUp(state) {
|
|
84
|
+
return state === 'started' || state === 'starting' || state === 'replacing';
|
|
54
85
|
}
|
|
55
86
|
/**
|
|
56
87
|
* Default sandbox image. Fly pulls images itself, so this MUST be a reference
|
|
@@ -184,21 +215,25 @@ const MACHINE_CREATE_RETRY_STATUSES = [404, 412];
|
|
|
184
215
|
* Machine's exec agent died before the command ran: `412 {"error":
|
|
185
216
|
* "failed_precondition: exec request failed: EOF"}`. The Machine is `started`;
|
|
186
217
|
* the agent inside it dropped the request (a Machine seconds past boot, or
|
|
187
|
-
* Fly's own exec burst).
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
*
|
|
218
|
+
* Fly's own exec burst).
|
|
219
|
+
*/
|
|
220
|
+
const EXEC_BODY_DROPPED_CONNECTION = /exec request failed/i;
|
|
221
|
+
/**
|
|
222
|
+
* The OTHER 412 the exec endpoint answers — `{"error":"failed_precondition:
|
|
223
|
+
* machine not running"}`. Whether that is the real precondition or the exec
|
|
224
|
+
* endpoint lagging a Machine that is up cannot be read off the body, so it is
|
|
225
|
+
* settled by the state Fly reports for the Machine at that moment
|
|
226
|
+
* ({@link isMachineWarmingUp}).
|
|
192
227
|
*/
|
|
193
|
-
const EXEC_BODY_TRANSIENT = /exec request failed/i;
|
|
194
|
-
/** The real-precondition 412, which retrying an exec cannot fix. */
|
|
195
228
|
const EXEC_BODY_MACHINE_NOT_RUNNING = /machine not running/i;
|
|
196
229
|
/**
|
|
197
|
-
* Attempts for one exec when Fly answers
|
|
198
|
-
* {@link
|
|
199
|
-
* under 12 s of waiting, against the ~75 s each fresh production
|
|
200
|
-
* when this is left to a caller: X1 run flash-m85 (2026-10-16)
|
|
201
|
-
* consecutive deploys, and the run, to
|
|
230
|
+
* Attempts for one exec when Fly answers a transient 412 — either body of
|
|
231
|
+
* {@link isTransientExecPrecondition}. Four attempts over the three backoffs
|
|
232
|
+
* below is under 12 s of waiting, against the ~75 s each fresh production
|
|
233
|
+
* deploy costs when this is left to a caller: X1 run flash-m85 (2026-10-16)
|
|
234
|
+
* lost three consecutive deploys, and the run, to the dropped connection;
|
|
235
|
+
* flash-m94 (2026-10-16) lost 65 s and a whole redeploy to the same budget not
|
|
236
|
+
* covering `machine not running` on a Machine Fly reported `started`.
|
|
202
237
|
*/
|
|
203
238
|
const EXEC_PRECONDITION_ATTEMPTS = 4;
|
|
204
239
|
/**
|
|
@@ -258,6 +293,15 @@ const PROBE_EXEC_HEADROOM_SECONDS = 10;
|
|
|
258
293
|
*/
|
|
259
294
|
class FlyioSandboxProvider {
|
|
260
295
|
name = 'flyio';
|
|
296
|
+
/**
|
|
297
|
+
* The idle policy a sandbox gets when its own create does not name one — this
|
|
298
|
+
* provider's configured `autostop` (`FLY_PRODUCTION_AUTOSTOP` for production
|
|
299
|
+
* hosting). {@link SandboxConfig.idleAction} overrides it per Machine, and
|
|
300
|
+
* {@link Sandbox.setIdleAction} puts it back, which is how a deploy keeps its
|
|
301
|
+
* destination awake through a multi-minute copy and then returns the Machine
|
|
302
|
+
* to the app's real cost policy.
|
|
303
|
+
*/
|
|
304
|
+
defaultIdleAction;
|
|
261
305
|
config;
|
|
262
306
|
client;
|
|
263
307
|
metadataPrefix;
|
|
@@ -280,6 +324,7 @@ class FlyioSandboxProvider {
|
|
|
280
324
|
*/
|
|
281
325
|
constructor(config = {}, client, store) {
|
|
282
326
|
this.config = config;
|
|
327
|
+
this.defaultIdleAction = config.autostop ?? 'off';
|
|
283
328
|
this.metadataPrefix = config.metadataPrefix ?? DEFAULT_METADATA_PREFIX;
|
|
284
329
|
if (store !== undefined)
|
|
285
330
|
this.templateStoreCache = store;
|
|
@@ -375,10 +420,14 @@ class FlyioSandboxProvider {
|
|
|
375
420
|
* instead driven by the consumer's own per-tier hibernation loop, which calls
|
|
376
421
|
* `sleep()`/`hibernate()` — the same provider-agnostic mechanism the Docker
|
|
377
422
|
* bond relies on. An operator who wants Fly-native scale-to-zero can still opt
|
|
378
|
-
* in with `config.autostop: 'suspend'
|
|
423
|
+
* in with `config.autostop: 'suspend'`, and a caller can override it for ONE
|
|
424
|
+
* Machine with {@link SandboxConfig.idleAction} (a production deploy keeps its
|
|
425
|
+
* destination `'off'` until the artifact has landed and the app is healthy).
|
|
426
|
+
* @param action - The idle action for this Machine's service; defaults to the
|
|
427
|
+
* provider's configured policy.
|
|
379
428
|
* @returns The service definition, or `undefined`.
|
|
380
429
|
*/
|
|
381
|
-
previewService() {
|
|
430
|
+
previewService(action = this.defaultIdleAction) {
|
|
382
431
|
if (this.config.publicService === false)
|
|
383
432
|
return undefined;
|
|
384
433
|
return {
|
|
@@ -389,7 +438,7 @@ class FlyioSandboxProvider {
|
|
|
389
438
|
{ port: 443, handlers: ['tls', 'http'] },
|
|
390
439
|
],
|
|
391
440
|
autostart: true,
|
|
392
|
-
autostop:
|
|
441
|
+
autostop: action,
|
|
393
442
|
min_machines_running: 0,
|
|
394
443
|
};
|
|
395
444
|
}
|
|
@@ -1126,7 +1175,7 @@ class FlyioSandboxProvider {
|
|
|
1126
1175
|
// rootfs and only durable state pays the volume's small-file IO cost.
|
|
1127
1176
|
machineConfig.mounts = [{ volume: volumeId, path: config.volumeMountPath ?? WORKSPACE_PATH }];
|
|
1128
1177
|
}
|
|
1129
|
-
const service = this.previewService();
|
|
1178
|
+
const service = this.previewService(config.idleAction);
|
|
1130
1179
|
if (service)
|
|
1131
1180
|
machineConfig.services = [service];
|
|
1132
1181
|
const machine = await this.client.request(`/apps/${app}/machines`, {
|
|
@@ -1837,6 +1886,34 @@ class FlyioSandboxProvider {
|
|
|
1837
1886
|
// ---------------------------------------------------------------------------
|
|
1838
1887
|
// Sandbox
|
|
1839
1888
|
// ---------------------------------------------------------------------------
|
|
1889
|
+
/**
|
|
1890
|
+
* Reads the state Fly reports for a Machine, or `null` when it cannot be read.
|
|
1891
|
+
*
|
|
1892
|
+
* Best-effort on purpose: this runs both on the failure path and just before a
|
|
1893
|
+
* retry, and a failed diagnostic read must not replace the failure it is
|
|
1894
|
+
* describing. `null` is meaningful — it never classifies a refusal as
|
|
1895
|
+
* recoverable (see {@link isTransientExecPrecondition}).
|
|
1896
|
+
*
|
|
1897
|
+
* @param app - The Fly app name.
|
|
1898
|
+
* @param machineId - The Fly Machine id.
|
|
1899
|
+
* @returns The Machine's state, or `null` when the read failed or 404'd.
|
|
1900
|
+
*/
|
|
1901
|
+
async readMachineState(app, machineId) {
|
|
1902
|
+
try {
|
|
1903
|
+
const machine = await this.client.request(`/apps/${app}/machines/${machineId}`, {
|
|
1904
|
+
nullOn: [404],
|
|
1905
|
+
});
|
|
1906
|
+
return machine?.state ?? null;
|
|
1907
|
+
}
|
|
1908
|
+
catch (error) {
|
|
1909
|
+
logger.debug('Could not read the Machine state while an exec was refused', {
|
|
1910
|
+
app,
|
|
1911
|
+
machineId,
|
|
1912
|
+
error,
|
|
1913
|
+
});
|
|
1914
|
+
return null;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1840
1917
|
/**
|
|
1841
1918
|
* Issues one Fly exec call against a Machine.
|
|
1842
1919
|
*
|
|
@@ -1875,28 +1952,38 @@ class FlyioSandboxProvider {
|
|
|
1875
1952
|
return response ?? {};
|
|
1876
1953
|
}
|
|
1877
1954
|
catch (error) {
|
|
1878
|
-
|
|
1879
|
-
|
|
1955
|
+
// Which 412 this is cannot be read off the body alone: `machine not
|
|
1956
|
+
// running` is transient against a Machine Fly reports `started` and the
|
|
1957
|
+
// real precondition against one it reports `stopped`. So the state is
|
|
1958
|
+
// read here, once, and the same read decides the classification, the
|
|
1959
|
+
// wait below, and the state the error finally names.
|
|
1960
|
+
const state = error instanceof FlyApiError && error.status === 412
|
|
1961
|
+
? await this.readMachineState(app, machineId)
|
|
1962
|
+
: null;
|
|
1963
|
+
if (!isTransientExecPrecondition(error, state)) {
|
|
1964
|
+
throw await this.withMachineState(error, app, machineId, state);
|
|
1880
1965
|
}
|
|
1881
1966
|
if (attempt >= EXEC_PRECONDITION_ATTEMPTS || Date.now() >= deadline) {
|
|
1882
|
-
logger.warn('Fly kept
|
|
1967
|
+
logger.warn('Fly kept refusing the exec with a transient precondition', {
|
|
1883
1968
|
app,
|
|
1884
1969
|
machineId,
|
|
1885
1970
|
attempt,
|
|
1971
|
+
state: state ?? 'unreadable',
|
|
1886
1972
|
});
|
|
1887
|
-
throw await this.withMachineState(error, app, machineId);
|
|
1973
|
+
throw await this.withMachineState(error, app, machineId, state);
|
|
1888
1974
|
}
|
|
1889
|
-
logger.warn('Fly
|
|
1975
|
+
logger.warn('Fly refused the exec with a transient precondition; retrying', {
|
|
1890
1976
|
app,
|
|
1891
1977
|
machineId,
|
|
1892
1978
|
attempt,
|
|
1893
1979
|
attempts: EXEC_PRECONDITION_ATTEMPTS,
|
|
1980
|
+
state: state ?? 'unreadable',
|
|
1894
1981
|
});
|
|
1895
1982
|
// The Machine is up (that is what makes this 412 the transient one), but
|
|
1896
1983
|
// re-read it anyway: `stop`/`suspend` can land between attempts, and
|
|
1897
1984
|
// retrying an exec against a Machine that is not running would repeat a
|
|
1898
1985
|
// 412 that waiting — not repeating — is what answers.
|
|
1899
|
-
await this.waitForExecReady(app, machineId);
|
|
1986
|
+
await this.waitForExecReady(app, machineId, state);
|
|
1900
1987
|
await this.client.sleep(execPreconditionBackoffMs(attempt));
|
|
1901
1988
|
}
|
|
1902
1989
|
}
|
|
@@ -1908,17 +1995,17 @@ class FlyioSandboxProvider {
|
|
|
1908
1995
|
*
|
|
1909
1996
|
* A wait that does not reach `started` is logged and the exec is retried
|
|
1910
1997
|
* anyway: the retry is the recovery this path exists for, and turning a
|
|
1911
|
-
* recoverable
|
|
1912
|
-
*
|
|
1998
|
+
* recoverable refusal into a start-timeout error would hide the condition the
|
|
1999
|
+
* caller's error message is supposed to name.
|
|
1913
2000
|
*
|
|
1914
2001
|
* @param app - The Fly app name.
|
|
1915
2002
|
* @param machineId - The Fly Machine id.
|
|
2003
|
+
* @param state - The state already read for this Machine, when the caller read
|
|
2004
|
+
* one (the exec retry does); read again when omitted.
|
|
1916
2005
|
*/
|
|
1917
|
-
async waitForExecReady(app, machineId) {
|
|
1918
|
-
const
|
|
1919
|
-
|
|
1920
|
-
.catch(() => null);
|
|
1921
|
-
if (machine?.state === 'started')
|
|
2006
|
+
async waitForExecReady(app, machineId, state) {
|
|
2007
|
+
const machineState = state === undefined ? await this.readMachineState(app, machineId) : state;
|
|
2008
|
+
if (machineState === 'started')
|
|
1922
2009
|
return;
|
|
1923
2010
|
try {
|
|
1924
2011
|
await this.waitForStarted(app, machineId);
|
|
@@ -1927,7 +2014,7 @@ class FlyioSandboxProvider {
|
|
|
1927
2014
|
logger.warn('The Machine did not report started after a refused exec; retrying the exec', {
|
|
1928
2015
|
app,
|
|
1929
2016
|
machineId,
|
|
1930
|
-
state:
|
|
2017
|
+
state: machineState ?? 'unknown',
|
|
1931
2018
|
error,
|
|
1932
2019
|
});
|
|
1933
2020
|
}
|
|
@@ -1944,19 +2031,19 @@ class FlyioSandboxProvider {
|
|
|
1944
2031
|
* @param error - The failure to annotate.
|
|
1945
2032
|
* @param app - The Fly app name.
|
|
1946
2033
|
* @param machineId - The Fly Machine id.
|
|
2034
|
+
* @param knownState - The state already read for this Machine, when the caller
|
|
2035
|
+
* read one (the exec retry does); read again when omitted.
|
|
1947
2036
|
* @returns The original error, or a 412 carrying the Machine's state.
|
|
1948
2037
|
*/
|
|
1949
|
-
async withMachineState(error, app, machineId) {
|
|
2038
|
+
async withMachineState(error, app, machineId, knownState) {
|
|
1950
2039
|
if (!(error instanceof Error))
|
|
1951
2040
|
return new Error(String(error));
|
|
1952
2041
|
if (!(error instanceof FlyApiError) || error.status !== 412)
|
|
1953
2042
|
return error;
|
|
1954
2043
|
if (/machine state:/i.test(error.message))
|
|
1955
2044
|
return error;
|
|
1956
|
-
const
|
|
1957
|
-
|
|
1958
|
-
.catch(() => null);
|
|
1959
|
-
const state = machine?.state ?? 'unreadable';
|
|
2045
|
+
const read = knownState === undefined ? await this.readMachineState(app, machineId) : knownState;
|
|
2046
|
+
const state = read ?? 'unreadable';
|
|
1960
2047
|
return new FlyApiError(error.method, error.path, error.status, `${error.body} (machine ${machineId} state: ${state})`, { cause: error });
|
|
1961
2048
|
}
|
|
1962
2049
|
/**
|
|
@@ -2054,6 +2141,65 @@ class FlyioSandboxProvider {
|
|
|
2054
2141
|
`${totalSeconds}s (last observed state: ${lastState ?? 'unknown'}).`,
|
|
2055
2142
|
}), { cause: lastError });
|
|
2056
2143
|
}
|
|
2144
|
+
/**
|
|
2145
|
+
* Applies an idle policy to a running Machine's public service, in place.
|
|
2146
|
+
*
|
|
2147
|
+
* Fly's update endpoint takes the ENTIRE Machine config — "we don't support
|
|
2148
|
+
* partial updates" — and "If the Machine is running and the request is
|
|
2149
|
+
* successful, it will reboot" (verified against
|
|
2150
|
+
* https://docs.fly.io/machines/api/machines-resource, 2026-10-17). So this
|
|
2151
|
+
* re-reads the Machine, changes only each service's `autostop`, and waits for
|
|
2152
|
+
* the Machine to reach `started` again before resolving: the caller's next act
|
|
2153
|
+
* is to run commands in it. A Machine that ALREADY has the policy is left
|
|
2154
|
+
* alone — the reboot is a real cost, not a formality — and one that is not
|
|
2155
|
+
* running is updated with `skip_launch` so changing a parked Machine's policy
|
|
2156
|
+
* does not wake it.
|
|
2157
|
+
*
|
|
2158
|
+
* A Machine with no services has no proxy in front of it and therefore no
|
|
2159
|
+
* idle policy; that is a supported shape (a private sandbox), not an error.
|
|
2160
|
+
*
|
|
2161
|
+
* @param app - The Fly app name.
|
|
2162
|
+
* @param machineId - The Fly Machine id.
|
|
2163
|
+
* @param action - The idle action to apply to every service.
|
|
2164
|
+
* @throws {Error} When the Machine or its config cannot be read, the update is
|
|
2165
|
+
* rejected, or a rebooted Machine does not come back to `started`.
|
|
2166
|
+
*/
|
|
2167
|
+
async applyIdleAction(app, machineId, action) {
|
|
2168
|
+
const machine = await this.client.request(`/apps/${app}/machines/${machineId}`, {
|
|
2169
|
+
nullOn: [404],
|
|
2170
|
+
});
|
|
2171
|
+
if (!machine?.config) {
|
|
2172
|
+
throw new Error(t('codeSandbox.flyio.error.idlePolicyUnreadable', { machineId }, {
|
|
2173
|
+
defaultValue: `Cannot change the idle policy of Fly Machine ${machineId}: its config could not be ` +
|
|
2174
|
+
'read, so the Machine is left exactly as it is.',
|
|
2175
|
+
}));
|
|
2176
|
+
}
|
|
2177
|
+
const services = machine.config.services;
|
|
2178
|
+
if (!services?.length)
|
|
2179
|
+
return;
|
|
2180
|
+
if (services.every((service) => (service.autostop ?? 'off') === action))
|
|
2181
|
+
return;
|
|
2182
|
+
const config = {
|
|
2183
|
+
...machine.config,
|
|
2184
|
+
services: services.map((service) => ({ ...service, autostop: action })),
|
|
2185
|
+
};
|
|
2186
|
+
// A running Machine reboots to apply the config, so wait for it; a parked
|
|
2187
|
+
// one is updated without being started (there is nothing to wait for).
|
|
2188
|
+
const wasRunning = machine.state === 'started' || machine.state === 'starting';
|
|
2189
|
+
await this.client.request(`/apps/${app}/machines/${machineId}`, {
|
|
2190
|
+
method: 'POST',
|
|
2191
|
+
body: {
|
|
2192
|
+
config,
|
|
2193
|
+
// Immutable, but the update body is a whole Machine description; send
|
|
2194
|
+
// back what was read rather than letting Fly infer them.
|
|
2195
|
+
...(machine.name ? { name: machine.name } : {}),
|
|
2196
|
+
...(machine.region ? { region: machine.region } : {}),
|
|
2197
|
+
...(wasRunning ? {} : { skip_launch: true }),
|
|
2198
|
+
},
|
|
2199
|
+
});
|
|
2200
|
+
if (wasRunning)
|
|
2201
|
+
await this.waitForStarted(app, machineId);
|
|
2202
|
+
}
|
|
2057
2203
|
/**
|
|
2058
2204
|
* Builds the `Sandbox` facade for one Machine.
|
|
2059
2205
|
* @param app - The Fly app name.
|
|
@@ -2098,6 +2244,15 @@ class FlyioSandboxProvider {
|
|
|
2098
2244
|
await provider.startMachine(app, machineId);
|
|
2099
2245
|
this.status = 'running';
|
|
2100
2246
|
},
|
|
2247
|
+
/**
|
|
2248
|
+
* Applies an idle policy to this Machine's public service (see
|
|
2249
|
+
* {@link FlyioSandboxProvider.applyIdleAction} for the endpoint and the
|
|
2250
|
+
* reboot it costs). Resolves with the Machine running again.
|
|
2251
|
+
*/
|
|
2252
|
+
async setIdleAction(action) {
|
|
2253
|
+
await provider.applyIdleAction(app, machineId, action);
|
|
2254
|
+
this.status = 'running';
|
|
2255
|
+
},
|
|
2101
2256
|
async exec(command, opts) {
|
|
2102
2257
|
return await execCommand(exec, command, opts, WORKSPACE_PATH);
|
|
2103
2258
|
},
|
package/dist/types.d.ts
CHANGED
|
@@ -111,6 +111,12 @@ export interface FlyioConfig {
|
|
|
111
111
|
* `suspend` is the scale-to-zero mapping (resume from a memory snapshot on the
|
|
112
112
|
* next request) and `stop` is a full stop with a cold boot on wake; opt into
|
|
113
113
|
* either deliberately.
|
|
114
|
+
*
|
|
115
|
+
* This is the provider's STEADY-STATE policy, reported as
|
|
116
|
+
* `SandboxProvider.defaultIdleAction`. A caller can override it for one sandbox
|
|
117
|
+
* with `SandboxConfig.idleAction` and restore this value afterwards with
|
|
118
|
+
* `Sandbox.setIdleAction` — which is what a production deploy does so its
|
|
119
|
+
* destination cannot suspend mid-copy (m103, 2026-10-17).
|
|
114
120
|
*/
|
|
115
121
|
autostop?: 'off' | 'stop' | 'suspend';
|
|
116
122
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gGAAgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/api-code-sandbox-flyio",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Fly.io Machines (Firecracker microVM) code sandbox provider",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"license": "Apache-2.0",
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@molecule/api-bond": "1.0.2",
|
|
34
|
-
"@molecule/api-code-sandbox": "1.
|
|
34
|
+
"@molecule/api-code-sandbox": "1.4.0",
|
|
35
35
|
"@types/node": "26.1.2",
|
|
36
36
|
"typescript": "6.0.3",
|
|
37
37
|
"vitest": "4.1.11"
|