rightsize 0.2.0 → 0.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 +12 -4
- package/dist/backend-docker/backend.d.ts +27 -4
- package/dist/backend-docker/backend.d.ts.map +1 -1
- package/dist/backend-docker/backend.js +56 -6
- package/dist/backend-docker/backend.js.map +1 -1
- package/dist/backend-docker/cli.d.ts +25 -0
- package/dist/backend-docker/cli.d.ts.map +1 -0
- package/dist/backend-docker/cli.js +64 -0
- package/dist/backend-docker/cli.js.map +1 -0
- package/dist/backend-msb/backend.d.ts +61 -7
- package/dist/backend-msb/backend.d.ts.map +1 -1
- package/dist/backend-msb/backend.js +121 -11
- package/dist/backend-msb/backend.js.map +1 -1
- package/dist/backend-msb/commands.d.ts +10 -0
- package/dist/backend-msb/commands.d.ts.map +1 -1
- package/dist/backend-msb/commands.js +29 -1
- package/dist/backend-msb/commands.js.map +1 -1
- package/dist/backend-msb/snapshot-not-found.d.ts +25 -0
- package/dist/backend-msb/snapshot-not-found.d.ts.map +1 -0
- package/dist/backend-msb/snapshot-not-found.js +27 -0
- package/dist/backend-msb/snapshot-not-found.js.map +1 -0
- package/dist/core/backend.d.ts +57 -6
- package/dist/core/backend.d.ts.map +1 -1
- package/dist/core/checkpoint/api.d.ts +80 -0
- package/dist/core/checkpoint/api.d.ts.map +1 -0
- package/dist/core/checkpoint/api.js +138 -0
- package/dist/core/checkpoint/api.js.map +1 -0
- package/dist/core/checkpoint/name.d.ts +12 -0
- package/dist/core/checkpoint/name.d.ts.map +1 -0
- package/dist/core/checkpoint/name.js +17 -0
- package/dist/core/checkpoint/name.js.map +1 -0
- package/dist/core/checkpoint/ref.d.ts +12 -0
- package/dist/core/checkpoint/ref.d.ts.map +1 -0
- package/dist/core/checkpoint/ref.js +16 -0
- package/dist/core/checkpoint/ref.js.map +1 -0
- package/dist/core/checkpoint/registry.d.ts +107 -0
- package/dist/core/checkpoint/registry.d.ts.map +1 -0
- package/dist/core/checkpoint/registry.js +180 -0
- package/dist/core/checkpoint/registry.js.map +1 -0
- package/dist/core/errors.d.ts +60 -4
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +80 -7
- package/dist/core/errors.js.map +1 -1
- package/dist/core/generic-container.d.ts +87 -18
- package/dist/core/generic-container.d.ts.map +1 -1
- package/dist/core/generic-container.js +171 -22
- package/dist/core/generic-container.js.map +1 -1
- package/dist/core/model.d.ts +25 -8
- package/dist/core/model.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/modules/keycloak.js +1 -1
- package/dist/modules/mysql.d.ts.map +1 -1
- package/dist/modules/mysql.js +4 -3
- package/dist/modules/mysql.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { cacheDir } from "../cache-dir.js";
|
|
2
|
+
import { Backends } from "../backends.js";
|
|
3
|
+
import { requireValidCheckpointName } from "./name.js";
|
|
4
|
+
import { readCheckpointRegistry, removeCheckpointRegistryFile, listCheckpointNames, fromCheckpointRegistryEntry, } from "./registry.js";
|
|
5
|
+
/** Every field of a `Checkpoint` comes straight from the registry entry except `spec`, which is reconstructed via `fromCheckpointRegistryEntry` — see that function's own doc for what is and isn't meaningful in the result. */
|
|
6
|
+
function toCheckpoint(entry) {
|
|
7
|
+
return { ref: entry.ref, backend: entry.backend, spec: fromCheckpointRegistryEntry(entry) };
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Rediscovers a named checkpoint written by an earlier `checkpoint(name)`
|
|
11
|
+
* call — in this process or an entirely different one, since the registry
|
|
12
|
+
* lives on disk under the shared rightsize cache directory. No entry for
|
|
13
|
+
* `name` resolves to `undefined`. A corrupt entry is treated the same as
|
|
14
|
+
* absent, with a best-effort delete of the bad file.
|
|
15
|
+
*
|
|
16
|
+
* When the entry's own recorded backend matches the CURRENTLY active
|
|
17
|
+
* backend, the underlying artifact is probed via the backend's
|
|
18
|
+
* `hasCheckpoint` SPI before this resolves — an artifact that's gone (removed
|
|
19
|
+
* by hand, or by something outside this library) makes the entry stale: it's
|
|
20
|
+
* best-effort deleted and this resolves to `undefined`, the same as if it
|
|
21
|
+
* had never existed. A probe FAILURE (the backend call itself throws) is
|
|
22
|
+
* never swallowed into a `false` — only a confirmed "does not exist"
|
|
23
|
+
* resolves that way, so a probe failure propagates out of this call.
|
|
24
|
+
*
|
|
25
|
+
* When the entry's recorded backend DIFFERS from the active one, this
|
|
26
|
+
* returns the entry unprobed — an msb ref means nothing to a docker probe
|
|
27
|
+
* and vice versa. `GenericContainer.fromCheckpoint(cp).start()`'s own
|
|
28
|
+
* `CheckpointBackendMismatchError` gate stays the sole authority for that
|
|
29
|
+
* mismatch; this function must not force-resolve a backend the host may not
|
|
30
|
+
* even have.
|
|
31
|
+
*
|
|
32
|
+
* `name` is validated against `CHECKPOINT_NAME_PATTERN` before anything else
|
|
33
|
+
* — including before the registry file is even looked up — so a `name`
|
|
34
|
+
* carrying `../` segments can never reach path construction; an invalid name
|
|
35
|
+
* throws `InvalidCheckpointNameError` and touches no file.
|
|
36
|
+
*/
|
|
37
|
+
export async function find(name) {
|
|
38
|
+
requireValidCheckpointName(name);
|
|
39
|
+
const dir = cacheDir();
|
|
40
|
+
const read = await readCheckpointRegistry(dir, name);
|
|
41
|
+
if (read.kind === "missing") {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
if (read.kind === "corrupt") {
|
|
45
|
+
await removeCheckpointRegistryFile(dir, name);
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
const entry = read.entry;
|
|
49
|
+
const active = Backends.active();
|
|
50
|
+
if (entry.backend !== active.name) {
|
|
51
|
+
return toCheckpoint(entry);
|
|
52
|
+
}
|
|
53
|
+
const exists = await active.hasCheckpoint(entry.ref);
|
|
54
|
+
if (!exists) {
|
|
55
|
+
await removeCheckpointRegistryFile(dir, name);
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
return toCheckpoint(entry);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Every named checkpoint currently in the registry — registry contents
|
|
62
|
+
* only, never probed against a backend (unlike `find`), so a stale entry
|
|
63
|
+
* whose artifact is gone still appears here until something calls `find` or
|
|
64
|
+
* `remove` on it. A corrupt entry is silently skipped, never removed (only
|
|
65
|
+
* `find`/`remove` clean those up, since `list` never resolves a single name
|
|
66
|
+
* the caller could target for a retry).
|
|
67
|
+
*/
|
|
68
|
+
export async function list() {
|
|
69
|
+
const dir = cacheDir();
|
|
70
|
+
const names = await listCheckpointNames(dir);
|
|
71
|
+
const checkpoints = [];
|
|
72
|
+
for (const name of names) {
|
|
73
|
+
const read = await readCheckpointRegistry(dir, name);
|
|
74
|
+
if (read.kind === "found") {
|
|
75
|
+
checkpoints.push(toCheckpoint(read.entry));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return checkpoints;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Deletes a named checkpoint: best-effort removal of the backend artifact
|
|
82
|
+
* (only when the entry's recorded backend matches the currently active
|
|
83
|
+
* one — this call never touches a backend that isn't active) plus the
|
|
84
|
+
* registry file, regardless of order of failure in either. Idempotent and
|
|
85
|
+
* always best-effort: "not found" anywhere (no registry entry at all) is
|
|
86
|
+
* success, reported as `false`; an existing entry — valid or corrupt —
|
|
87
|
+
* reports `true` once its registry file is gone.
|
|
88
|
+
*
|
|
89
|
+
* When the entry's recorded backend DIFFERS from the currently active one,
|
|
90
|
+
* only the registry record is deleted — the underlying artifact (the docker
|
|
91
|
+
* image, or the microsandbox snapshot) is left on disk PERMANENTLY, since
|
|
92
|
+
* this call never touches a backend that isn't active. Nothing in this
|
|
93
|
+
* library reclaims it automatically — and once the record is gone, a later
|
|
94
|
+
* `remove(name)` finds nothing to act on. Remove a checkpoint under its
|
|
95
|
+
* creating backend in the first place, or clean the leftover artifact
|
|
96
|
+
* directly with that backend's own CLI one-liner (see the
|
|
97
|
+
* [checkpoints guide](/guide/checkpoints#cleanup-checkpoints-are-not-auto-reaped)).
|
|
98
|
+
*
|
|
99
|
+
* `name` is validated against `CHECKPOINT_NAME_PATTERN` before anything else
|
|
100
|
+
* — including before the registry file is even looked up — so a `name`
|
|
101
|
+
* carrying `../` segments can never reach path construction; an invalid name
|
|
102
|
+
* throws `InvalidCheckpointNameError` and touches no file.
|
|
103
|
+
*/
|
|
104
|
+
export async function remove(name) {
|
|
105
|
+
requireValidCheckpointName(name);
|
|
106
|
+
const dir = cacheDir();
|
|
107
|
+
const read = await readCheckpointRegistry(dir, name);
|
|
108
|
+
if (read.kind === "missing") {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
if (read.kind === "corrupt") {
|
|
112
|
+
await removeCheckpointRegistryFile(dir, name);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
const entry = read.entry;
|
|
116
|
+
const active = Backends.active();
|
|
117
|
+
if (entry.backend === active.name) {
|
|
118
|
+
await active.removeCheckpoint(entry.ref).catch(() => { });
|
|
119
|
+
}
|
|
120
|
+
await removeCheckpointRegistryFile(dir, name);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* The library's entry point for rediscovering NAMED checkpoints across
|
|
125
|
+
* processes — see the [checkpoints guide](/guide/checkpoints#reusing-checkpoints-across-runs)
|
|
126
|
+
* for the `find(...) ?? seed()` first-run/later-run pattern this exists to
|
|
127
|
+
* support. Unnamed `checkpoint()` calls never appear here; only a
|
|
128
|
+
* `checkpoint(name)` call writes a registry entry these functions can find.
|
|
129
|
+
*/
|
|
130
|
+
export const Checkpoints = {
|
|
131
|
+
/** Rediscovers a named checkpoint — see `find` above. */
|
|
132
|
+
find,
|
|
133
|
+
/** Every named checkpoint currently in the registry — see `list` above. */
|
|
134
|
+
list,
|
|
135
|
+
/** Deletes a named checkpoint — see `remove` above. */
|
|
136
|
+
remove,
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/core/checkpoint/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pinned identically across every rightsize language implementation (see the
|
|
3
|
+
* named-checkpoints spec's own "Names and refs" section): lowercase letters,
|
|
4
|
+
* digits, and hyphens only, starting with a letter or digit, at most 41
|
|
5
|
+
* characters. This is also exactly the alphabet both backends' ref formats
|
|
6
|
+
* embed verbatim (`rz-ckpt-<name>`, `rightsize/checkpoint:<name>`), so a
|
|
7
|
+
* valid name is guaranteed to produce a valid ref on either backend.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CHECKPOINT_NAME_PATTERN: RegExp;
|
|
10
|
+
/** Fails fast — before any backend or filesystem call — on a `name` that doesn't match `CHECKPOINT_NAME_PATTERN`. */
|
|
11
|
+
export declare function requireValidCheckpointName(name: string): void;
|
|
12
|
+
//# sourceMappingURL=name.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name.d.ts","sourceRoot":"","sources":["../../../src/core/checkpoint/name.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,QAA8B,CAAC;AAEnE,qHAAqH;AACrH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI7D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { InvalidCheckpointNameError } from "../errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pinned identically across every rightsize language implementation (see the
|
|
4
|
+
* named-checkpoints spec's own "Names and refs" section): lowercase letters,
|
|
5
|
+
* digits, and hyphens only, starting with a letter or digit, at most 41
|
|
6
|
+
* characters. This is also exactly the alphabet both backends' ref formats
|
|
7
|
+
* embed verbatim (`rz-ckpt-<name>`, `rightsize/checkpoint:<name>`), so a
|
|
8
|
+
* valid name is guaranteed to produce a valid ref on either backend.
|
|
9
|
+
*/
|
|
10
|
+
export const CHECKPOINT_NAME_PATTERN = /^[a-z0-9][a-z0-9-]{0,40}$/;
|
|
11
|
+
/** Fails fast — before any backend or filesystem call — on a `name` that doesn't match `CHECKPOINT_NAME_PATTERN`. */
|
|
12
|
+
export function requireValidCheckpointName(name) {
|
|
13
|
+
if (!CHECKPOINT_NAME_PATTERN.test(name)) {
|
|
14
|
+
throw new InvalidCheckpointNameError(name);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"name.js","sourceRoot":"","sources":["../../../src/core/checkpoint/name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,2BAA2B,CAAC;AAEnE,qHAAqH;AACrH,MAAM,UAAU,0BAA0B,CAAC,IAAY;IACrD,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,IAAI,0BAA0B,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mints the backend-specific checkpoint ref: `rz-ckpt-<suffix>` on
|
|
3
|
+
* microsandbox, `rightsize/checkpoint:<suffix>` elsewhere. `name` present
|
|
4
|
+
* (a NAMED checkpoint) makes the suffix — and therefore the whole ref —
|
|
5
|
+
* deterministic: re-checkpointing the same name reproduces the exact same
|
|
6
|
+
* ref, which is what makes the registry's replace semantics (remove the old
|
|
7
|
+
* artifact under this ref, then create the new one) correct. `name`
|
|
8
|
+
* `undefined` mints a fresh random 12-hex suffix instead, byte-for-byte the
|
|
9
|
+
* pre-named-checkpoints behavior.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkpointRef(backendName: string, name: string | undefined): string;
|
|
12
|
+
//# sourceMappingURL=ref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../../src/core/checkpoint/ref.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAGnF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Mints the backend-specific checkpoint ref: `rz-ckpt-<suffix>` on
|
|
4
|
+
* microsandbox, `rightsize/checkpoint:<suffix>` elsewhere. `name` present
|
|
5
|
+
* (a NAMED checkpoint) makes the suffix — and therefore the whole ref —
|
|
6
|
+
* deterministic: re-checkpointing the same name reproduces the exact same
|
|
7
|
+
* ref, which is what makes the registry's replace semantics (remove the old
|
|
8
|
+
* artifact under this ref, then create the new one) correct. `name`
|
|
9
|
+
* `undefined` mints a fresh random 12-hex suffix instead, byte-for-byte the
|
|
10
|
+
* pre-named-checkpoints behavior.
|
|
11
|
+
*/
|
|
12
|
+
export function checkpointRef(backendName, name) {
|
|
13
|
+
const suffix = name ?? randomBytes(6).toString("hex");
|
|
14
|
+
return backendName === "microsandbox" ? `rz-ckpt-${suffix}` : `rightsize/checkpoint:${suffix}`;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=ref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ref.js","sourceRoot":"","sources":["../../../src/core/checkpoint/ref.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB,EAAE,IAAwB;IACzE,MAAM,MAAM,GAAG,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,OAAO,WAAW,KAAK,cAAc,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC,CAAC,wBAAwB,MAAM,EAAE,CAAC;AACjG,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ContainerSpec } from "../model.js";
|
|
2
|
+
/**
|
|
3
|
+
* The reduced, cross-language-pinned subset of `ContainerSpec` a named
|
|
4
|
+
* checkpoint's registry entry carries — exactly the fields
|
|
5
|
+
* `GenericContainer.fromCheckpoint()` actually reads (env, command, exposed
|
|
6
|
+
* ports, memory limit), never the rest (name, image, host ports, mounts,
|
|
7
|
+
* network topology, `runId`, `keepAlive`). Field names and shapes are part
|
|
8
|
+
* of the wire format: `env` as a plain object (not an array of pairs, unlike
|
|
9
|
+
* `ContainerSpec.env`), `command` as an array or `null` (never `undefined` —
|
|
10
|
+
* JSON has no `undefined`), `exposedPorts` as guest ports only.
|
|
11
|
+
*/
|
|
12
|
+
export interface CheckpointRegistrySpec {
|
|
13
|
+
readonly env: Record<string, string>;
|
|
14
|
+
readonly command: ReadonlyArray<string> | null;
|
|
15
|
+
readonly exposedPorts: ReadonlyArray<number>;
|
|
16
|
+
readonly memoryLimitMb: number | null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* One `checkpoints/<name>.json` record: written atomically only after the
|
|
20
|
+
* backend checkpoint it describes has actually succeeded, and read by
|
|
21
|
+
* `Checkpoints.find`/`list`/`remove` in this process or a later one. Every
|
|
22
|
+
* field here is part of the cross-language contract pinned by the
|
|
23
|
+
* named-checkpoints spec — a Kotlin or Rust process must be able to parse
|
|
24
|
+
* exactly this shape.
|
|
25
|
+
*/
|
|
26
|
+
export interface CheckpointRegistryEntry {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly ref: string;
|
|
29
|
+
/** The backend that created this checkpoint (e.g. `"microsandbox"`, `"docker"`) — `find`/`remove` only probe/touch the artifact when this matches the CURRENTLY active backend. */
|
|
30
|
+
readonly backend: string;
|
|
31
|
+
readonly createdIso: string;
|
|
32
|
+
readonly spec: CheckpointRegistrySpec;
|
|
33
|
+
}
|
|
34
|
+
/** `<cacheDir>/checkpoints` — the directory every named checkpoint's registry file lives under. */
|
|
35
|
+
export declare function checkpointsDir(cacheDir: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* `checkpoints/<name>.json`. Validates `name` against
|
|
38
|
+
* `CHECKPOINT_NAME_PATTERN` itself (throwing `InvalidCheckpointNameError` on
|
|
39
|
+
* a miss) rather than trusting every caller to have done so already — this
|
|
40
|
+
* is the one function every registry read/write ultimately funnels through
|
|
41
|
+
* to build a path, so a defensive check here is what stands between a `../`
|
|
42
|
+
* name and a path that escapes `checkpoints/` even if some future caller
|
|
43
|
+
* forgets `requireValidCheckpointName` at its own boundary.
|
|
44
|
+
*/
|
|
45
|
+
export declare function checkpointRegistryPath(cacheDir: string, name: string): string;
|
|
46
|
+
/** The three outcomes reading a registry file can settle to — corrupt is deliberately distinct from missing, since `find`/`remove` react differently to each (see their own docs). */
|
|
47
|
+
export type CheckpointRegistryReadResult = {
|
|
48
|
+
readonly kind: "missing";
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: "corrupt";
|
|
51
|
+
} | {
|
|
52
|
+
readonly kind: "found";
|
|
53
|
+
readonly entry: CheckpointRegistryEntry;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Reads and parses `checkpoints/<name>.json`. `"missing"` means the file
|
|
57
|
+
* does not exist at all; `"corrupt"` means it exists but isn't a well-shaped
|
|
58
|
+
* `CheckpointRegistryEntry` — malformed JSON or a missing/mistyped required
|
|
59
|
+
* field. An invalid `name` (see `checkpointRegistryPath`) throws
|
|
60
|
+
* `InvalidCheckpointNameError` rather than resolving `"missing"` — the path
|
|
61
|
+
* is resolved BEFORE the file-read `try`, so that throw is never mistaken
|
|
62
|
+
* for an ordinary "no file here" miss.
|
|
63
|
+
*/
|
|
64
|
+
export declare function readCheckpointRegistry(cacheDir: string, name: string): Promise<CheckpointRegistryReadResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Atomically writes `checkpoints/<name>.json` (tmp file + rename, the same
|
|
67
|
+
* protocol as the reuse registry's `writeRegistryAtomic` and the reaping
|
|
68
|
+
* ledger's `writeRunRecord`) — called once, only after the backend
|
|
69
|
+
* checkpoint this entry describes has already succeeded. A concurrent reader
|
|
70
|
+
* only ever observes either the previous complete file (if this is a
|
|
71
|
+
* replace) or this one, never a partial write.
|
|
72
|
+
*/
|
|
73
|
+
export declare function writeCheckpointRegistryAtomic(cacheDir: string, name: string, entry: CheckpointRegistryEntry): Promise<void>;
|
|
74
|
+
/** Best-effort delete of `checkpoints/<name>.json`. A file already gone is not an error. */
|
|
75
|
+
export declare function removeCheckpointRegistryFile(cacheDir: string, name: string): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Every checkpoint name with a registry file on disk, derived from the
|
|
78
|
+
* directory listing itself (not from parsing) — includes names whose file
|
|
79
|
+
* turns out to be corrupt; `Checkpoints.list()` filters those out itself
|
|
80
|
+
* after reading each one. Excludes the atomic-write tmp files (`.<name>.json.tmp-...`),
|
|
81
|
+
* which sort before their target thanks to the leading dot but are never a
|
|
82
|
+
* real entry. `checkpoints/` not existing yet (nothing ever checkpointed
|
|
83
|
+
* with a name) is not an error — resolves to an empty list.
|
|
84
|
+
*/
|
|
85
|
+
export declare function listCheckpointNames(cacheDir: string): Promise<string[]>;
|
|
86
|
+
/**
|
|
87
|
+
* The write-side projection: `handle.spec` (a full `ContainerSpec`) down to
|
|
88
|
+
* the reduced, pinned shape the registry persists. `undefined` fields
|
|
89
|
+
* normalize to `null` (JSON has no `undefined`); `ports` keeps only the
|
|
90
|
+
* guest side (the source container's own host ports are never meaningful to
|
|
91
|
+
* a later restore, which allocates fresh ones).
|
|
92
|
+
*/
|
|
93
|
+
export declare function toCheckpointRegistrySpec(spec: ContainerSpec): CheckpointRegistrySpec;
|
|
94
|
+
/**
|
|
95
|
+
* The read-side counterpart: reconstructs a `ContainerSpec`-shaped object
|
|
96
|
+
* from a persisted `CheckpointRegistryEntry`, for handing back as a
|
|
97
|
+
* `Checkpoint`'s `spec` from `Checkpoints.find`/`list` (which never held the
|
|
98
|
+
* source container's actual `ContainerSpec`, only what the registry
|
|
99
|
+
* persisted). Only the four fields `GenericContainer.fromCheckpoint()`
|
|
100
|
+
* itself reads — `env`, `command`, `ports` (guest side only), and
|
|
101
|
+
* `memoryLimitMb` — carry real information; every other field is a stable
|
|
102
|
+
* placeholder, since the registry never persists it. `checkpointRef` mirrors
|
|
103
|
+
* what a live backend hands back after its own reboot-from-snapshot cycle:
|
|
104
|
+
* pointing at itself.
|
|
105
|
+
*/
|
|
106
|
+
export declare function fromCheckpointRegistryEntry(entry: CheckpointRegistryEntry): ContainerSpec;
|
|
107
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/checkpoint/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD;;;;;;;;;GASG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mLAAmL;IACnL,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;CACvC;AAED,mGAAmG;AACnG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7E;AAkDD,sLAAsL;AACtL,MAAM,MAAM,4BAA4B,GACpC;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAExE;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAkBlH;AAED;;;;;;;GAOG;AACH,wBAAsB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAOjI;AAED,4FAA4F;AAC5F,wBAAsB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhG;AAED;;;;;;;;GAQG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAQ7E;AAOD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,sBAAsB,CAWpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,uBAAuB,GAAG,aAAa,CAezF"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import * as fsp from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { requireValidCheckpointName } from "./name.js";
|
|
4
|
+
/** `<cacheDir>/checkpoints` — the directory every named checkpoint's registry file lives under. */
|
|
5
|
+
export function checkpointsDir(cacheDir) {
|
|
6
|
+
return path.join(cacheDir, "checkpoints");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* `checkpoints/<name>.json`. Validates `name` against
|
|
10
|
+
* `CHECKPOINT_NAME_PATTERN` itself (throwing `InvalidCheckpointNameError` on
|
|
11
|
+
* a miss) rather than trusting every caller to have done so already — this
|
|
12
|
+
* is the one function every registry read/write ultimately funnels through
|
|
13
|
+
* to build a path, so a defensive check here is what stands between a `../`
|
|
14
|
+
* name and a path that escapes `checkpoints/` even if some future caller
|
|
15
|
+
* forgets `requireValidCheckpointName` at its own boundary.
|
|
16
|
+
*/
|
|
17
|
+
export function checkpointRegistryPath(cacheDir, name) {
|
|
18
|
+
requireValidCheckpointName(name);
|
|
19
|
+
return path.join(checkpointsDir(cacheDir), `${name}.json`);
|
|
20
|
+
}
|
|
21
|
+
function isCheckpointRegistrySpec(value) {
|
|
22
|
+
if (typeof value !== "object" || value === null) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const rec = value;
|
|
26
|
+
const env = rec["env"];
|
|
27
|
+
if (typeof env !== "object" || env === null || Array.isArray(env)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (!Object.values(env).every((v) => typeof v === "string")) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const command = rec["command"];
|
|
34
|
+
if (command !== null && !(Array.isArray(command) && command.every((c) => typeof c === "string"))) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
const exposedPorts = rec["exposedPorts"];
|
|
38
|
+
if (!Array.isArray(exposedPorts) || !exposedPorts.every((p) => typeof p === "number")) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const memoryLimitMb = rec["memoryLimitMb"];
|
|
42
|
+
if (memoryLimitMb !== null && typeof memoryLimitMb !== "number") {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
function isCheckpointRegistryEntry(value) {
|
|
48
|
+
if (typeof value !== "object" || value === null) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
const rec = value;
|
|
52
|
+
if (typeof rec["name"] !== "string" ||
|
|
53
|
+
typeof rec["ref"] !== "string" ||
|
|
54
|
+
typeof rec["backend"] !== "string" ||
|
|
55
|
+
typeof rec["createdIso"] !== "string") {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return isCheckpointRegistrySpec(rec["spec"]);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reads and parses `checkpoints/<name>.json`. `"missing"` means the file
|
|
62
|
+
* does not exist at all; `"corrupt"` means it exists but isn't a well-shaped
|
|
63
|
+
* `CheckpointRegistryEntry` — malformed JSON or a missing/mistyped required
|
|
64
|
+
* field. An invalid `name` (see `checkpointRegistryPath`) throws
|
|
65
|
+
* `InvalidCheckpointNameError` rather than resolving `"missing"` — the path
|
|
66
|
+
* is resolved BEFORE the file-read `try`, so that throw is never mistaken
|
|
67
|
+
* for an ordinary "no file here" miss.
|
|
68
|
+
*/
|
|
69
|
+
export async function readCheckpointRegistry(cacheDir, name) {
|
|
70
|
+
const registryPath = checkpointRegistryPath(cacheDir, name);
|
|
71
|
+
let text;
|
|
72
|
+
try {
|
|
73
|
+
text = await fsp.readFile(registryPath, "utf8");
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return { kind: "missing" };
|
|
77
|
+
}
|
|
78
|
+
let parsed;
|
|
79
|
+
try {
|
|
80
|
+
parsed = JSON.parse(text);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return { kind: "corrupt" };
|
|
84
|
+
}
|
|
85
|
+
if (!isCheckpointRegistryEntry(parsed)) {
|
|
86
|
+
return { kind: "corrupt" };
|
|
87
|
+
}
|
|
88
|
+
return { kind: "found", entry: parsed };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Atomically writes `checkpoints/<name>.json` (tmp file + rename, the same
|
|
92
|
+
* protocol as the reuse registry's `writeRegistryAtomic` and the reaping
|
|
93
|
+
* ledger's `writeRunRecord`) — called once, only after the backend
|
|
94
|
+
* checkpoint this entry describes has already succeeded. A concurrent reader
|
|
95
|
+
* only ever observes either the previous complete file (if this is a
|
|
96
|
+
* replace) or this one, never a partial write.
|
|
97
|
+
*/
|
|
98
|
+
export async function writeCheckpointRegistryAtomic(cacheDir, name, entry) {
|
|
99
|
+
const dir = checkpointsDir(cacheDir);
|
|
100
|
+
await fsp.mkdir(dir, { recursive: true });
|
|
101
|
+
const target = checkpointRegistryPath(cacheDir, name);
|
|
102
|
+
const tmp = path.join(dir, `.${name}.json.tmp-${process.pid}-${Date.now()}`);
|
|
103
|
+
await fsp.writeFile(tmp, JSON.stringify(entry));
|
|
104
|
+
await fsp.rename(tmp, target);
|
|
105
|
+
}
|
|
106
|
+
/** Best-effort delete of `checkpoints/<name>.json`. A file already gone is not an error. */
|
|
107
|
+
export async function removeCheckpointRegistryFile(cacheDir, name) {
|
|
108
|
+
await fsp.unlink(checkpointRegistryPath(cacheDir, name)).catch(() => { });
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Every checkpoint name with a registry file on disk, derived from the
|
|
112
|
+
* directory listing itself (not from parsing) — includes names whose file
|
|
113
|
+
* turns out to be corrupt; `Checkpoints.list()` filters those out itself
|
|
114
|
+
* after reading each one. Excludes the atomic-write tmp files (`.<name>.json.tmp-...`),
|
|
115
|
+
* which sort before their target thanks to the leading dot but are never a
|
|
116
|
+
* real entry. `checkpoints/` not existing yet (nothing ever checkpointed
|
|
117
|
+
* with a name) is not an error — resolves to an empty list.
|
|
118
|
+
*/
|
|
119
|
+
export async function listCheckpointNames(cacheDir) {
|
|
120
|
+
let entries;
|
|
121
|
+
try {
|
|
122
|
+
entries = await fsp.readdir(checkpointsDir(cacheDir));
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
return entries.filter((f) => f.endsWith(".json") && !f.startsWith(".")).map((f) => f.slice(0, -".json".length));
|
|
128
|
+
}
|
|
129
|
+
/** The inverse of the env part of `toCheckpointRegistrySpec`: `Record<string,string>` back to the array-of-pairs shape `ContainerSpec.env` uses. */
|
|
130
|
+
function envRecordToPairs(env) {
|
|
131
|
+
return Object.entries(env);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The write-side projection: `handle.spec` (a full `ContainerSpec`) down to
|
|
135
|
+
* the reduced, pinned shape the registry persists. `undefined` fields
|
|
136
|
+
* normalize to `null` (JSON has no `undefined`); `ports` keeps only the
|
|
137
|
+
* guest side (the source container's own host ports are never meaningful to
|
|
138
|
+
* a later restore, which allocates fresh ones).
|
|
139
|
+
*/
|
|
140
|
+
export function toCheckpointRegistrySpec(spec) {
|
|
141
|
+
const env = {};
|
|
142
|
+
for (const [key, value] of spec.env) {
|
|
143
|
+
env[key] = value;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
env,
|
|
147
|
+
command: spec.command ?? null,
|
|
148
|
+
exposedPorts: spec.ports.map((p) => p.guestPort),
|
|
149
|
+
memoryLimitMb: spec.memoryLimitMb ?? null,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The read-side counterpart: reconstructs a `ContainerSpec`-shaped object
|
|
154
|
+
* from a persisted `CheckpointRegistryEntry`, for handing back as a
|
|
155
|
+
* `Checkpoint`'s `spec` from `Checkpoints.find`/`list` (which never held the
|
|
156
|
+
* source container's actual `ContainerSpec`, only what the registry
|
|
157
|
+
* persisted). Only the four fields `GenericContainer.fromCheckpoint()`
|
|
158
|
+
* itself reads — `env`, `command`, `ports` (guest side only), and
|
|
159
|
+
* `memoryLimitMb` — carry real information; every other field is a stable
|
|
160
|
+
* placeholder, since the registry never persists it. `checkpointRef` mirrors
|
|
161
|
+
* what a live backend hands back after its own reboot-from-snapshot cycle:
|
|
162
|
+
* pointing at itself.
|
|
163
|
+
*/
|
|
164
|
+
export function fromCheckpointRegistryEntry(entry) {
|
|
165
|
+
return {
|
|
166
|
+
name: entry.name,
|
|
167
|
+
image: entry.ref,
|
|
168
|
+
env: envRecordToPairs(entry.spec.env),
|
|
169
|
+
command: entry.spec.command ?? undefined,
|
|
170
|
+
ports: entry.spec.exposedPorts.map((guestPort) => ({ hostPort: 0, guestPort })),
|
|
171
|
+
mounts: [],
|
|
172
|
+
networkId: undefined,
|
|
173
|
+
aliases: [],
|
|
174
|
+
runId: "",
|
|
175
|
+
memoryLimitMb: entry.spec.memoryLimitMb ?? undefined,
|
|
176
|
+
keepAlive: false,
|
|
177
|
+
checkpointRef: entry.ref,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/checkpoint/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AAoCvD,mGAAmG;AACnG,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB,EAAE,IAAY;IACnE,0BAA0B,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAc;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,GAAG,GAAG,KAAgC,CAAC;IAE7C,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAClE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAA8B,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACvF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/B,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,EAAE,CAAC;QACjG,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,YAAY,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;QACtF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,aAAa,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;IAC3C,IAAI,aAAa,KAAK,IAAI,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,yBAAyB,CAAC,KAAc;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,IACE,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,QAAQ;QAC/B,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,QAAQ;QAC9B,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,QAAQ;QAClC,OAAO,GAAG,CAAC,YAAY,CAAC,KAAK,QAAQ,EACrC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,wBAAwB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/C,CAAC;AAQD;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,QAAgB,EAAE,IAAY;IACzE,MAAM,YAAY,GAAG,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC5D,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IACD,IAAI,CAAC,yBAAyB,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,QAAgB,EAAE,IAAY,EAAE,KAA8B;IAChH,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,aAAa,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC7E,MAAM,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAChD,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,4FAA4F;AAC5F,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,QAAgB,EAAE,IAAY;IAC/E,MAAM,GAAG,CAAC,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAAgB;IACxD,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAClH,CAAC;AAED,oJAAoJ;AACpJ,SAAS,gBAAgB,CAAC,GAA2B;IACnD,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAmB;IAC1D,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACpC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,OAAO;QACL,GAAG;QACH,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;QAC7B,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QAChD,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI;KAC1C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAA8B;IACxE,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,KAAK,CAAC,GAAG;QAChB,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;QACrC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,IAAI,SAAS;QACxC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/E,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,EAAE;QACT,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,SAAS;QACpD,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,KAAK,CAAC,GAAG;KACzB,CAAC;AACJ,CAAC"}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -77,10 +77,11 @@ export declare class IsolationRequiredError extends Error {
|
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
79
79
|
* Thrown by `checkpoint()` when the active backend's
|
|
80
|
-
* `capabilities.checkpoint` is `false` —
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* backend
|
|
80
|
+
* `capabilities.checkpoint` is `false` — both real backends (docker, image
|
|
81
|
+
* commit; microsandbox, disk snapshot) support it today, so this only fires
|
|
82
|
+
* against a backend that genuinely lacks the capability (a test double).
|
|
83
|
+
* Thrown before any backend call: the generic layer gates on the capability
|
|
84
|
+
* itself rather than letting the backend's own `createCheckpoint` reject.
|
|
84
85
|
*/
|
|
85
86
|
export declare class CheckpointUnsupportedError extends Error {
|
|
86
87
|
/** The active backend's name (e.g. `"microsandbox"`). */
|
|
@@ -89,4 +90,59 @@ export declare class CheckpointUnsupportedError extends Error {
|
|
|
89
90
|
/** The active backend's name (e.g. `"microsandbox"`). */
|
|
90
91
|
backend: string);
|
|
91
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Thrown by `GenericContainer.fromCheckpoint(cp).start()` when the active
|
|
95
|
+
* backend's name doesn't match the backend that created `cp` — a checkpoint
|
|
96
|
+
* ref is only meaningful to the backend that minted it (a docker image tag
|
|
97
|
+
* means nothing to `msb`, and a msb snapshot name means nothing to docker).
|
|
98
|
+
* Thrown before any backend call.
|
|
99
|
+
*/
|
|
100
|
+
export declare class CheckpointBackendMismatchError extends Error {
|
|
101
|
+
/** The backend that created the checkpoint. */
|
|
102
|
+
readonly createdOnBackend: string;
|
|
103
|
+
/** The backend `start()` actually resolved. */
|
|
104
|
+
readonly activeBackend: string;
|
|
105
|
+
constructor(
|
|
106
|
+
/** The backend that created the checkpoint. */
|
|
107
|
+
createdOnBackend: string,
|
|
108
|
+
/** The backend `start()` actually resolved. */
|
|
109
|
+
activeBackend: string);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Thrown at `start()` when a container built via `GenericContainer.fromCheckpoint()`
|
|
113
|
+
* is also marked `withReuse()` — reuse's identity hash never covers
|
|
114
|
+
* `checkpointRef`, so an adopted sandbox from an earlier process could never
|
|
115
|
+
* be verified against the checkpoint this container was meant to restore.
|
|
116
|
+
* Thrown only once reuse is actually double opt-in active, the same
|
|
117
|
+
* placement as `ReuseWithNetworkError`.
|
|
118
|
+
*/
|
|
119
|
+
export declare class ReuseFromCheckpointError extends Error {
|
|
120
|
+
constructor();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Thrown by `copyFileToContainer`/`copyContentToContainer`/
|
|
124
|
+
* `copyFileFromContainer` when `containerPath` is not absolute — both
|
|
125
|
+
* backends require an absolute `NAME:/path` shape, so a relative path can
|
|
126
|
+
* never reach either CLI. Thrown before any backend call.
|
|
127
|
+
*/
|
|
128
|
+
export declare class RelativeContainerPathError extends Error {
|
|
129
|
+
/** The rejected path, exactly as passed in. */
|
|
130
|
+
readonly containerPath: string;
|
|
131
|
+
constructor(
|
|
132
|
+
/** The rejected path, exactly as passed in. */
|
|
133
|
+
containerPath: string);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Thrown by `checkpoint(name)` when `name` doesn't match
|
|
137
|
+
* `^[a-z0-9][a-z0-9-]{0,40}$` — the same pattern pinned across every
|
|
138
|
+
* rightsize language implementation. Thrown before any backend or
|
|
139
|
+
* filesystem call, so a bad name never mints a ref or touches the registry.
|
|
140
|
+
*/
|
|
141
|
+
export declare class InvalidCheckpointNameError extends Error {
|
|
142
|
+
/** The rejected name, exactly as passed in. */
|
|
143
|
+
readonly checkpointName: string;
|
|
144
|
+
constructor(
|
|
145
|
+
/** The rejected name, exactly as passed in. */
|
|
146
|
+
checkpointName: string);
|
|
147
|
+
}
|
|
92
148
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAEhD,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,qFAAqF;IACrF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;;IALxB,uDAAuD;IAC9C,OAAO,EAAE,MAAM;IACxB,yDAAyD;IAChD,OAAO,EAAE,MAAM;IACxB,qFAAqF;IAC5E,MAAM,CAAC,EAAE,MAAM,YAAA;CAK3B;AAED;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAG5C,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;gBAFxB,OAAO,EAAE,MAAM;IACf,4FAA4F;IACnF,KAAK,CAAC,EAAE,OAAO,YAAA;CAK3B;AAED,gFAAgF;AAChF,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,8EAA8E;AAC9E,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED,kIAAkI;AAClI,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;;CAS/C;AAED;;;;;;GAMG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAE7C,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM;;IADxB,mDAAmD;IAC1C,OAAO,EAAE,MAAM;CAS3B;AAED
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAEhD,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,MAAM;IACxB,qFAAqF;IACrF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;;IALxB,uDAAuD;IAC9C,OAAO,EAAE,MAAM;IACxB,yDAAyD;IAChD,OAAO,EAAE,MAAM;IACxB,qFAAqF;IAC5E,MAAM,CAAC,EAAE,MAAM,YAAA;CAK3B;AAED;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IAG5C,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO;gBAFxB,OAAO,EAAE,MAAM;IACf,4FAA4F;IACnF,KAAK,CAAC,EAAE,OAAO,YAAA;CAK3B;AAED,gFAAgF;AAChF,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,8EAA8E;AAC9E,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B;AAED,kIAAkI;AAClI,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;;CAS/C;AAED;;;;;;GAMG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;IAE7C,mDAAmD;IACnD,QAAQ,CAAC,OAAO,EAAE,MAAM;;IADxB,mDAAmD;IAC1C,OAAO,EAAE,MAAM;CAS3B;AAED;;;;;;;GAOG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IAEjD,yDAAyD;IACzD,QAAQ,CAAC,OAAO,EAAE,MAAM;;IADxB,yDAAyD;IAChD,OAAO,EAAE,MAAM;CAQ3B;AAED;;;;;;GAMG;AACH,qBAAa,8BAA+B,SAAQ,KAAK;IAErD,+CAA+C;IAC/C,QAAQ,CAAC,gBAAgB,EAAE,MAAM;IACjC,+CAA+C;IAC/C,QAAQ,CAAC,aAAa,EAAE,MAAM;;IAH9B,+CAA+C;IACtC,gBAAgB,EAAE,MAAM;IACjC,+CAA+C;IACtC,aAAa,EAAE,MAAM;CASjC;AAED;;;;;;;GAOG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;;CASlD;AAED;;;;;GAKG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IAEjD,+CAA+C;IAC/C,QAAQ,CAAC,aAAa,EAAE,MAAM;;IAD9B,+CAA+C;IACtC,aAAa,EAAE,MAAM;CAKjC;AAED;;;;;GAKG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IAEjD,+CAA+C;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM;;IAD/B,+CAA+C;IACtC,cAAc,EAAE,MAAM;CASlC"}
|