@highstate/backend 0.9.4 → 0.9.6
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/{chunk-I7NLZ54E.js → chunk-NMGIUI6X.js} +22 -7
- package/dist/chunk-NMGIUI6X.js.map +1 -0
- package/dist/highstate.manifest.json +3 -3
- package/dist/index.js +160 -92
- package/dist/index.js.map +1 -1
- package/dist/library/worker/main.js +19 -15
- package/dist/library/worker/main.js.map +1 -1
- package/dist/shared/index.js +3 -1
- package/package.json +3 -3
- package/src/library/local.ts +10 -2
- package/src/library/worker/evaluator.ts +14 -6
- package/src/library/worker/loader.ts +12 -9
- package/src/orchestrator/manager.ts +4 -2
- package/src/orchestrator/operation-workset.ts +132 -63
- package/src/orchestrator/operation.ts +49 -30
- package/src/project/manager.ts +8 -0
- package/src/shared/library.ts +3 -0
- package/src/shared/operation.ts +13 -2
- package/src/shared/resolvers/validation.ts +3 -3
- package/src/shared/state.ts +9 -1
- package/dist/chunk-I7NLZ54E.js.map +0 -1
@@ -29,21 +29,24 @@ async function loadLibrary(jiti2, logger2, modulePaths) {
|
|
29
29
|
const modules = {};
|
30
30
|
for (const modulePath of modulePaths) {
|
31
31
|
try {
|
32
|
-
logger2.debug("loading module"
|
32
|
+
logger2.debug({ modulePath }, "loading module");
|
33
33
|
modules[modulePath] = await jiti2.import(modulePath);
|
34
|
-
logger2.debug("module loaded"
|
35
|
-
} catch (
|
36
|
-
logger2.error("module load failed"
|
34
|
+
logger2.debug({ modulePath }, "module loaded");
|
35
|
+
} catch (err) {
|
36
|
+
logger2.error({ modulePath, err }, "module load failed");
|
37
37
|
}
|
38
38
|
}
|
39
39
|
const components = {};
|
40
40
|
const entities = {};
|
41
41
|
await _loadLibrary(modules, components, entities);
|
42
|
-
logger2.info(
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
logger2.info(
|
43
|
+
{
|
44
|
+
componentCount: Object.keys(components).length,
|
45
|
+
entityCount: Object.keys(entities).length
|
46
|
+
},
|
47
|
+
"library loaded"
|
48
|
+
);
|
49
|
+
logger2.trace({ components, entities }, "library content");
|
47
50
|
return { components, entities };
|
48
51
|
}
|
49
52
|
async function _loadLibrary(value, components, entities) {
|
@@ -109,11 +112,12 @@ function evaluateModules(jiti2, logger2, modulePaths) {
|
|
109
112
|
function evaluateInstances(logger2, library2, allInstances, resolvedInputs, instanceIds) {
|
110
113
|
const results = [];
|
111
114
|
const allInstancesMap = new Map(allInstances.map((instance) => [instance.id, instance]));
|
112
|
-
const instanceOutputs = /* @__PURE__ */ new Map();
|
113
115
|
for (const instanceId of instanceIds ?? []) {
|
116
|
+
const externalInstanceIds = new Set(allInstances.map((instance) => instance.id));
|
117
|
+
externalInstanceIds.delete(instanceId);
|
114
118
|
try {
|
115
119
|
logger2.debug({ instanceId }, "evaluating top-level instance");
|
116
|
-
resetEvaluation();
|
120
|
+
resetEvaluation(externalInstanceIds);
|
117
121
|
evaluateInstance(instanceId);
|
118
122
|
results.push({
|
119
123
|
success: true,
|
@@ -129,15 +133,15 @@ function evaluateInstances(logger2, library2, allInstances, resolvedInputs, inst
|
|
129
133
|
}
|
130
134
|
}
|
131
135
|
return results;
|
132
|
-
function evaluateInstance(instanceId) {
|
136
|
+
function evaluateInstance(instanceId, instanceOutputs = /* @__PURE__ */ new Map()) {
|
133
137
|
let outputs = instanceOutputs.get(instanceId);
|
134
138
|
if (!outputs) {
|
135
|
-
outputs = _evaluateInstance(instanceId);
|
139
|
+
outputs = _evaluateInstance(instanceId, instanceOutputs);
|
136
140
|
instanceOutputs.set(instanceId, outputs);
|
137
141
|
}
|
138
142
|
return outputs;
|
139
143
|
}
|
140
|
-
function _evaluateInstance(instanceId) {
|
144
|
+
function _evaluateInstance(instanceId, instanceOutputs) {
|
141
145
|
const inputs = {};
|
142
146
|
const instance = allInstancesMap.get(instanceId);
|
143
147
|
logger2.info("evaluating instance", { instanceId });
|
@@ -146,7 +150,7 @@ function evaluateInstances(logger2, library2, allInstances, resolvedInputs, inst
|
|
146
150
|
}
|
147
151
|
for (const [inputName, input] of Object.entries(resolvedInputs[instanceId] ?? {})) {
|
148
152
|
inputs[inputName] = input.map((input2) => {
|
149
|
-
const evaluated = evaluateInstance(input2.input.instanceId);
|
153
|
+
const evaluated = evaluateInstance(input2.input.instanceId, instanceOutputs);
|
150
154
|
return evaluated[input2.input.output];
|
151
155
|
});
|
152
156
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["../../../src/library/worker/main.ts","../../../src/library/worker/loader.ts","../../../src/library/worker/evaluator.ts"],"sourcesContent":["import type { WorkerData, WorkerRequest, WorkerResponse } from \"./protocol\"\nimport { parentPort, workerData } from \"node:worker_threads\"\nimport { createJiti, type Jiti } from \"jiti\"\nimport { pino } from \"pino\"\nimport { mapValues } from \"remeda\"\nimport { errorToString } from \"../../common\"\nimport { loadLibrary, type Library } from \"./loader\"\nimport { evaluateInstances, evaluateModules } from \"./evaluator\"\n\nconst data = workerData as WorkerData\n\nconst logger = pino({ name: \"library-worker\", level: data.logLevel })\nlet jiti: Jiti\nlet library: Library\n\ntry {\n logger.info(\"worker started\")\n logger.trace({ data }, \"worker data\")\n\n jiti = createJiti(import.meta.filename)\n logger.debug({ filename: import.meta.filename }, \"jiti created\")\n\n library = await loadLibrary(jiti, logger, data.modulePaths)\n\n parentPort!.postMessage({\n type: \"library\",\n library: {\n components: mapValues(library.components, component => component.model),\n entities: library.entities,\n },\n } satisfies WorkerResponse)\n\n logger.info(\"library loaded and sent\")\n} catch (error) {\n logger.error({ error }, \"failed to load library\")\n\n parentPort!.postMessage({\n type: \"error\",\n error: errorToString(error),\n })\n}\n\n// eslint-disable-next-line @typescript-eslint/no-misused-promises\nparentPort!.on(\"message\", async message => {\n try {\n const request = message as WorkerRequest\n\n switch (request.type) {\n case \"evaluate-composite-instances\": {\n const results = evaluateInstances(\n logger,\n library,\n request.allInstances,\n request.resolvedInputs,\n request.instanceIds,\n )\n\n parentPort!.postMessage({\n type: \"instance-evaluation-results\",\n results,\n } satisfies WorkerResponse)\n break\n }\n case \"evaluate-modules\": {\n const result = await evaluateModules(jiti, logger, request.modulePaths)\n\n parentPort!.postMessage({\n type: \"module-evaluation-result\",\n result,\n } satisfies WorkerResponse)\n break\n }\n }\n } catch (error) {\n logger.error({ error }, \"failed to evaluate\")\n\n parentPort!.postMessage({\n type: \"error\",\n error: errorToString(error),\n } satisfies WorkerResponse)\n }\n})\n","import type { Logger } from \"pino\"\nimport type { Jiti } from \"jiti\"\nimport Module from \"node:module\"\nimport {\n type Component,\n type Entity,\n isComponent,\n isEntity,\n isUnitModel,\n originalCreate,\n} from \"@highstate/contract\"\nimport { serializeFunction } from \"@pulumi/pulumi/runtime/index.js\"\nimport { sha256 } from \"crypto-hash\"\n\ndeclare module \"module\" {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Module {\n function _load(request: unknown, parent: unknown, isMain: boolean): unknown\n }\n}\n\nconst originalLoad = Module._load\n\nModule._load = function (request: unknown, parent: unknown, isMain: boolean) {\n if (request === \"trace_events\") {\n return {}\n }\n\n return originalLoad(request, parent, isMain)\n}\n\nexport type Library = Readonly<{\n components: Readonly<Record<string, Component>>\n entities: Readonly<Record<string, Entity>>\n}>\n\nexport async function loadLibrary(\n jiti: Jiti,\n logger: Logger,\n modulePaths: string[],\n): Promise<Library> {\n const modules: Record<string, unknown> = {}\n for (const modulePath of modulePaths) {\n try {\n logger.debug(\"loading module\", { modulePath })\n modules[modulePath] = await jiti.import(modulePath)\n\n logger.debug(\"module loaded\", { modulePath })\n } catch (error) {\n logger.error(\"module load failed\", { modulePath, error })\n }\n }\n\n const components: Record<string, Component> = {}\n const entities: Record<string, Entity> = {}\n\n await _loadLibrary(modules, components, entities)\n\n logger.info(\"library loaded\", {\n componentCount: Object.keys(components).length,\n entityCount: Object.keys(entities).length,\n })\n\n logger.trace(\"library content\", { components, entities })\n\n return { components, entities }\n}\n\nasync function _loadLibrary(\n value: unknown,\n components: Record<string, Component>,\n entities: Record<string, Entity>,\n): Promise<void> {\n if (isComponent(value)) {\n components[value.model.type] = value\n value.model.definitionHash = await calculateComponentDefinitionHash(value)\n\n for (const entity of value.entities.values()) {\n entity.definitionHash ??= await calculateEntityDefinitionHash(entity)\n }\n return\n }\n\n if (isEntity(value)) {\n entities[value.type] = value\n entities[value.type].definitionHash ??= await calculateEntityDefinitionHash(value)\n return\n }\n\n if (typeof value !== \"object\" || value === null) {\n return\n }\n\n for (const key in value) {\n await _loadLibrary((value as Record<string, unknown>)[key], components, entities)\n }\n}\n\nasync function calculateComponentDefinitionHash(component: Component): Promise<string> {\n if (isUnitModel(component.model)) {\n return await sha256(JSON.stringify(component.model))\n }\n\n const serializedCreate = await serializeFunction(component[originalCreate])\n\n return await sha256(JSON.stringify(component.model) + serializedCreate.text)\n}\n\nasync function calculateEntityDefinitionHash(entity: Entity): Promise<string> {\n return await sha256(JSON.stringify(entity))\n}\n","import type { Logger } from \"pino\"\nimport type { Library } from \"./loader\"\nimport type { Jiti } from \"jiti\"\nimport type { InstanceEvaluationResult, ModuleEvaluationResult } from \"../abstractions\"\nimport type { ResolvedInstanceInput } from \"../../shared\"\nimport { getCompositeInstances, resetEvaluation, type InstanceModel } from \"@highstate/contract\"\nimport { BetterLock } from \"better-lock\"\nimport { errorToString } from \"../../common\"\n\nconst lock = new BetterLock()\n\nexport function evaluateModules(\n jiti: Jiti,\n logger: Logger,\n modulePaths: string[],\n): Promise<ModuleEvaluationResult> {\n return lock.acquire(async () => {\n resetEvaluation()\n let lastModulePath = \"\"\n\n try {\n for (const modulePath of modulePaths) {\n logger.info(\"loading module: %s\", modulePath)\n\n lastModulePath = modulePath\n await jiti.import(modulePath)\n\n logger.debug(\"module loaded: %s\", modulePath)\n }\n\n return {\n success: true,\n compositeInstances: getCompositeInstances(),\n }\n } catch (error) {\n return {\n success: false,\n modulePath: lastModulePath,\n error: errorToString(error),\n }\n }\n })\n}\n\nexport function evaluateInstances(\n logger: Logger,\n library: Library,\n allInstances: InstanceModel[],\n resolvedInputs: Record<string, Record<string, ResolvedInstanceInput[]>>,\n instanceIds: string[],\n): InstanceEvaluationResult[] {\n const results: InstanceEvaluationResult[] = []\n const allInstancesMap = new Map(allInstances.map(instance => [instance.id, instance]))\n const instanceOutputs = new Map<string, Record<string, unknown>>()\n\n for (const instanceId of instanceIds ?? []) {\n try {\n logger.debug({ instanceId }, \"evaluating top-level instance\")\n resetEvaluation()\n\n evaluateInstance(instanceId)\n\n results.push({\n success: true,\n instanceId,\n compositeInstances: getCompositeInstances(),\n })\n } catch (error) {\n results.push({\n success: false,\n instanceId,\n error: errorToString(error),\n })\n }\n }\n\n return results\n\n function evaluateInstance(instanceId: string): Record<string, unknown> {\n let outputs = instanceOutputs.get(instanceId)\n\n if (!outputs) {\n outputs = _evaluateInstance(instanceId)\n instanceOutputs.set(instanceId, outputs)\n }\n\n return outputs\n }\n\n function _evaluateInstance(instanceId: string): Record<string, unknown> {\n const inputs: Record<string, unknown> = {}\n const instance = allInstancesMap.get(instanceId)\n\n logger.info(\"evaluating instance\", { instanceId })\n\n if (!instance) {\n throw new Error(`Instance not found: ${instanceId}`)\n }\n\n for (const [inputName, input] of Object.entries(resolvedInputs[instanceId] ?? {})) {\n inputs[inputName] = input.map(input => {\n const evaluated = evaluateInstance(input.input.instanceId)\n\n return evaluated[input.input.output]\n })\n }\n\n const component = library.components[instance.type]\n if (!component) {\n throw new Error(`Component not found: ${instance.type}, required by instance: ${instanceId}`)\n }\n\n return component({\n name: instance.name,\n args: instance.args as Record<string, never>,\n inputs: inputs as Record<string, never>,\n })\n }\n}\n"],"mappings":"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","names":["jiti","logger","jiti","logger","library","input"]}
|
1
|
+
{"version":3,"sources":["../../../src/library/worker/main.ts","../../../src/library/worker/loader.ts","../../../src/library/worker/evaluator.ts"],"sourcesContent":["import type { WorkerData, WorkerRequest, WorkerResponse } from \"./protocol\"\nimport { parentPort, workerData } from \"node:worker_threads\"\nimport { createJiti, type Jiti } from \"jiti\"\nimport { pino } from \"pino\"\nimport { mapValues } from \"remeda\"\nimport { errorToString } from \"../../common\"\nimport { loadLibrary, type Library } from \"./loader\"\nimport { evaluateInstances, evaluateModules } from \"./evaluator\"\n\nconst data = workerData as WorkerData\n\nconst logger = pino({ name: \"library-worker\", level: data.logLevel })\nlet jiti: Jiti\nlet library: Library\n\ntry {\n logger.info(\"worker started\")\n logger.trace({ data }, \"worker data\")\n\n jiti = createJiti(import.meta.filename)\n logger.debug({ filename: import.meta.filename }, \"jiti created\")\n\n library = await loadLibrary(jiti, logger, data.modulePaths)\n\n parentPort!.postMessage({\n type: \"library\",\n library: {\n components: mapValues(library.components, component => component.model),\n entities: library.entities,\n },\n } satisfies WorkerResponse)\n\n logger.info(\"library loaded and sent\")\n} catch (error) {\n logger.error({ error }, \"failed to load library\")\n\n parentPort!.postMessage({\n type: \"error\",\n error: errorToString(error),\n })\n}\n\n// eslint-disable-next-line @typescript-eslint/no-misused-promises\nparentPort!.on(\"message\", async message => {\n try {\n const request = message as WorkerRequest\n\n switch (request.type) {\n case \"evaluate-composite-instances\": {\n const results = evaluateInstances(\n logger,\n library,\n request.allInstances,\n request.resolvedInputs,\n request.instanceIds,\n )\n\n parentPort!.postMessage({\n type: \"instance-evaluation-results\",\n results,\n } satisfies WorkerResponse)\n break\n }\n case \"evaluate-modules\": {\n const result = await evaluateModules(jiti, logger, request.modulePaths)\n\n parentPort!.postMessage({\n type: \"module-evaluation-result\",\n result,\n } satisfies WorkerResponse)\n break\n }\n }\n } catch (error) {\n logger.error({ error }, \"failed to evaluate\")\n\n parentPort!.postMessage({\n type: \"error\",\n error: errorToString(error),\n } satisfies WorkerResponse)\n }\n})\n","import type { Logger } from \"pino\"\nimport type { Jiti } from \"jiti\"\nimport Module from \"node:module\"\nimport {\n type Component,\n type Entity,\n isComponent,\n isEntity,\n isUnitModel,\n originalCreate,\n} from \"@highstate/contract\"\nimport { serializeFunction } from \"@pulumi/pulumi/runtime/index.js\"\nimport { sha256 } from \"crypto-hash\"\n\ndeclare module \"module\" {\n // eslint-disable-next-line @typescript-eslint/no-namespace\n namespace Module {\n function _load(request: unknown, parent: unknown, isMain: boolean): unknown\n }\n}\n\nconst originalLoad = Module._load\n\nModule._load = function (request: unknown, parent: unknown, isMain: boolean) {\n if (request === \"trace_events\") {\n return {}\n }\n\n return originalLoad(request, parent, isMain)\n}\n\nexport type Library = Readonly<{\n components: Readonly<Record<string, Component>>\n entities: Readonly<Record<string, Entity>>\n}>\n\nexport async function loadLibrary(\n jiti: Jiti,\n logger: Logger,\n modulePaths: string[],\n): Promise<Library> {\n const modules: Record<string, unknown> = {}\n for (const modulePath of modulePaths) {\n try {\n logger.debug({ modulePath }, \"loading module\")\n modules[modulePath] = await jiti.import(modulePath)\n\n logger.debug({ modulePath }, \"module loaded\")\n } catch (err) {\n logger.error({ modulePath, err }, \"module load failed\")\n }\n }\n\n const components: Record<string, Component> = {}\n const entities: Record<string, Entity> = {}\n\n await _loadLibrary(modules, components, entities)\n\n logger.info(\n {\n componentCount: Object.keys(components).length,\n entityCount: Object.keys(entities).length,\n },\n \"library loaded\",\n )\n\n logger.trace({ components, entities }, \"library content\")\n\n return { components, entities }\n}\n\nasync function _loadLibrary(\n value: unknown,\n components: Record<string, Component>,\n entities: Record<string, Entity>,\n): Promise<void> {\n if (isComponent(value)) {\n components[value.model.type] = value\n value.model.definitionHash = await calculateComponentDefinitionHash(value)\n\n for (const entity of value.entities.values()) {\n entity.definitionHash ??= await calculateEntityDefinitionHash(entity)\n }\n return\n }\n\n if (isEntity(value)) {\n entities[value.type] = value\n entities[value.type].definitionHash ??= await calculateEntityDefinitionHash(value)\n return\n }\n\n if (typeof value !== \"object\" || value === null) {\n return\n }\n\n for (const key in value) {\n await _loadLibrary((value as Record<string, unknown>)[key], components, entities)\n }\n}\n\nasync function calculateComponentDefinitionHash(component: Component): Promise<string> {\n if (isUnitModel(component.model)) {\n return await sha256(JSON.stringify(component.model))\n }\n\n const serializedCreate = await serializeFunction(component[originalCreate])\n\n return await sha256(JSON.stringify(component.model) + serializedCreate.text)\n}\n\nasync function calculateEntityDefinitionHash(entity: Entity): Promise<string> {\n return await sha256(JSON.stringify(entity))\n}\n","import type { Logger } from \"pino\"\nimport type { Library } from \"./loader\"\nimport type { Jiti } from \"jiti\"\nimport type { InstanceEvaluationResult, ModuleEvaluationResult } from \"../abstractions\"\nimport type { ResolvedInstanceInput } from \"../../shared\"\nimport { getCompositeInstances, resetEvaluation, type InstanceModel } from \"@highstate/contract\"\nimport { BetterLock } from \"better-lock\"\nimport { errorToString } from \"../../common\"\n\nconst lock = new BetterLock()\n\nexport function evaluateModules(\n jiti: Jiti,\n logger: Logger,\n modulePaths: string[],\n): Promise<ModuleEvaluationResult> {\n return lock.acquire(async () => {\n resetEvaluation()\n let lastModulePath = \"\"\n\n try {\n for (const modulePath of modulePaths) {\n logger.info(\"loading module: %s\", modulePath)\n\n lastModulePath = modulePath\n await jiti.import(modulePath)\n\n logger.debug(\"module loaded: %s\", modulePath)\n }\n\n return {\n success: true,\n compositeInstances: getCompositeInstances(),\n }\n } catch (error) {\n return {\n success: false,\n modulePath: lastModulePath,\n error: errorToString(error),\n }\n }\n })\n}\n\nexport function evaluateInstances(\n logger: Logger,\n library: Library,\n allInstances: InstanceModel[],\n resolvedInputs: Record<string, Record<string, ResolvedInstanceInput[]>>,\n instanceIds: string[],\n): InstanceEvaluationResult[] {\n const results: InstanceEvaluationResult[] = []\n const allInstancesMap = new Map(allInstances.map(instance => [instance.id, instance]))\n\n for (const instanceId of instanceIds ?? []) {\n const externalInstanceIds = new Set(allInstances.map(instance => instance.id))\n externalInstanceIds.delete(instanceId)\n\n try {\n logger.debug({ instanceId }, \"evaluating top-level instance\")\n resetEvaluation(externalInstanceIds)\n\n evaluateInstance(instanceId)\n\n results.push({\n success: true,\n instanceId,\n compositeInstances: getCompositeInstances(),\n })\n } catch (error) {\n results.push({\n success: false,\n instanceId,\n error: errorToString(error),\n })\n }\n }\n\n return results\n\n function evaluateInstance(\n instanceId: string,\n instanceOutputs: Map<string, Record<string, unknown>> = new Map(),\n ): Record<string, unknown> {\n let outputs = instanceOutputs.get(instanceId)\n\n if (!outputs) {\n outputs = _evaluateInstance(instanceId, instanceOutputs)\n instanceOutputs.set(instanceId, outputs)\n }\n\n return outputs\n }\n\n function _evaluateInstance(\n instanceId: string,\n instanceOutputs: Map<string, Record<string, unknown>>,\n ): Record<string, unknown> {\n const inputs: Record<string, unknown> = {}\n const instance = allInstancesMap.get(instanceId)\n\n logger.info(\"evaluating instance\", { instanceId })\n\n if (!instance) {\n throw new Error(`Instance not found: ${instanceId}`)\n }\n\n for (const [inputName, input] of Object.entries(resolvedInputs[instanceId] ?? {})) {\n inputs[inputName] = input.map(input => {\n const evaluated = evaluateInstance(input.input.instanceId, instanceOutputs)\n\n return evaluated[input.input.output]\n })\n }\n\n const component = library.components[instance.type]\n if (!component) {\n throw new Error(`Component not found: ${instance.type}, required by instance: ${instanceId}`)\n }\n\n return component({\n name: instance.name,\n args: instance.args as Record<string, never>,\n inputs: inputs as Record<string, never>,\n })\n }\n}\n"],"mappings":"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","names":["jiti","logger","jiti","logger","library","input"]}
|
package/dist/shared/index.js
CHANGED
@@ -31,6 +31,7 @@ import {
|
|
31
31
|
instanceStateSchema,
|
32
32
|
instanceStateUpdateSchema,
|
33
33
|
instanceStatusFieldSchema,
|
34
|
+
instanceStatusFieldValueSchema,
|
34
35
|
instanceStatusSchema,
|
35
36
|
instanceTerminalFileSchema,
|
36
37
|
instanceTerminalMetaSchema,
|
@@ -47,7 +48,7 @@ import {
|
|
47
48
|
projectOperationSchema,
|
48
49
|
resolverFactories,
|
49
50
|
terminalSessionSchema
|
50
|
-
} from "../chunk-
|
51
|
+
} from "../chunk-NMGIUI6X.js";
|
51
52
|
export {
|
52
53
|
CircularDependencyError,
|
53
54
|
applyLibraryUpdate,
|
@@ -81,6 +82,7 @@ export {
|
|
81
82
|
instanceStateSchema,
|
82
83
|
instanceStateUpdateSchema,
|
83
84
|
instanceStatusFieldSchema,
|
85
|
+
instanceStatusFieldValueSchema,
|
84
86
|
instanceStatusSchema,
|
85
87
|
instanceTerminalFileSchema,
|
86
88
|
instanceTerminalMetaSchema,
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@highstate/backend",
|
3
|
-
"version": "0.9.
|
3
|
+
"version": "0.9.6",
|
4
4
|
"type": "module",
|
5
5
|
"files": [
|
6
6
|
"dist",
|
@@ -26,7 +26,7 @@
|
|
26
26
|
"build": "highstate build"
|
27
27
|
},
|
28
28
|
"dependencies": {
|
29
|
-
"@highstate/contract": "^0.9.
|
29
|
+
"@highstate/contract": "^0.9.6",
|
30
30
|
"@types/node": "^22.10.1",
|
31
31
|
"ajv": "^8.17.1",
|
32
32
|
"better-lock": "^3.2.0",
|
@@ -65,5 +65,5 @@
|
|
65
65
|
"rollup": "^4.28.1",
|
66
66
|
"typescript": "^5.7.2"
|
67
67
|
},
|
68
|
-
"gitHead": "
|
68
|
+
"gitHead": "3c7e8883ef6cbc3e3f7c2c5529115767aae5c96a"
|
69
69
|
}
|
package/src/library/local.ts
CHANGED
@@ -110,7 +110,11 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
110
110
|
return await this.lock.acquire(async () => {
|
111
111
|
const [library] = await this.getLibrary()
|
112
112
|
|
113
|
-
const units = unitTypes
|
113
|
+
const units = unitTypes
|
114
|
+
.map(type => library.components[type])
|
115
|
+
.filter(Boolean)
|
116
|
+
.filter(isUnitModel)
|
117
|
+
|
114
118
|
const packageNames = Object.keys(groupBy(units, unit => unit.source.package))
|
115
119
|
|
116
120
|
await this.ensureLibraryPackagesLoaded(packageNames, true)
|
@@ -213,11 +217,13 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
213
217
|
private async reloadLibrary(): Promise<[LibraryModel, Worker]> {
|
214
218
|
this.logger.info("reloading library")
|
215
219
|
|
220
|
+
this.eventEmitter.emit("library", [{ type: "reload-started" }])
|
221
|
+
|
216
222
|
await this.ensureLibraryPackagesLoaded(this.libraryPackages, true)
|
217
223
|
|
218
224
|
this.worker = this.createLibraryWorker({
|
219
225
|
modulePaths: this.libraryPackages,
|
220
|
-
logLevel: "
|
226
|
+
logLevel: "warn",
|
221
227
|
})
|
222
228
|
|
223
229
|
for await (const [event] of on(this.worker, "message")) {
|
@@ -245,6 +251,8 @@ export class LocalLibraryBackend implements LibraryBackend {
|
|
245
251
|
|
246
252
|
this.logger.info("library reloaded")
|
247
253
|
|
254
|
+
this.eventEmitter.emit("library", [{ type: "reload-completed" }])
|
255
|
+
|
248
256
|
return [this.library, this.worker]
|
249
257
|
}
|
250
258
|
|
@@ -51,12 +51,14 @@ export function evaluateInstances(
|
|
51
51
|
): InstanceEvaluationResult[] {
|
52
52
|
const results: InstanceEvaluationResult[] = []
|
53
53
|
const allInstancesMap = new Map(allInstances.map(instance => [instance.id, instance]))
|
54
|
-
const instanceOutputs = new Map<string, Record<string, unknown>>()
|
55
54
|
|
56
55
|
for (const instanceId of instanceIds ?? []) {
|
56
|
+
const externalInstanceIds = new Set(allInstances.map(instance => instance.id))
|
57
|
+
externalInstanceIds.delete(instanceId)
|
58
|
+
|
57
59
|
try {
|
58
60
|
logger.debug({ instanceId }, "evaluating top-level instance")
|
59
|
-
resetEvaluation()
|
61
|
+
resetEvaluation(externalInstanceIds)
|
60
62
|
|
61
63
|
evaluateInstance(instanceId)
|
62
64
|
|
@@ -76,18 +78,24 @@ export function evaluateInstances(
|
|
76
78
|
|
77
79
|
return results
|
78
80
|
|
79
|
-
function evaluateInstance(
|
81
|
+
function evaluateInstance(
|
82
|
+
instanceId: string,
|
83
|
+
instanceOutputs: Map<string, Record<string, unknown>> = new Map(),
|
84
|
+
): Record<string, unknown> {
|
80
85
|
let outputs = instanceOutputs.get(instanceId)
|
81
86
|
|
82
87
|
if (!outputs) {
|
83
|
-
outputs = _evaluateInstance(instanceId)
|
88
|
+
outputs = _evaluateInstance(instanceId, instanceOutputs)
|
84
89
|
instanceOutputs.set(instanceId, outputs)
|
85
90
|
}
|
86
91
|
|
87
92
|
return outputs
|
88
93
|
}
|
89
94
|
|
90
|
-
function _evaluateInstance(
|
95
|
+
function _evaluateInstance(
|
96
|
+
instanceId: string,
|
97
|
+
instanceOutputs: Map<string, Record<string, unknown>>,
|
98
|
+
): Record<string, unknown> {
|
91
99
|
const inputs: Record<string, unknown> = {}
|
92
100
|
const instance = allInstancesMap.get(instanceId)
|
93
101
|
|
@@ -99,7 +107,7 @@ export function evaluateInstances(
|
|
99
107
|
|
100
108
|
for (const [inputName, input] of Object.entries(resolvedInputs[instanceId] ?? {})) {
|
101
109
|
inputs[inputName] = input.map(input => {
|
102
|
-
const evaluated = evaluateInstance(input.input.instanceId)
|
110
|
+
const evaluated = evaluateInstance(input.input.instanceId, instanceOutputs)
|
103
111
|
|
104
112
|
return evaluated[input.input.output]
|
105
113
|
})
|
@@ -42,12 +42,12 @@ export async function loadLibrary(
|
|
42
42
|
const modules: Record<string, unknown> = {}
|
43
43
|
for (const modulePath of modulePaths) {
|
44
44
|
try {
|
45
|
-
logger.debug("loading module"
|
45
|
+
logger.debug({ modulePath }, "loading module")
|
46
46
|
modules[modulePath] = await jiti.import(modulePath)
|
47
47
|
|
48
|
-
logger.debug("module loaded"
|
49
|
-
} catch (
|
50
|
-
logger.error("module load failed"
|
48
|
+
logger.debug({ modulePath }, "module loaded")
|
49
|
+
} catch (err) {
|
50
|
+
logger.error({ modulePath, err }, "module load failed")
|
51
51
|
}
|
52
52
|
}
|
53
53
|
|
@@ -56,12 +56,15 @@ export async function loadLibrary(
|
|
56
56
|
|
57
57
|
await _loadLibrary(modules, components, entities)
|
58
58
|
|
59
|
-
logger.info(
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
logger.info(
|
60
|
+
{
|
61
|
+
componentCount: Object.keys(components).length,
|
62
|
+
entityCount: Object.keys(entities).length,
|
63
|
+
},
|
64
|
+
"library loaded",
|
65
|
+
)
|
63
66
|
|
64
|
-
logger.trace(
|
67
|
+
logger.trace({ components, entities }, "library content")
|
65
68
|
|
66
69
|
return { components, entities }
|
67
70
|
}
|
@@ -72,11 +72,13 @@ export class OperationManager {
|
|
72
72
|
id: uuidv7(),
|
73
73
|
projectId: request.projectId,
|
74
74
|
type: request.type,
|
75
|
-
|
76
|
-
|
75
|
+
requestedInstanceIds: request.instanceIds,
|
76
|
+
instanceIdsToUpdate: [],
|
77
|
+
instanceIdsToDestroy: [],
|
77
78
|
status: "pending",
|
78
79
|
options: {
|
79
80
|
forceUpdateDependencies: request.options?.forceUpdateDependencies ?? false,
|
81
|
+
forceUpdateChildren: request.options?.forceUpdateChildren ?? false,
|
80
82
|
destroyDependentInstances: request.options?.destroyDependentInstances ?? true,
|
81
83
|
invokeDestroyTriggers: request.options?.invokeDestroyTriggers ?? false,
|
82
84
|
deleteUnreachableResources: request.options?.deleteUnreachableResources ?? false,
|