@telorun/kernel 0.59.0 → 0.61.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/dist/bundle/files-integrity.d.ts +21 -12
- package/dist/bundle/files-integrity.d.ts.map +1 -1
- package/dist/bundle/files-integrity.js +27 -14
- package/dist/bundle/files-integrity.js.map +1 -1
- package/dist/bundle/module-artifact.d.ts +134 -0
- package/dist/bundle/module-artifact.d.ts.map +1 -0
- package/dist/bundle/module-artifact.js +300 -0
- package/dist/bundle/module-artifact.js.map +1 -0
- package/dist/bundle/module-manifest.d.ts +12 -4
- package/dist/bundle/module-manifest.d.ts.map +1 -1
- package/dist/bundle/module-manifest.js +8 -4
- package/dist/bundle/module-manifest.js.map +1 -1
- package/dist/controller-loader.d.ts +3 -2
- package/dist/controller-loader.d.ts.map +1 -1
- package/dist/controller-loader.js +8 -8
- package/dist/controller-loader.js.map +1 -1
- package/dist/controller-loaders/bundle-loader.d.ts +8 -6
- package/dist/controller-loaders/bundle-loader.d.ts.map +1 -1
- package/dist/controller-loaders/bundle-loader.js +52 -13
- package/dist/controller-loaders/bundle-loader.js.map +1 -1
- package/dist/controller-loaders/npm-loader.d.ts +0 -18
- package/dist/controller-loaders/npm-loader.d.ts.map +1 -1
- package/dist/controller-loaders/npm-loader.js +3 -190
- package/dist/controller-loaders/npm-loader.js.map +1 -1
- package/dist/controllers/resource-definition/resource-definition-controller.d.ts.map +1 -1
- package/dist/controllers/resource-definition/resource-definition-controller.js +6 -1
- package/dist/controllers/resource-definition/resource-definition-controller.js.map +1 -1
- package/dist/controllers/resource-definition/resource-inherited-controller.d.ts.map +1 -1
- package/dist/controllers/resource-definition/resource-inherited-controller.js +57 -10
- package/dist/controllers/resource-definition/resource-inherited-controller.js.map +1 -1
- package/dist/controllers/type/json-schema-controller.d.ts +8 -0
- package/dist/controllers/type/json-schema-controller.d.ts.map +1 -0
- package/dist/controllers/type/json-schema-controller.js +91 -0
- package/dist/controllers/type/json-schema-controller.js.map +1 -0
- package/dist/directory-lock.d.ts +27 -0
- package/dist/directory-lock.d.ts.map +1 -0
- package/dist/directory-lock.js +205 -0
- package/dist/directory-lock.js.map +1 -0
- package/dist/evaluation-context.d.ts +5 -0
- package/dist/evaluation-context.d.ts.map +1 -1
- package/dist/evaluation-context.js +63 -33
- package/dist/evaluation-context.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/init-failure-diagnostics.d.ts +61 -0
- package/dist/init-failure-diagnostics.d.ts.map +1 -0
- package/dist/init-failure-diagnostics.js +141 -0
- package/dist/init-failure-diagnostics.js.map +1 -0
- package/dist/invocation-contract-binding.d.ts +105 -0
- package/dist/invocation-contract-binding.d.ts.map +1 -0
- package/dist/invocation-contract-binding.js +296 -0
- package/dist/invocation-contract-binding.js.map +1 -0
- package/dist/kernel.d.ts +49 -0
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +117 -6
- package/dist/kernel.js.map +1 -1
- package/dist/manifest-sources/local-manifest-cache-source.d.ts +1 -1
- package/dist/manifest-sources/local-manifest-cache-source.d.ts.map +1 -1
- package/dist/manifest-sources/local-manifest-cache-source.js +1 -1
- package/dist/manifest-sources/local-manifest-cache-source.js.map +1 -1
- package/dist/module-context.d.ts.map +1 -1
- package/dist/module-context.js +21 -0
- package/dist/module-context.js.map +1 -1
- package/dist/resource-context.d.ts +61 -0
- package/dist/resource-context.d.ts.map +1 -1
- package/dist/resource-context.js +131 -0
- package/dist/resource-context.js.map +1 -1
- package/dist/schema-compiled-values.d.ts +9 -1
- package/dist/schema-compiled-values.d.ts.map +1 -1
- package/dist/schema-compiled-values.js +55 -16
- package/dist/schema-compiled-values.js.map +1 -1
- package/dist/schema-validator.d.ts.map +1 -1
- package/dist/schema-validator.js +15 -1
- package/dist/schema-validator.js.map +1 -1
- package/dist/transports/oci/oci-client.d.ts +28 -1
- package/dist/transports/oci/oci-client.d.ts.map +1 -1
- package/dist/transports/oci/oci-client.js +24 -1
- package/dist/transports/oci/oci-client.js.map +1 -1
- package/dist/transports/oci/oci-transport.d.ts +20 -14
- package/dist/transports/oci/oci-transport.d.ts.map +1 -1
- package/dist/transports/oci/oci-transport.js +105 -46
- package/dist/transports/oci/oci-transport.js.map +1 -1
- package/dist/transports/registry-transport.d.ts +7 -2
- package/dist/transports/registry-transport.d.ts.map +1 -1
- package/dist/transports/registry-transport.js +8 -33
- package/dist/transports/registry-transport.js.map +1 -1
- package/dist/transports/transport-registry.d.ts +5 -4
- package/dist/transports/transport-registry.d.ts.map +1 -1
- package/dist/transports/transport-registry.js +4 -4
- package/dist/transports/transport-registry.js.map +1 -1
- package/dist/transports/transport.d.ts +27 -19
- package/dist/transports/transport.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/bundle/files-integrity.ts +34 -14
- package/src/bundle/module-artifact.ts +375 -0
- package/src/bundle/module-manifest.ts +22 -6
- package/src/controller-loader.ts +9 -4
- package/src/controller-loaders/bundle-loader.ts +57 -11
- package/src/controller-loaders/npm-loader.ts +3 -209
- package/src/controllers/resource-definition/resource-definition-controller.ts +19 -0
- package/src/controllers/resource-definition/resource-inherited-controller.ts +69 -10
- package/src/controllers/type/json-schema-controller.ts +114 -0
- package/src/directory-lock.ts +225 -0
- package/src/evaluation-context.ts +81 -32
- package/src/index.ts +11 -2
- package/src/init-failure-diagnostics.ts +169 -0
- package/src/invocation-contract-binding.ts +392 -0
- package/src/kernel.ts +149 -6
- package/src/manifest-sources/local-manifest-cache-source.ts +1 -1
- package/src/module-context.ts +27 -0
- package/src/resource-context.ts +138 -0
- package/src/schema-compiled-values.ts +55 -15
- package/src/schema-validator.ts +15 -1
- package/src/transports/oci/oci-client.ts +32 -1
- package/src/transports/oci/oci-transport.ts +122 -51
- package/src/transports/registry-transport.ts +10 -38
- package/src/transports/transport-registry.ts +5 -5
- package/src/transports/transport.ts +32 -19
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseLayerIndex } from "@telorun/analyzer";
|
|
1
2
|
import { defaultCustomTags } from "@telorun/templating";
|
|
2
3
|
import { parseAllDocuments } from "yaml";
|
|
3
4
|
const OWNER_KINDS = new Set(["Telo.Application", "Telo.Library"]);
|
|
@@ -6,8 +7,9 @@ export function parseManifestDocs(text) {
|
|
|
6
7
|
return parseAllDocuments(text, { customTags: defaultCustomTags() });
|
|
7
8
|
}
|
|
8
9
|
/** The owner document of a manifest — the single `Telo.Application` /
|
|
9
|
-
* `Telo.Library` doc that carries its identity, `files:`, and
|
|
10
|
-
* The one place that selects it, shared by every
|
|
10
|
+
* `Telo.Library` doc that carries its identity, `files:` / `assets:`, and the
|
|
11
|
+
* published `layers:` index. The one place that selects it, shared by every
|
|
12
|
+
* reader/writer. */
|
|
11
13
|
export function findOwnerDoc(docs) {
|
|
12
14
|
return docs.find((d) => {
|
|
13
15
|
const kind = d.toJSON()?.kind;
|
|
@@ -16,16 +18,18 @@ export function findOwnerDoc(docs) {
|
|
|
16
18
|
}
|
|
17
19
|
/** Read the owner doc's identity + payload fields from a manifest, parsing once
|
|
18
20
|
* (never regex-scraping). The single source both transports call for the
|
|
19
|
-
* module's name and version,
|
|
21
|
+
* module's name and version, its layer index, and payload detection. */
|
|
20
22
|
export function readOwnerManifest(text) {
|
|
21
23
|
const owner = findOwnerDoc(parseManifestDocs(text));
|
|
22
24
|
const parsed = owner?.toJSON();
|
|
23
25
|
const md = parsed?.metadata ?? {};
|
|
24
26
|
const str = (v) => (typeof v === "string" ? v : undefined);
|
|
27
|
+
const patterns = (v) => Array.isArray(v) ? v.filter((p) => typeof p === "string") : [];
|
|
25
28
|
return {
|
|
26
29
|
name: str(md.name),
|
|
27
30
|
version: str(md.version),
|
|
28
|
-
|
|
31
|
+
layers: parsed?.layers === undefined ? undefined : parseLayerIndex(parsed.layers),
|
|
32
|
+
assetPatterns: patterns(parsed?.assets),
|
|
29
33
|
declaresFiles: Array.isArray(parsed?.files) && parsed.files.length > 0,
|
|
30
34
|
description: str(md.description),
|
|
31
35
|
repository: str(md.repository),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-manifest.js","sourceRoot":"","sources":["../../src/bundle/module-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAiB,MAAM,MAAM,CAAC;AAExD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC,CAAC;AAElE,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,iBAAiB,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;AACtE,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"module-manifest.js","sourceRoot":"","sources":["../../src/bundle/module-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAiB,MAAM,MAAM,CAAC;AAExD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC,CAAC;AAElE,8EAA8E;AAC9E,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,iBAAiB,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;AACtE,CAAC;AAED;;;qBAGqB;AACrB,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;QACrB,MAAM,IAAI,GAAI,CAAC,CAAC,MAAM,EAA+B,EAAE,IAAI,CAAC;QAC5D,OAAO,IAAI,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC;AAwBD;;yEAEyE;AACzE,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,KAAK,GAAG,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,KAAK,EAAE,MAAM,EAOf,CAAC;IACd,MAAM,EAAE,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,CAAC,CAAU,EAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACxF,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAY,EAAE,CACxC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC;QAClB,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;QACxB,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC;QACjF,aAAa,EAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACvC,aAAa,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QACtE,WAAW,EAAE,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC;QAChC,UAAU,EAAE,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC;QAC9B,OAAO,EAAE,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;QACxB,aAAa,EAAE,GAAG,CAAC,EAAE,CAAC,aAAa,CAAC;KACrC,CAAC;AACJ,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ControllerInstance, type Logger } from "@telorun/sdk";
|
|
2
|
+
import type { ModuleArtifact } from "./bundle/module-artifact.js";
|
|
2
3
|
import { ControllerPolicy } from "./runtime-registry.js";
|
|
3
4
|
export type { ControllerPolicy } from "./runtime-registry.js";
|
|
4
5
|
/**
|
|
@@ -104,7 +105,7 @@ export declare class ControllerLoader {
|
|
|
104
105
|
private readonly napiLoader;
|
|
105
106
|
private readonly bundleLoader;
|
|
106
107
|
constructor(options?: ControllerLoaderOptions);
|
|
107
|
-
load(purlCandidates: string[], baseUri: string, policy?: ControllerPolicy): Promise<ControllerInstance>;
|
|
108
|
+
load(purlCandidates: string[], baseUri: string, policy?: ControllerPolicy, artifact?: ModuleArtifact): Promise<ControllerInstance>;
|
|
108
109
|
/**
|
|
109
110
|
* Resolve a controller without importing it: pick the first candidate this
|
|
110
111
|
* environment can host (same ordering + env-missing fallback as {@link load}),
|
|
@@ -118,7 +119,7 @@ export declare class ControllerLoader {
|
|
|
118
119
|
* load actually happens. A total resolution failure throws (the boot-time
|
|
119
120
|
* fail-fast), mirroring {@link load}'s aggregated error.
|
|
120
121
|
*/
|
|
121
|
-
resolve(purlCandidates: string[], baseUri: string, policy?: ControllerPolicy): Promise<ResolvedController>;
|
|
122
|
+
resolve(purlCandidates: string[], baseUri: string, policy?: ControllerPolicy, artifact?: ModuleArtifact): Promise<ResolvedController>;
|
|
122
123
|
private dispatchOne;
|
|
123
124
|
private dispatchResolveOne;
|
|
124
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller-loader.d.ts","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAgB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"controller-loader.d.ts","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAgB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAmC,MAAM,uBAAuB,CAAC;AAE1F,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAC/B,OAAO,GACP,cAAc,GACd,OAAO,GACP,aAAa,GACb,aAAa,GACb,QAAQ,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,uBAAuB,CAAC;IAChC,cAAc,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACnD;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxD;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF,GACD;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE;AAC5E;;;;;;GAMG;GACD;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1F,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;kDAE8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;2DAGuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyB;gBAE1C,OAAO,GAAE,uBAA4B;IAW3C,IAAI,CACR,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,gBAAgB,EACzB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,kBAAkB,CAAC;IAqD9B;;;;;;;;;;;;OAYG;IACG,OAAO,CACX,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,gBAAgB,EACzB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,kBAAkB,CAAC;YA+BhB,WAAW;YASX,kBAAkB;CAgBjC"}
|
|
@@ -32,7 +32,7 @@ export class ControllerLoader {
|
|
|
32
32
|
this.napiLoader = new NapiControllerLoader();
|
|
33
33
|
this.bundleLoader = new BundleControllerLoader();
|
|
34
34
|
}
|
|
35
|
-
async load(purlCandidates, baseUri, policy) {
|
|
35
|
+
async load(purlCandidates, baseUri, policy, artifact) {
|
|
36
36
|
if (!purlCandidates || purlCandidates.length === 0) {
|
|
37
37
|
throw new RuntimeError("ERR_CONTROLLER_NOT_FOUND", "Missing controller PURL candidates");
|
|
38
38
|
}
|
|
@@ -46,7 +46,7 @@ export class ControllerLoader {
|
|
|
46
46
|
await this.emit?.({ name: "ControllerLoading", payload: { purl } });
|
|
47
47
|
const startedAt = Date.now();
|
|
48
48
|
try {
|
|
49
|
-
const { instance, source } = await this.dispatchOne(purl, baseUri);
|
|
49
|
+
const { instance, source } = await this.dispatchOne(purl, baseUri, artifact);
|
|
50
50
|
await this.emit?.({
|
|
51
51
|
name: "ControllerLoaded",
|
|
52
52
|
payload: { purl, source, durationMs: Date.now() - startedAt },
|
|
@@ -94,7 +94,7 @@ export class ControllerLoader {
|
|
|
94
94
|
* load actually happens. A total resolution failure throws (the boot-time
|
|
95
95
|
* fail-fast), mirroring {@link load}'s aggregated error.
|
|
96
96
|
*/
|
|
97
|
-
async resolve(purlCandidates, baseUri, policy) {
|
|
97
|
+
async resolve(purlCandidates, baseUri, policy, artifact) {
|
|
98
98
|
if (!purlCandidates || purlCandidates.length === 0) {
|
|
99
99
|
throw new RuntimeError("ERR_CONTROLLER_NOT_FOUND", "Missing controller PURL candidates");
|
|
100
100
|
}
|
|
@@ -106,7 +106,7 @@ export class ControllerLoader {
|
|
|
106
106
|
const errors = [];
|
|
107
107
|
for (const purl of ordered) {
|
|
108
108
|
try {
|
|
109
|
-
const { source, importInstance } = await this.dispatchResolveOne(purl, baseUri);
|
|
109
|
+
const { source, importInstance } = await this.dispatchResolveOne(purl, baseUri, artifact);
|
|
110
110
|
return { purl, source, importInstance };
|
|
111
111
|
}
|
|
112
112
|
catch (err) {
|
|
@@ -119,11 +119,11 @@ export class ControllerLoader {
|
|
|
119
119
|
}
|
|
120
120
|
throw new RuntimeError("ERR_CONTROLLER_NOT_FOUND", `No controller resolved. Tried ${ordered.length} candidate(s):\n${errors.join("\n")}`);
|
|
121
121
|
}
|
|
122
|
-
async dispatchOne(purl, baseUri) {
|
|
123
|
-
const { source, importInstance } = await this.dispatchResolveOne(purl, baseUri);
|
|
122
|
+
async dispatchOne(purl, baseUri, artifact) {
|
|
123
|
+
const { source, importInstance } = await this.dispatchResolveOne(purl, baseUri, artifact);
|
|
124
124
|
return { instance: await importInstance(), source };
|
|
125
125
|
}
|
|
126
|
-
async dispatchResolveOne(purl, baseUri) {
|
|
126
|
+
async dispatchResolveOne(purl, baseUri, artifact) {
|
|
127
127
|
if (purl.startsWith("pkg:npm")) {
|
|
128
128
|
return this.npmLoader.resolve(purl, baseUri);
|
|
129
129
|
}
|
|
@@ -131,7 +131,7 @@ export class ControllerLoader {
|
|
|
131
131
|
return this.napiLoader.resolve(purl, baseUri);
|
|
132
132
|
}
|
|
133
133
|
if (purl.startsWith("pkg:telo")) {
|
|
134
|
-
return this.bundleLoader.resolve(purl, baseUri);
|
|
134
|
+
return this.bundleLoader.resolve(purl, baseUri, artifact);
|
|
135
135
|
}
|
|
136
136
|
throw new ControllerEnvMissingError(`Unsupported PURL scheme: ${purl}`);
|
|
137
137
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller-loader.js","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAe,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"controller-loader.js","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ControllerInstance } from "@telorun/sdk";
|
|
2
|
+
import { type ModuleArtifact } from "../bundle/module-artifact.js";
|
|
2
3
|
import type { ControllerResolveSource } from "../controller-loader.js";
|
|
3
4
|
/**
|
|
4
5
|
* Loads a `pkg:telo` controller — a controller delivered inside the module's own
|
|
@@ -37,17 +38,18 @@ import type { ControllerResolveSource } from "../controller-loader.js";
|
|
|
37
38
|
* through); a bundle that loads but is malformed is a hard `ERR_CONTROLLER_INVALID`.
|
|
38
39
|
*/
|
|
39
40
|
export declare class BundleControllerLoader {
|
|
40
|
-
load(purl: string, baseUri: string): Promise<{
|
|
41
|
+
load(purl: string, baseUri: string, artifact?: ModuleArtifact): Promise<{
|
|
41
42
|
instance: ControllerInstance;
|
|
42
43
|
source: ControllerResolveSource;
|
|
43
44
|
}>;
|
|
44
45
|
/**
|
|
45
|
-
* Resolve without importing: parse + validate the PURL,
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* into the returned `importInstance` thunk.
|
|
46
|
+
* Resolve without importing: parse + validate the PURL, reject a candidate this
|
|
47
|
+
* host cannot run, materialize the layer that carries it, confirm the file
|
|
48
|
+
* exists, and ensure the realm symlinks — all fail-fast checks — but defer the
|
|
49
|
+
* bundle `import()` (the eval cost) into the returned `importInstance` thunk.
|
|
50
|
+
* Used by lazy controller loading.
|
|
49
51
|
*/
|
|
50
|
-
resolve(purl: string, baseUri: string): Promise<{
|
|
52
|
+
resolve(purl: string, baseUri: string, artifact?: ModuleArtifact): Promise<{
|
|
51
53
|
source: ControllerResolveSource;
|
|
52
54
|
importInstance: () => Promise<ControllerInstance>;
|
|
53
55
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle-loader.d.ts","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bundle-loader.d.ts","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAgB,MAAM,cAAc,CAAC;AAOhE,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAsGvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,qBAAa,sBAAsB;IAC3B,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC;QAAE,QAAQ,EAAE,kBAAkB,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAA;KAAE,CAAC;IAK7E;;;;;;OAMG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC;QAAE,MAAM,EAAE,uBAAuB,CAAC;QAAC,cAAc,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAA;KAAE,CAAC;CAqHnG"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { describeSelector, selectorFromQualifiers, selectorMatches } from "@telorun/analyzer";
|
|
1
2
|
import { RuntimeError } from "@telorun/sdk";
|
|
2
3
|
import { existsSync, readFileSync } from "fs";
|
|
3
4
|
import * as fs from "fs/promises";
|
|
@@ -5,8 +6,15 @@ import { createRequire } from "module";
|
|
|
5
6
|
import { PackageURL } from "packageurl-js";
|
|
6
7
|
import * as path from "path";
|
|
7
8
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
9
|
+
import { hostPlatformTarget } from "../bundle/module-artifact.js";
|
|
8
10
|
import { ControllerEnvMissingError } from "./napi-loader.js";
|
|
9
11
|
import { REALM_COLLAPSE_NAMES } from "./realm.js";
|
|
12
|
+
/** A base URI whose files are already on disk: a `file://` URL or a bare
|
|
13
|
+
* absolute path. Everything else (`oci://`, `http(s)://`, `memory://`) names a
|
|
14
|
+
* module whose payload only exists inside an artifact. */
|
|
15
|
+
function isLocalBase(baseUri) {
|
|
16
|
+
return baseUri.startsWith("file://") || path.isAbsolute(baseUri);
|
|
17
|
+
}
|
|
10
18
|
async function pathExists(filePath) {
|
|
11
19
|
try {
|
|
12
20
|
await fs.access(filePath);
|
|
@@ -144,17 +152,18 @@ function findPackageRoot(entryFile, name) {
|
|
|
144
152
|
* through); a bundle that loads but is malformed is a hard `ERR_CONTROLLER_INVALID`.
|
|
145
153
|
*/
|
|
146
154
|
export class BundleControllerLoader {
|
|
147
|
-
async load(purl, baseUri) {
|
|
148
|
-
const { source, importInstance } = await this.resolve(purl, baseUri);
|
|
155
|
+
async load(purl, baseUri, artifact) {
|
|
156
|
+
const { source, importInstance } = await this.resolve(purl, baseUri, artifact);
|
|
149
157
|
return { instance: await importInstance(), source };
|
|
150
158
|
}
|
|
151
159
|
/**
|
|
152
|
-
* Resolve without importing: parse + validate the PURL,
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
* into the returned `importInstance` thunk.
|
|
160
|
+
* Resolve without importing: parse + validate the PURL, reject a candidate this
|
|
161
|
+
* host cannot run, materialize the layer that carries it, confirm the file
|
|
162
|
+
* exists, and ensure the realm symlinks — all fail-fast checks — but defer the
|
|
163
|
+
* bundle `import()` (the eval cost) into the returned `importInstance` thunk.
|
|
164
|
+
* Used by lazy controller loading.
|
|
156
165
|
*/
|
|
157
|
-
async resolve(purl, baseUri) {
|
|
166
|
+
async resolve(purl, baseUri, artifact) {
|
|
158
167
|
let parsed;
|
|
159
168
|
try {
|
|
160
169
|
parsed = PackageURL.fromString(purl);
|
|
@@ -179,13 +188,43 @@ export class BundleControllerLoader {
|
|
|
179
188
|
if (!relPath) {
|
|
180
189
|
throw new ControllerEnvMissingError(`pkg:telo controller "${purl}" is missing a "path" qualifier`);
|
|
181
190
|
}
|
|
182
|
-
//
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
191
|
+
// Platform gate, BEFORE any materialization. A candidate list names one
|
|
192
|
+
// binary per platform, so checking the host first is what keeps a fallthrough
|
|
193
|
+
// from downloading every platform's layer on the way to the right one.
|
|
194
|
+
const selector = selectorFromQualifiers(format, parsed.qualifiers, `controller "${purl}"`);
|
|
195
|
+
const host = hostPlatformTarget();
|
|
196
|
+
if (!selectorMatches(selector, host)) {
|
|
197
|
+
throw new ControllerEnvMissingError(`pkg:telo controller "${purl}" targets ${describeSelector(selector)}, which does not ` +
|
|
198
|
+
`match this host (${host.os ?? "unknown os"}/${host.arch ?? "unknown arch"}` +
|
|
199
|
+
`${host.libc ? `/${host.libc}` : ""})`);
|
|
200
|
+
}
|
|
201
|
+
// A published module's payload lives in its artifact, so materialize the one
|
|
202
|
+
// layer carrying this candidate and resolve `path=` inside it. Nothing is
|
|
203
|
+
// fetched here: the artifact handle owns the pinned ref and the verified
|
|
204
|
+
// layer index, so an `oci://` module ref never reaches this loader as a path.
|
|
205
|
+
let bundleDir;
|
|
206
|
+
if (artifact) {
|
|
207
|
+
// By its own selector, not by re-matching the host: this candidate IS one
|
|
208
|
+
// selector, and it is exactly the key of the layer that carries it.
|
|
209
|
+
const layer = await artifact.materializeController(selector);
|
|
210
|
+
if (!layer) {
|
|
211
|
+
throw new ControllerEnvMissingError(`pkg:telo controller "${purl}": the module artifact ships no layer for ` +
|
|
212
|
+
`${describeSelector(selector)} (has: ${artifact.describeLayers()})`);
|
|
213
|
+
}
|
|
214
|
+
bundleDir = layer.dir;
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// No artifact: a module already on disk (local development, or a manifest
|
|
218
|
+
// served from the on-disk cache). Its files sit next to the manifest.
|
|
219
|
+
if (!isLocalBase(baseUri)) {
|
|
220
|
+
throw new ControllerEnvMissingError(`pkg:telo controller "${purl}" cannot be located: the declaring module resolved from ` +
|
|
221
|
+
`"${baseUri}", which is neither a local path nor an artifact with a layer index. ` +
|
|
222
|
+
`A bundled controller ships in its module's artifact — republish the module, or ` +
|
|
223
|
+
`import it from a local path during development.`);
|
|
224
|
+
}
|
|
225
|
+
bundleDir = path.dirname(baseUri.startsWith("file://") ? fileURLToPath(baseUri) : baseUri);
|
|
186
226
|
}
|
|
187
|
-
const
|
|
188
|
-
const absFile = path.resolve(path.dirname(basePath), relPath);
|
|
227
|
+
const absFile = path.resolve(bundleDir, relPath);
|
|
189
228
|
if (!(await pathExists(absFile))) {
|
|
190
229
|
throw new ControllerEnvMissingError(`pkg:telo controller bundle not found at "${absFile}" (from "${purl}")`);
|
|
191
230
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle-loader.js","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"bundle-loader.js","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -139,20 +139,6 @@ export declare class NpmControllerLoader {
|
|
|
139
139
|
*/
|
|
140
140
|
private installPackage;
|
|
141
141
|
}
|
|
142
|
-
/**
|
|
143
|
-
* Acquire the install lock for `installRoot` and run `fn` under it: first the
|
|
144
|
-
* in-process queue above, then the cross-process filesystem lock.
|
|
145
|
-
*/
|
|
146
|
-
declare function withInstallLock<T>(installRoot: string, fn: () => Promise<T>, log?: Logger): Promise<T>;
|
|
147
|
-
/**
|
|
148
|
-
* If the lock at `lockPath` is stale (mtime older than {@link LOCK_STALE_MS}, so
|
|
149
|
-
* its holder stopped heartbeating), atomically claim and remove it and return
|
|
150
|
-
* true; otherwise return false. The claim is a `rename` to a unique tombstone:
|
|
151
|
-
* `rename` is atomic and fails for all but one racer, so two processes that
|
|
152
|
-
* both observe the same stale lock cannot both reclaim it — the loser's rename
|
|
153
|
-
* throws ENOENT (the file is already gone) and it simply retries the open.
|
|
154
|
-
*/
|
|
155
|
-
declare function reclaimIfStale(lockPath: string): Promise<boolean>;
|
|
156
142
|
/**
|
|
157
143
|
* Decide where the per-kernel install root lives for a given entry URL.
|
|
158
144
|
*
|
|
@@ -231,10 +217,6 @@ export declare const __testing__: {
|
|
|
231
217
|
resolveExportTargetValue: typeof resolveExportTargetValue;
|
|
232
218
|
tryResolveFile: typeof tryResolveFile;
|
|
233
219
|
computeInstallRoot: typeof computeInstallRoot;
|
|
234
|
-
withInstallLock: typeof withInstallLock;
|
|
235
|
-
reclaimIfStale: typeof reclaimIfStale;
|
|
236
|
-
LOCK_STALE_MS: number;
|
|
237
|
-
LOCK_HEARTBEAT_MS: number;
|
|
238
220
|
EXPORTS_MAX_DEPTH: number;
|
|
239
221
|
DEFAULT_RESOLVER_CONDITIONS: readonly string[];
|
|
240
222
|
REALM_COLLAPSE_NAMES: readonly string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npm-loader.d.ts","sourceRoot":"","sources":["../../src/controller-loaders/npm-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAe,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AA+
|
|
1
|
+
{"version":3,"file":"npm-loader.d.ts","sourceRoot":"","sources":["../../src/controller-loaders/npm-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAe,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AA+C5E;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,cAAc,GAAG,aAAa,GAAG,OAAO,CAAC;AAoBlF,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,mBAAmB;IAC9B;;mEAE+D;IAC/D,OAAO,CAAC,GAAG,CAAuB;IAElC,mEAAmE;IACnE,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAI5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAS;IACnC,kFAAkF;IAClF,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAS;IAE9C;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IAEpD;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoC;IAE7D;;;;OAIG;IACH,OAAO,CAAC,SAAS,CAAC,CAAkB;IAEpC;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ,CAA8B;gBAElC,OAAO,GAAE,0BAA+B;IAK9C,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAKjE;;;;;OAKG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAC;QAAC,cAAc,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAA;KAAE,CAAC;IA2B3F;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;YAUX,sBAAsB;IAqFpC;;;;;;;OAOG;YACW,aAAa;IAe3B;;;;;;;;;;;;;;OAcG;YACW,cAAc;CAuH7B;AAqHD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,iBAAS,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA4BpD;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iBAAS,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMzE;AAED;;;;;;GAMG;AACH,iBAAS,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAKpE;AAuLD;;;;GAIG;AACH,iBAAe,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOrE;AAED,iBAAS,0BAA0B,CACjC,YAAY,EAAE,GAAG,EACjB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,GAChC,MAAM,GAAG,IAAI,CAIf;AAED,iBAAS,wBAAwB,CAC/B,MAAM,EAAE,GAAG,EACX,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,EACjC,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAoBf;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;CAUvB,CAAC"}
|
|
@@ -10,6 +10,7 @@ import { fileURLToPath, pathToFileURL } from "url";
|
|
|
10
10
|
import { promisify } from "util";
|
|
11
11
|
import { hostEnv } from "../host-env.js";
|
|
12
12
|
import { tryBuildControllerBundle } from "./bundle-builder.js";
|
|
13
|
+
import { withDirectoryLock } from "../directory-lock.js";
|
|
13
14
|
import { ControllerEnvMissingError } from "./napi-loader.js";
|
|
14
15
|
import { REALM_COLLAPSE_NAMES } from "./realm.js";
|
|
15
16
|
const execFileAsync = promisify(execFile);
|
|
@@ -38,36 +39,6 @@ const PEER_INSTALL_FLAGS = PACKAGE_MANAGER === "npm"
|
|
|
38
39
|
: PACKAGE_MANAGER === "pnpm"
|
|
39
40
|
? ["--no-strict-peer-dependencies"]
|
|
40
41
|
: [];
|
|
41
|
-
/**
|
|
42
|
-
* A held lock is refreshed (its mtime bumped) every {@link LOCK_HEARTBEAT_MS}
|
|
43
|
-
* by the holder. Staleness is judged purely by mtime age — a lock older than
|
|
44
|
-
* this means the holder stopped heartbeating (crashed, was killed, or its
|
|
45
|
-
* container vanished), so it is safe to reclaim. This deliberately does NOT
|
|
46
|
-
* probe the recorded PID for liveness: PID identity is meaningless across
|
|
47
|
-
* container restarts and PID namespaces (deterministic PID reuse makes an
|
|
48
|
-
* unrelated process look like the dead holder on the same hostname), which is
|
|
49
|
-
* exactly what deadlocked container boots. The `{pid, host}` in the lock body
|
|
50
|
-
* is diagnostics for humans, never a reclaim signal. Must be comfortably
|
|
51
|
-
* larger than the heartbeat interval so a briefly-descheduled holder (GC
|
|
52
|
-
* pause, busy event loop) is not reclaimed out from under itself.
|
|
53
|
-
*/
|
|
54
|
-
const LOCK_STALE_MS = 30000;
|
|
55
|
-
/** How often the holder refreshes the lock mtime while `fn` runs. Well under
|
|
56
|
-
* {@link LOCK_STALE_MS} so several heartbeats are missed before a live holder
|
|
57
|
-
* is ever judged stale. */
|
|
58
|
-
const LOCK_HEARTBEAT_MS = 5000;
|
|
59
|
-
/**
|
|
60
|
-
* Total wall-clock cap for waiting on the install lock — enough for a slow
|
|
61
|
-
* first install on a peer process to finish, short enough that a genuinely
|
|
62
|
-
* deadlocked CI job fails loudly rather than hanging for hours. The retry
|
|
63
|
-
* interval trades wakeup latency vs. wasted polls; 500ms is well below the
|
|
64
|
-
* lock holder's typical hold time.
|
|
65
|
-
*/
|
|
66
|
-
const LOCK_WAIT_MAX_MS = 5 * 60000;
|
|
67
|
-
const LOCK_RETRY_MS = 500;
|
|
68
|
-
/** After this long waiting on a lock, emit one stderr line so a slow wait is
|
|
69
|
-
* visible instead of looking like a silent hang. */
|
|
70
|
-
const LOCK_WAIT_NOTICE_MS = 2000;
|
|
71
42
|
/**
|
|
72
43
|
* The npm-loader maintains a single install root per kernel process. For a
|
|
73
44
|
* local entry manifest (`file://` URL or bare path) the root lives at
|
|
@@ -229,7 +200,7 @@ export class NpmControllerLoader {
|
|
|
229
200
|
await this.seedDepCaches(installRoot, dependencies);
|
|
230
201
|
return installRoot;
|
|
231
202
|
}
|
|
232
|
-
await
|
|
203
|
+
await withDirectoryLock(installRoot, "controller install", async () => {
|
|
233
204
|
// Re-check inside the lock: a peer may have completed the install
|
|
234
205
|
// between the fast-path miss and our acquisition.
|
|
235
206
|
const existingHash = await readJsonField(stateFile, "rootHash");
|
|
@@ -332,7 +303,7 @@ export class NpmControllerLoader {
|
|
|
332
303
|
}
|
|
333
304
|
}
|
|
334
305
|
const work = (async () => {
|
|
335
|
-
await
|
|
306
|
+
await withDirectoryLock(installRoot, "controller install", async () => {
|
|
336
307
|
// Re-check inside the lock: a peer process may have installed the
|
|
337
308
|
// spec between the fast-path miss and our acquisition.
|
|
338
309
|
if (kind === "registry") {
|
|
@@ -442,160 +413,6 @@ async function resolveKernelPackageRoot(name) {
|
|
|
442
413
|
dir = parent;
|
|
443
414
|
}
|
|
444
415
|
}
|
|
445
|
-
/**
|
|
446
|
-
* Serialize same-process callers for one install root, in memory, ahead of the
|
|
447
|
-
* filesystem lock.
|
|
448
|
-
*
|
|
449
|
-
* Package installs dedupe per alias, so N distinct controllers are N distinct
|
|
450
|
-
* `withInstallLock` calls against the SAME root. Without this queue they all
|
|
451
|
-
* contend through the filesystem: one wins and the rest poll `fs.open` every
|
|
452
|
-
* {@link LOCK_RETRY_MS} for the whole install, each crossing
|
|
453
|
-
* {@link LOCK_WAIT_NOTICE_MS} and printing the wait notice — a notice whose
|
|
454
|
-
* whole point is "another Telo *process* holds this", which is misleading when
|
|
455
|
-
* the holder is us. (`telo install` fanning 52 controllers out through one
|
|
456
|
-
* `Promise.allSettled` printed 51 of them.)
|
|
457
|
-
*
|
|
458
|
-
* Queuing here means exactly one caller per process reaches the fs lock, so the
|
|
459
|
-
* notice regains its cross-process meaning and the losers do no I/O at all. The
|
|
460
|
-
* fs lock is untouched and still provides the cross-process guarantee.
|
|
461
|
-
*/
|
|
462
|
-
const localInstallQueues = new Map();
|
|
463
|
-
function withLocalInstallQueue(installRoot, fn) {
|
|
464
|
-
const prev = localInstallQueues.get(installRoot) ?? Promise.resolve();
|
|
465
|
-
// Run on both settle paths: one failed install must not wedge the queue.
|
|
466
|
-
const run = prev.then(fn, fn);
|
|
467
|
-
// The stored tail never rejects — a failure neither poisons followers nor
|
|
468
|
-
// surfaces as an unhandled rejection on the chain copy.
|
|
469
|
-
const tail = run.then(() => { }, () => { });
|
|
470
|
-
localInstallQueues.set(installRoot, tail);
|
|
471
|
-
// Drop the entry once nothing further is queued, so a long-lived process that
|
|
472
|
-
// touches many entry dirs doesn't retain a promise per root forever.
|
|
473
|
-
void tail.then(() => {
|
|
474
|
-
if (localInstallQueues.get(installRoot) === tail)
|
|
475
|
-
localInstallQueues.delete(installRoot);
|
|
476
|
-
});
|
|
477
|
-
return run;
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* Acquire the install lock for `installRoot` and run `fn` under it: first the
|
|
481
|
-
* in-process queue above, then the cross-process filesystem lock.
|
|
482
|
-
*/
|
|
483
|
-
async function withInstallLock(installRoot, fn, log = NOOP_LOGGER) {
|
|
484
|
-
return withLocalInstallQueue(installRoot, () => withFileInstallLock(installRoot, fn, log));
|
|
485
|
-
}
|
|
486
|
-
/**
|
|
487
|
-
* Acquire a process-portable lock on `<root>/.lock` and execute fn while
|
|
488
|
-
* holding it. `fs.open(path, 'wx')` is atomic on POSIX and Windows, so
|
|
489
|
-
* concurrent processes serialize naturally.
|
|
490
|
-
*
|
|
491
|
-
* Liveness is a heartbeat: the holder bumps the lock's mtime every
|
|
492
|
-
* {@link LOCK_HEARTBEAT_MS} while `fn` runs, and a waiter reclaims a lock whose
|
|
493
|
-
* mtime is older than {@link LOCK_STALE_MS} (holder crashed/killed/vanished).
|
|
494
|
-
* mtime age is the *only* reclaim signal — the recorded `{pid, host}` is
|
|
495
|
-
* diagnostics, never probed for liveness, because PID identity is unreliable
|
|
496
|
-
* across container restarts and PID namespaces (the failure that deadlocked
|
|
497
|
-
* container boots). Reclaim is via atomic rename to a unique tombstone so two
|
|
498
|
-
* waiters that both see the lock stale can't both win.
|
|
499
|
-
*
|
|
500
|
-
* The lock guards the install-root manifest write, the package-manager
|
|
501
|
-
* invocation, and any state-file writes. It does NOT serialize *reads* of
|
|
502
|
-
* already-installed controllers — those run lock-free against a stable tree.
|
|
503
|
-
*/
|
|
504
|
-
async function withFileInstallLock(installRoot, fn, log = NOOP_LOGGER) {
|
|
505
|
-
const lockPath = path.join(installRoot, ".lock");
|
|
506
|
-
await fs.mkdir(installRoot, { recursive: true });
|
|
507
|
-
const lockBody = JSON.stringify({ pid: process.pid, host: os.hostname(), startedAt: Date.now() });
|
|
508
|
-
let handle = null;
|
|
509
|
-
const waitedSince = Date.now();
|
|
510
|
-
let noticed = false;
|
|
511
|
-
while (true) {
|
|
512
|
-
try {
|
|
513
|
-
handle = await fs.open(lockPath, "wx");
|
|
514
|
-
await handle.writeFile(lockBody);
|
|
515
|
-
break;
|
|
516
|
-
}
|
|
517
|
-
catch (err) {
|
|
518
|
-
if (err?.code !== "EEXIST")
|
|
519
|
-
throw err;
|
|
520
|
-
// Lock exists. Reclaim it only if its heartbeat has gone silent.
|
|
521
|
-
if (await reclaimIfStale(lockPath))
|
|
522
|
-
continue;
|
|
523
|
-
const waited = Date.now() - waitedSince;
|
|
524
|
-
if (waited > LOCK_WAIT_MAX_MS) {
|
|
525
|
-
throw new Error(`[telo] timed out waiting for install lock at ${lockPath} ` +
|
|
526
|
-
`(held >${LOCK_WAIT_MAX_MS / 60000} min with a live heartbeat). ` +
|
|
527
|
-
`Inspect the lock file or remove it manually if no other Telo process is running.`);
|
|
528
|
-
}
|
|
529
|
-
if (!noticed && waited > LOCK_WAIT_NOTICE_MS) {
|
|
530
|
-
noticed = true;
|
|
531
|
-
log.info("waiting for controller install lock", { "telo.install.lock_path": lockPath });
|
|
532
|
-
}
|
|
533
|
-
await sleep(LOCK_RETRY_MS);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
// Keep the lock fresh while `fn` runs so a slow-but-live install is never
|
|
537
|
-
// reclaimed. `unref` so the heartbeat can't by itself keep the process alive.
|
|
538
|
-
const heartbeat = setInterval(() => {
|
|
539
|
-
const now = new Date();
|
|
540
|
-
fs.utimes(lockPath, now, now).catch(() => { });
|
|
541
|
-
}, LOCK_HEARTBEAT_MS);
|
|
542
|
-
heartbeat.unref?.();
|
|
543
|
-
try {
|
|
544
|
-
return await fn();
|
|
545
|
-
}
|
|
546
|
-
finally {
|
|
547
|
-
clearInterval(heartbeat);
|
|
548
|
-
// The fd close races nothing important: if it fails, the FD is reaped on
|
|
549
|
-
// process exit. The unlink is the dangerous one — a non-ENOENT failure
|
|
550
|
-
// (permissions, read-only mount) means every subsequent kernel waits
|
|
551
|
-
// LOCK_STALE_MS before reclaiming. Surface it so the cause is visible
|
|
552
|
-
// rather than hiding behind a silent hang.
|
|
553
|
-
await handle.close().catch(() => { });
|
|
554
|
-
try {
|
|
555
|
-
await fs.rm(lockPath, { force: true });
|
|
556
|
-
}
|
|
557
|
-
catch (err) {
|
|
558
|
-
if (err?.code !== "ENOENT") {
|
|
559
|
-
log.warn("failed to release install lock", { "telo.install.lock_path": lockPath }, { error: err });
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
/**
|
|
565
|
-
* If the lock at `lockPath` is stale (mtime older than {@link LOCK_STALE_MS}, so
|
|
566
|
-
* its holder stopped heartbeating), atomically claim and remove it and return
|
|
567
|
-
* true; otherwise return false. The claim is a `rename` to a unique tombstone:
|
|
568
|
-
* `rename` is atomic and fails for all but one racer, so two processes that
|
|
569
|
-
* both observe the same stale lock cannot both reclaim it — the loser's rename
|
|
570
|
-
* throws ENOENT (the file is already gone) and it simply retries the open.
|
|
571
|
-
*/
|
|
572
|
-
async function reclaimIfStale(lockPath) {
|
|
573
|
-
let stat;
|
|
574
|
-
try {
|
|
575
|
-
stat = await fs.stat(lockPath);
|
|
576
|
-
}
|
|
577
|
-
catch (err) {
|
|
578
|
-
// Race: lock vanished while we inspected it. Retry the open immediately.
|
|
579
|
-
if (err?.code === "ENOENT")
|
|
580
|
-
return true;
|
|
581
|
-
throw err;
|
|
582
|
-
}
|
|
583
|
-
if (Date.now() - stat.mtimeMs < LOCK_STALE_MS)
|
|
584
|
-
return false;
|
|
585
|
-
// Stale — the holder's heartbeat is silent. Claim via atomic rename; only one
|
|
586
|
-
// racer wins, the rest get ENOENT and fall back to retrying the open.
|
|
587
|
-
const tombstone = `${lockPath}.stale.${process.pid}.${stat.mtimeMs}`;
|
|
588
|
-
try {
|
|
589
|
-
await fs.rename(lockPath, tombstone);
|
|
590
|
-
}
|
|
591
|
-
catch (err) {
|
|
592
|
-
if (err?.code === "ENOENT")
|
|
593
|
-
return true; // another waiter reclaimed it first
|
|
594
|
-
throw err;
|
|
595
|
-
}
|
|
596
|
-
await fs.rm(tombstone, { force: true });
|
|
597
|
-
return true;
|
|
598
|
-
}
|
|
599
416
|
async function runPackageManager(cwd, args) {
|
|
600
417
|
try {
|
|
601
418
|
await execFileAsync(PACKAGE_MANAGER, args, { cwd, maxBuffer: 32 * 1024 * 1024, env: hostEnv() });
|
|
@@ -970,10 +787,6 @@ export const __testing__ = {
|
|
|
970
787
|
resolveExportTargetValue,
|
|
971
788
|
tryResolveFile,
|
|
972
789
|
computeInstallRoot,
|
|
973
|
-
withInstallLock,
|
|
974
|
-
reclaimIfStale,
|
|
975
|
-
LOCK_STALE_MS,
|
|
976
|
-
LOCK_HEARTBEAT_MS,
|
|
977
790
|
EXPORTS_MAX_DEPTH,
|
|
978
791
|
DEFAULT_RESOLVER_CONDITIONS,
|
|
979
792
|
REALM_COLLAPSE_NAMES,
|