@highstate/backend 0.9.16 → 0.9.19
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-5WVU2AK4.js +1535 -0
- package/dist/chunk-5WVU2AK4.js.map +1 -0
- package/dist/chunk-I7BWSAN6.js +49 -0
- package/dist/chunk-I7BWSAN6.js.map +1 -0
- package/dist/{chunk-RCB4AFGD.js → chunk-VB4YL327.js} +51 -71
- package/dist/chunk-VB4YL327.js.map +1 -0
- package/dist/database/local/prisma.config.js +26 -0
- package/dist/database/local/prisma.config.js.map +1 -0
- package/dist/highstate.manifest.json +5 -4
- package/dist/index.js +7676 -6634
- package/dist/index.js.map +1 -1
- package/dist/library/package-resolution-worker.js +8 -6
- package/dist/library/package-resolution-worker.js.map +1 -1
- package/dist/library/worker/main.js +63 -58
- package/dist/library/worker/main.js.map +1 -1
- package/dist/shared/index.js +3 -216
- package/dist/shared/index.js.map +1 -1
- package/package.json +23 -11
- package/prisma/backend/_schema/layout.prisma +7 -0
- package/prisma/backend/_schema/library.prisma +17 -0
- package/prisma/backend/_schema/project.prisma +101 -0
- package/prisma/backend/_schema/pulumi.prisma +17 -0
- package/prisma/backend/postgresql/main.prisma +17 -0
- package/prisma/backend/sqlite/main.prisma +17 -0
- package/prisma/backend/sqlite/migrations/20250817070609_initiial/migration.sql +34 -0
- package/prisma/backend/sqlite/migrations/20250817104948_add_fields/migration.sql +59 -0
- package/prisma/backend/sqlite/migrations/20250818082732_add_models/migration.sql +41 -0
- package/prisma/backend/sqlite/migrations/20250818083106_a/migration.sql +19 -0
- package/prisma/backend/sqlite/migrations/20250818101945_hi/migration.sql +1 -0
- package/prisma/backend/sqlite/migrations/20250819082315_a/migration.sql +5 -0
- package/prisma/backend/sqlite/migrations/migration_lock.toml +3 -0
- package/prisma/project/api-key.prisma +27 -0
- package/prisma/project/artifact.prisma +52 -0
- package/prisma/project/custom-status.prisma +46 -0
- package/prisma/project/evaluation.prisma +35 -0
- package/prisma/project/instance.prisma +160 -0
- package/prisma/project/layout.prisma +23 -0
- package/prisma/project/lock.prisma +18 -0
- package/prisma/project/main.prisma +17 -0
- package/prisma/project/migrations/20250816081310_initial/migration.sql +300 -0
- package/prisma/project/migrations/20250816082523_test/migration.sql +72 -0
- package/prisma/project/migrations/20250818065643_update/migration.sql +42 -0
- package/prisma/project/migrations/20250818070758_a/migration.sql +8 -0
- package/prisma/project/migrations/20250818070913_a/migration.sql +8 -0
- package/prisma/project/migrations/20250818082720_add_motels/migration.sql +11 -0
- package/prisma/project/migrations/20250818112523_hello/migration.sql +35 -0
- package/prisma/project/migrations/20250819082305_a/migration.sql +14 -0
- package/prisma/project/migrations/20250819165004_add_missing_fields/migration.sql +216 -0
- package/prisma/project/migrations/20250819171309_a/migration.sql +22 -0
- package/prisma/project/migrations/20250820113949_a/migration.sql +66 -0
- package/prisma/project/migrations/20250820144256_b/migration.sql +31 -0
- package/prisma/project/migrations/20250820145547_a/migration.sql +24 -0
- package/prisma/project/migrations/20250820182517_b/migration.sql +2 -0
- package/prisma/project/migrations/20250821172324_a/migration.sql +2 -0
- package/prisma/project/migrations/20250822081339_a/migration.sql +219 -0
- package/prisma/project/migrations/20250822083742_b/migration.sql +1 -0
- package/prisma/project/migrations/20250822105134_boom/migration.sql +1 -0
- package/prisma/project/migrations/20250822141028_b/migration.sql +1 -0
- package/prisma/project/migrations/20250822142342_b/migration.sql +16 -0
- package/prisma/project/migrations/20250824072720_a/migration.sql +1 -0
- package/prisma/project/migrations/20250824093656_b/migration.sql +21 -0
- package/prisma/project/migrations/20250825082518_a/migration.sql +1 -0
- package/prisma/project/migrations/20250825085343_b/migration.sql +1 -0
- package/prisma/project/migrations/20250825091312_a/migration.sql +1 -0
- package/prisma/project/migrations/20250903095431_hi/migration.sql +44 -0
- package/prisma/project/migrations/20250903174255_a/migration.sql +24 -0
- package/prisma/project/migrations/20250908095205_hi/migration.sql +18 -0
- package/prisma/project/migrations/20250909155857_hi/migration.sql +15 -0
- package/prisma/project/migrations/migration_lock.toml +3 -0
- package/prisma/project/model.prisma +37 -0
- package/prisma/project/operation.prisma +148 -0
- package/prisma/project/page.prisma +41 -0
- package/prisma/project/secret.prisma +42 -0
- package/prisma/project/service-account.prisma +36 -0
- package/prisma/project/terminal.prisma +90 -0
- package/prisma/project/trigger.prisma +31 -0
- package/prisma/project/unlock-method.prisma +32 -0
- package/prisma/project/worker.prisma +138 -0
- package/src/artifact/abstractions.ts +13 -13
- package/src/artifact/encryption.ts +31 -15
- package/src/artifact/factory.ts +7 -10
- package/src/artifact/local.ts +33 -50
- package/src/business/api-key.ts +24 -36
- package/src/business/artifact.test.ts +978 -0
- package/src/business/artifact.ts +136 -215
- package/src/business/evaluation.ts +328 -0
- package/src/business/index.ts +5 -1
- package/src/business/instance-lock.test.ts +1060 -0
- package/src/business/instance-lock.ts +387 -77
- package/src/business/instance-state.test.ts +735 -0
- package/src/business/instance-state.ts +604 -217
- package/src/business/operation.test.ts +439 -0
- package/src/business/operation.ts +174 -208
- package/src/business/project-model.ts +258 -0
- package/src/business/project-unlock.ts +172 -112
- package/src/business/project.ts +407 -0
- package/src/business/secret.test.ts +513 -0
- package/src/business/secret.ts +194 -131
- package/src/business/settings.test.ts +695 -0
- package/src/business/settings.ts +855 -0
- package/src/business/terminal-session.ts +90 -0
- package/src/business/unit-extra.test.ts +539 -0
- package/src/business/unit-extra.ts +160 -0
- package/src/business/worker.test.ts +391 -0
- package/src/business/worker.ts +250 -114
- package/src/common/codebase.ts +65 -0
- package/src/common/index.ts +3 -2
- package/src/common/logger.ts +5 -0
- package/src/common/utils.ts +4 -3
- package/src/config.ts +15 -12
- package/src/database/_generated/backend/postgresql/client.ts +72 -0
- package/src/database/_generated/backend/postgresql/commonInputTypes.ts +350 -0
- package/src/database/_generated/backend/postgresql/enums.ts +13 -0
- package/src/database/_generated/backend/postgresql/internal/class.ts +320 -0
- package/src/database/_generated/backend/postgresql/internal/prismaNamespace.ts +1238 -0
- package/src/database/_generated/backend/postgresql/models/Library.ts +1263 -0
- package/src/database/_generated/backend/postgresql/models/Project.ts +2175 -0
- package/src/database/_generated/backend/postgresql/models/ProjectModelStorage.ts +1263 -0
- package/src/database/_generated/backend/postgresql/models/ProjectSpace.ts +1602 -0
- package/src/database/_generated/backend/postgresql/models/PulumiBackend.ts +1263 -0
- package/src/database/_generated/backend/postgresql/models/UserWorkspaseLayout.ts +1065 -0
- package/src/database/_generated/backend/postgresql/models.ts +16 -0
- package/src/database/_generated/backend/postgresql/pjtg.ts +182 -0
- package/src/database/_generated/backend/sqlite/client.ts +72 -0
- package/src/database/_generated/backend/sqlite/commonInputTypes.ts +331 -0
- package/src/database/_generated/backend/sqlite/enums.ts +13 -0
- package/src/database/_generated/backend/sqlite/internal/class.ts +318 -0
- package/src/database/_generated/backend/sqlite/internal/prismaNamespace.ts +1207 -0
- package/src/database/_generated/backend/sqlite/models/Library.ts +1261 -0
- package/src/database/_generated/backend/sqlite/models/Project.ts +2169 -0
- package/src/database/_generated/backend/sqlite/models/ProjectModelStorage.ts +1261 -0
- package/src/database/_generated/backend/sqlite/models/ProjectSpace.ts +1599 -0
- package/src/database/_generated/backend/sqlite/models/PulumiBackend.ts +1261 -0
- package/src/database/_generated/backend/sqlite/models/UserWorkspaseLayout.ts +1063 -0
- package/src/database/_generated/backend/sqlite/models.ts +16 -0
- package/src/database/_generated/backend/sqlite/pjtg.ts +182 -0
- package/src/database/_generated/project/client.ts +204 -0
- package/src/database/_generated/project/commonInputTypes.ts +827 -0
- package/src/database/_generated/project/enums.ts +104 -0
- package/src/database/_generated/project/internal/class.ts +479 -0
- package/src/database/_generated/project/internal/prismaNamespace.ts +2974 -0
- package/src/database/_generated/project/models/ApiKey.ts +1506 -0
- package/src/database/_generated/project/models/Artifact.ts +2051 -0
- package/src/database/_generated/project/models/HubModel.ts +1125 -0
- package/src/database/_generated/project/models/InstanceCustomStatus.ts +1713 -0
- package/src/database/_generated/project/models/InstanceEvaluationState.ts +1312 -0
- package/src/database/_generated/project/models/InstanceLock.ts +1268 -0
- package/src/database/_generated/project/models/InstanceModel.ts +1125 -0
- package/src/database/_generated/project/models/InstanceOperationState.ts +1707 -0
- package/src/database/_generated/project/models/InstanceState.ts +4613 -0
- package/src/database/_generated/project/models/Operation.ts +1647 -0
- package/src/database/_generated/project/models/OperationLog.ts +1455 -0
- package/src/database/_generated/project/models/Page.ts +1838 -0
- package/src/database/_generated/project/models/Secret.ts +1692 -0
- package/src/database/_generated/project/models/ServiceAccount.ts +2165 -0
- package/src/database/_generated/project/models/Terminal.ts +2038 -0
- package/src/database/_generated/project/models/TerminalSession.ts +1454 -0
- package/src/database/_generated/project/models/TerminalSessionLog.ts +1280 -0
- package/src/database/_generated/project/models/Trigger.ts +1430 -0
- package/src/database/_generated/project/models/UnlockMethod.ts +1220 -0
- package/src/database/_generated/project/models/UserCompositeViewport.ts +1280 -0
- package/src/database/_generated/project/models/UserProjectViewport.ts +1059 -0
- package/src/database/_generated/project/models/Worker.ts +1459 -0
- package/src/database/_generated/project/models/WorkerUnitRegistration.ts +1524 -0
- package/src/database/_generated/project/models/WorkerVersion.ts +1974 -0
- package/src/database/_generated/project/models/WorkerVersionLog.ts +1318 -0
- package/src/database/_generated/project/models.ts +35 -0
- package/src/database/_generated/project/pjtg.ts +182 -0
- package/src/database/abstractions.ts +19 -0
- package/src/database/factory.ts +37 -0
- package/src/database/index.ts +6 -0
- package/src/database/local/backend.ts +134 -0
- package/src/database/local/index.ts +3 -0
- package/src/database/local/meta.ts +46 -0
- package/src/database/local/prisma.config.ts +25 -0
- package/src/database/local/project.ts +39 -0
- package/src/database/manager.ts +181 -0
- package/src/database/migrate.ts +35 -0
- package/src/database/prisma.ts +56 -0
- package/src/database/well-known.ts +38 -0
- package/src/index.ts +4 -4
- package/src/library/abstractions.ts +21 -14
- package/src/library/factory.ts +1 -1
- package/src/library/local.ts +86 -38
- package/src/library/package-resolution-worker.ts +1 -1
- package/src/library/worker/evaluator.ts +61 -48
- package/src/library/worker/loader.lite.ts +14 -1
- package/src/library/worker/main.ts +9 -16
- package/src/library/worker/protocol.ts +0 -12
- package/src/lock/manager.ts +12 -7
- package/src/orchestrator/manager.ts +198 -131
- package/src/orchestrator/operation-context.ts +357 -0
- package/src/orchestrator/operation-plan.destroy.test.md +357 -0
- package/src/orchestrator/operation-plan.destroy.test.ts +775 -0
- package/src/orchestrator/operation-plan.fixtures.ts +213 -0
- package/src/orchestrator/operation-plan.md +198 -0
- package/src/orchestrator/operation-plan.refresh.test.md +199 -0
- package/src/orchestrator/operation-plan.refresh.test.ts +367 -0
- package/src/orchestrator/operation-plan.ts +709 -0
- package/src/orchestrator/operation-plan.update.test.md +485 -0
- package/src/orchestrator/operation-plan.update.test.ts +1066 -0
- package/src/orchestrator/operation-workset.ts +235 -583
- package/src/orchestrator/operation.ts +446 -904
- package/src/orchestrator/plan-test-builder.ts +267 -0
- package/src/project-model/abstractions.ts +118 -0
- package/src/project-model/backends/codebase.ts +365 -0
- package/src/project-model/backends/database.ts +440 -0
- package/src/project-model/errors.ts +81 -0
- package/src/project-model/factory.ts +24 -0
- package/src/project-model/index.ts +4 -0
- package/src/project-model/utils.test.ts +544 -0
- package/src/project-model/utils.ts +242 -0
- package/src/pubsub/abstractions.ts +10 -1
- package/src/pubsub/factory.ts +4 -4
- package/src/pubsub/index.ts +1 -0
- package/src/pubsub/manager.ts +49 -25
- package/src/pubsub/memory.ts +31 -0
- package/src/runner/abstractions.ts +38 -26
- package/src/runner/artifact-env.ts +17 -6
- package/src/runner/factory.ts +6 -6
- package/src/runner/force-abort.ts +3 -6
- package/src/runner/local.ts +79 -72
- package/src/runner/pulumi.ts +26 -63
- package/src/services.ts +214 -103
- package/src/shared/models/backend/index.ts +3 -1
- package/src/shared/models/backend/library.ts +12 -4
- package/src/shared/models/backend/project.ts +43 -23
- package/src/shared/models/backend/pulumi.ts +14 -0
- package/src/shared/models/backend/unlock-method.ts +1 -1
- package/src/shared/models/backend/well-known.ts +58 -0
- package/src/shared/models/base.ts +40 -109
- package/src/shared/models/errors.ts +82 -1
- package/src/shared/models/index.ts +3 -2
- package/src/shared/models/prisma.ts +36 -0
- package/src/shared/models/project/api-key.ts +37 -56
- package/src/shared/models/project/artifact.ts +15 -105
- package/src/shared/models/project/custom-status.ts +12 -0
- package/src/shared/models/project/index.ts +9 -9
- package/src/shared/models/project/lock.ts +10 -78
- package/src/shared/models/project/model.ts +32 -0
- package/src/shared/models/project/operation.ts +222 -99
- package/src/shared/models/project/page.ts +37 -48
- package/src/shared/models/project/secret.ts +29 -103
- package/src/shared/models/project/service-account.ts +12 -17
- package/src/shared/models/project/state.ts +100 -390
- package/src/shared/models/project/terminal.ts +75 -89
- package/src/shared/models/project/trigger.ts +13 -49
- package/src/shared/models/project/unlock-method.ts +21 -20
- package/src/shared/models/project/worker.ts +89 -88
- package/src/shared/resolvers/graph-resolver.ts +62 -26
- package/src/shared/resolvers/index.ts +1 -1
- package/src/shared/resolvers/input-hash.ts +24 -14
- package/src/shared/resolvers/input.ts +48 -6
- package/src/shared/resolvers/registry.ts +5 -4
- package/src/shared/resolvers/state.ts +12 -1
- package/src/shared/resolvers/validation.ts +29 -9
- package/src/shared/utils/index.ts +1 -1
- package/src/shared/utils/promise-tracker.ts +30 -3
- package/src/terminal/abstractions.ts +1 -1
- package/src/terminal/docker.ts +3 -3
- package/src/terminal/manager.ts +102 -118
- package/src/test-utils/database.ts +119 -0
- package/src/test-utils/index.ts +2 -0
- package/src/test-utils/services.ts +134 -0
- package/src/unlock/abstractions.ts +31 -0
- package/src/unlock/index.ts +2 -0
- package/src/unlock/memory.ts +27 -0
- package/src/worker/abstractions.ts +7 -4
- package/src/worker/docker.ts +14 -19
- package/src/worker/manager.ts +376 -79
- package/dist/chunk-RCB4AFGD.js.map +0 -1
- package/dist/chunk-WHALQHEZ.js +0 -2017
- package/dist/chunk-WHALQHEZ.js.map +0 -1
- package/src/business/backend-unlock.ts +0 -10
- package/src/common/performance.ts +0 -44
- package/src/hotstate/abstractions.ts +0 -48
- package/src/hotstate/factory.ts +0 -17
- package/src/hotstate/index.ts +0 -3
- package/src/hotstate/manager.ts +0 -192
- package/src/hotstate/memory.ts +0 -100
- package/src/hotstate/validation.ts +0 -101
- package/src/project/abstractions.ts +0 -102
- package/src/project/factory.ts +0 -11
- package/src/project/index.ts +0 -3
- package/src/project/local.ts +0 -469
- package/src/project/manager.ts +0 -574
- package/src/pubsub/local.ts +0 -36
- package/src/pubsub/validation.ts +0 -33
- package/src/shared/models/project/component.ts +0 -45
- package/src/shared/models/project/instance.ts +0 -74
- package/src/state/abstractions.ts +0 -450
- package/src/state/encryption.ts +0 -59
- package/src/state/factory.ts +0 -20
- package/src/state/index.ts +0 -6
- package/src/state/local/backend.ts +0 -299
- package/src/state/local/collection.ts +0 -342
- package/src/state/local/index.ts +0 -2
- package/src/state/manager.ts +0 -819
- package/src/state/repository/index.ts +0 -2
- package/src/state/repository/repository.index.ts +0 -193
- package/src/state/repository/repository.ts +0 -458
- /package/src/{state → database/local}/keyring.ts +0 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import type { InstanceId, InstanceModel } from "@highstate/contract"
|
|
2
|
+
import type { Logger } from "pino"
|
|
3
|
+
import type { LibraryBackend } from "../library"
|
|
4
|
+
import type { PubSubManager } from "../pubsub"
|
|
5
|
+
import type { ProjectModelService } from "./project-model"
|
|
6
|
+
import type { ProjectUnlockService } from "./project-unlock"
|
|
7
|
+
import { isNonNullish } from "remeda"
|
|
8
|
+
import { renderTree, type TreeNode } from "../common"
|
|
9
|
+
import {
|
|
10
|
+
type DatabaseManager,
|
|
11
|
+
DbNull,
|
|
12
|
+
type InstanceEvaluationStateUncheckedCreateInput,
|
|
13
|
+
type InstanceEvaluationStateUpdateInput,
|
|
14
|
+
type InstanceStatus,
|
|
15
|
+
} from "../database"
|
|
16
|
+
|
|
17
|
+
type EvaluatedInstance = {
|
|
18
|
+
instanceId: InstanceId
|
|
19
|
+
status: "evaluated" | "error"
|
|
20
|
+
message?: string
|
|
21
|
+
model?: InstanceModel | null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export class ProjectEvaluationSubsystem {
|
|
25
|
+
private readonly projectWatchers = new Map<string, AbortController>()
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
private readonly database: DatabaseManager,
|
|
29
|
+
private readonly libraryBackend: LibraryBackend,
|
|
30
|
+
private readonly projectModelService: ProjectModelService,
|
|
31
|
+
private readonly pubsubManager: PubSubManager,
|
|
32
|
+
private readonly projectUnlockService: ProjectUnlockService,
|
|
33
|
+
private readonly logger: Logger,
|
|
34
|
+
) {
|
|
35
|
+
this.projectUnlockService.registerUnlockTask(
|
|
36
|
+
"evaluate-project",
|
|
37
|
+
//
|
|
38
|
+
projectId => this.evaluateProject(projectId),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
this.projectUnlockService.registerUnlockTask(
|
|
42
|
+
//
|
|
43
|
+
"track-unlocked-project",
|
|
44
|
+
projectId => this.trackUnlockedProject(projectId),
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async evaluateProject(projectId: string): Promise<void> {
|
|
49
|
+
const { project, instances, resolvedInputs } =
|
|
50
|
+
await this.projectModelService.resolveProject(projectId)
|
|
51
|
+
|
|
52
|
+
const instancesMap = new Map<string, InstanceModel>()
|
|
53
|
+
for (const instance of instances) {
|
|
54
|
+
instancesMap.set(instance.id, instance)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const compositeInstanceIds = instances
|
|
58
|
+
.filter(instance => instance.kind === "composite")
|
|
59
|
+
.map(instance => instance.id)
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const result = await this.libraryBackend.evaluateCompositeInstances(
|
|
63
|
+
project.libraryId,
|
|
64
|
+
instances,
|
|
65
|
+
resolvedInputs,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
if (result.success) {
|
|
69
|
+
// create evaluation tree for success messages
|
|
70
|
+
const treeNodes = ProjectEvaluationSubsystem.createEvaluatedInstanceTree(
|
|
71
|
+
result.virtualInstances,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
// store evaluation states for virtual instances
|
|
75
|
+
const evaluatedInstances: EvaluatedInstance[] = result.virtualInstances.map(instance => ({
|
|
76
|
+
instanceId: instance.id as InstanceId,
|
|
77
|
+
status: "evaluated",
|
|
78
|
+
message: ProjectEvaluationSubsystem.renderEvaluationMessage(treeNodes, instance.id),
|
|
79
|
+
model: instance,
|
|
80
|
+
}))
|
|
81
|
+
|
|
82
|
+
const errorEvaluatedInstances: EvaluatedInstance[] = Object.entries(
|
|
83
|
+
result.topLevelErrors,
|
|
84
|
+
).map(([instanceId, message]) => ({
|
|
85
|
+
instanceId: instanceId as InstanceId,
|
|
86
|
+
status: "error",
|
|
87
|
+
message,
|
|
88
|
+
model: null,
|
|
89
|
+
}))
|
|
90
|
+
|
|
91
|
+
await this.setInstanceEvaluationStates(project.id, [
|
|
92
|
+
...evaluatedInstances,
|
|
93
|
+
...errorEvaluatedInstances,
|
|
94
|
+
])
|
|
95
|
+
} else {
|
|
96
|
+
// set all composite instances to error state in evaluation
|
|
97
|
+
const errorEvaluationStates: EvaluatedInstance[] = compositeInstanceIds.map(instanceId => ({
|
|
98
|
+
instanceId: instanceId as InstanceId,
|
|
99
|
+
status: "error",
|
|
100
|
+
message: result.error,
|
|
101
|
+
model: instancesMap.get(instanceId) ?? null,
|
|
102
|
+
}))
|
|
103
|
+
|
|
104
|
+
await this.setInstanceEvaluationStates(project.id, errorEvaluationStates)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.logger.info(
|
|
108
|
+
{ projectId: project.id, compositeInstanceIds },
|
|
109
|
+
"composite instances evaluation completed",
|
|
110
|
+
)
|
|
111
|
+
} catch (error) {
|
|
112
|
+
this.logger.error({ projectId: project.id, error }, "failed to evaluate project")
|
|
113
|
+
|
|
114
|
+
// set all composite instances to internal error state
|
|
115
|
+
const internalErrorStates: EvaluatedInstance[] = compositeInstanceIds.map(instanceId => ({
|
|
116
|
+
instanceId: instanceId as InstanceId,
|
|
117
|
+
status: "error",
|
|
118
|
+
message: "Internal error occurred during evaluation.",
|
|
119
|
+
model: instancesMap.get(instanceId) ?? null,
|
|
120
|
+
}))
|
|
121
|
+
|
|
122
|
+
await this.setInstanceEvaluationStates(project.id, internalErrorStates)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Sets the evaluation states for multiple instances in a project.
|
|
128
|
+
*
|
|
129
|
+
* @param projectId The ID of the project to update.
|
|
130
|
+
* @param evaluatedInstances The evaluation states to set.
|
|
131
|
+
*/
|
|
132
|
+
private async setInstanceEvaluationStates(
|
|
133
|
+
projectId: string,
|
|
134
|
+
evaluatedInstances: EvaluatedInstance[],
|
|
135
|
+
): Promise<void> {
|
|
136
|
+
const database = await this.database.forProject(projectId)
|
|
137
|
+
|
|
138
|
+
await database.$transaction(async tx => {
|
|
139
|
+
// 1. resolve instanceId -> stateId for all evaluated instances
|
|
140
|
+
// also ensure that all states exist and has "virtual" source
|
|
141
|
+
const instanceIdToStateMap = new Map<
|
|
142
|
+
string,
|
|
143
|
+
{ id: string; status: InstanceStatus; model: InstanceModel | null }
|
|
144
|
+
>()
|
|
145
|
+
|
|
146
|
+
for (const instance of evaluatedInstances) {
|
|
147
|
+
const state = await tx.instanceState.upsert({
|
|
148
|
+
select: { id: true, status: true, model: true },
|
|
149
|
+
where: { instanceId: instance.instanceId },
|
|
150
|
+
create: {
|
|
151
|
+
instanceId: instance.instanceId,
|
|
152
|
+
kind: instance.model?.kind ?? "unit",
|
|
153
|
+
source: "virtual",
|
|
154
|
+
status: "undeployed",
|
|
155
|
+
},
|
|
156
|
+
update: {
|
|
157
|
+
source: "virtual",
|
|
158
|
+
},
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
instanceIdToStateMap.set(instance.instanceId, state)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 2. convert EvaluatedInstance[] to InstanceEvaluationStateUncheckedCreateInput[]
|
|
165
|
+
const states: InstanceEvaluationStateUncheckedCreateInput[] = evaluatedInstances.map(ei => {
|
|
166
|
+
return {
|
|
167
|
+
// biome-ignore lint/style/noNonNullAssertion: we ensure this is always set
|
|
168
|
+
stateId: instanceIdToStateMap.get(ei.instanceId)!.id,
|
|
169
|
+
status: ei.status,
|
|
170
|
+
message: ei.message,
|
|
171
|
+
model: ei.model ?? DbNull,
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
// 3. persist the evaluation states
|
|
176
|
+
const existingStates = await tx.instanceEvaluationState.findMany({
|
|
177
|
+
select: { stateId: true, state: { select: { instanceId: true } } },
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const existingStateIds = new Set(existingStates.map(state => state.stateId))
|
|
181
|
+
const actualStateIds = new Set(states.map(state => state.stateId))
|
|
182
|
+
|
|
183
|
+
const newStates = states.filter(state => !existingStateIds.has(state.stateId))
|
|
184
|
+
const statesToUpdate = states.filter(state => existingStateIds.has(state.stateId))
|
|
185
|
+
const statesToDelete = existingStates.filter(state => !actualStateIds.has(state.stateId))
|
|
186
|
+
|
|
187
|
+
// create new states
|
|
188
|
+
await tx.instanceEvaluationState.createMany({ data: newStates })
|
|
189
|
+
|
|
190
|
+
// update existing states
|
|
191
|
+
const updatedStates = await Promise.all(
|
|
192
|
+
statesToUpdate.map(state =>
|
|
193
|
+
tx.instanceEvaluationState.update({
|
|
194
|
+
where: { stateId: state.stateId },
|
|
195
|
+
data: state as InstanceEvaluationStateUpdateInput,
|
|
196
|
+
}),
|
|
197
|
+
),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
// delete states that are no longer present
|
|
201
|
+
await tx.instanceEvaluationState.deleteMany({
|
|
202
|
+
where: {
|
|
203
|
+
stateId: {
|
|
204
|
+
in: statesToDelete.map(state => state.stateId),
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
// 5. publish evaluation state updates
|
|
210
|
+
for (const state of updatedStates) {
|
|
211
|
+
void this.pubsubManager.publish(["instance-state", projectId], {
|
|
212
|
+
type: "patched",
|
|
213
|
+
stateId: state.stateId,
|
|
214
|
+
patch: {
|
|
215
|
+
evaluationState: state,
|
|
216
|
+
},
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// 6. publish project model update
|
|
221
|
+
void this.pubsubManager.publish(["project-model", projectId], {
|
|
222
|
+
updatedVirtualInstances: updatedStates.map(state => state.model).filter(isNonNullish),
|
|
223
|
+
deletedVirtualInstanceIds: statesToDelete.map(state => state.state.instanceId),
|
|
224
|
+
|
|
225
|
+
updatedGhostInstances: statesToDelete
|
|
226
|
+
.map(state => instanceIdToStateMap.get(state.state.instanceId))
|
|
227
|
+
.filter(isNonNullish)
|
|
228
|
+
.filter(state => state.status !== "undeployed")
|
|
229
|
+
.map(state => state.model)
|
|
230
|
+
.filter(isNonNullish),
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private async trackUnlockedProject(projectId: string): Promise<void> {
|
|
236
|
+
if (this.projectWatchers.has(projectId)) {
|
|
237
|
+
this.logger.debug({ projectId }, "project already being tracked, skipping")
|
|
238
|
+
return
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
try {
|
|
242
|
+
const project = await this.database.backend.project.findUnique({
|
|
243
|
+
where: { id: projectId },
|
|
244
|
+
select: { id: true, libraryId: true },
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
if (!project) {
|
|
248
|
+
this.logger.warn({ projectId }, "project not found, cannot track")
|
|
249
|
+
return
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const controller = new AbortController()
|
|
253
|
+
|
|
254
|
+
this.projectWatchers.set(projectId, controller)
|
|
255
|
+
this.logger.debug(
|
|
256
|
+
{ projectId, libraryId: project.libraryId },
|
|
257
|
+
"tracking unlocked project for library reload evaluations",
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
void this.startProjectLibraryWatcher(projectId, project.libraryId, controller.signal)
|
|
261
|
+
} catch (error) {
|
|
262
|
+
this.logger.error({ projectId, error }, "failed to start tracking project")
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
private async startProjectLibraryWatcher(
|
|
267
|
+
projectId: string,
|
|
268
|
+
libraryId: string,
|
|
269
|
+
signal: AbortSignal,
|
|
270
|
+
): Promise<void> {
|
|
271
|
+
try {
|
|
272
|
+
for await (const updates of this.libraryBackend.watchLibrary(libraryId, signal)) {
|
|
273
|
+
// only handle reload-completed events
|
|
274
|
+
if (updates.some(update => update.type === "reload-completed")) {
|
|
275
|
+
await this.handleProjectLibraryReload(projectId)
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
this.logger.error({ projectId, libraryId, error }, "project library reload watcher failed")
|
|
280
|
+
} finally {
|
|
281
|
+
this.projectWatchers.delete(projectId)
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private async handleProjectLibraryReload(projectId: string): Promise<void> {
|
|
286
|
+
this.logger.info({ projectId }, "launching evaluation for project after library reload")
|
|
287
|
+
|
|
288
|
+
try {
|
|
289
|
+
await this.evaluateProject(projectId)
|
|
290
|
+
} catch (error) {
|
|
291
|
+
this.logger.error({ projectId, error }, "failed to evaluate project after library reload")
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
static createEvaluatedInstanceTree(virtualInstances: InstanceModel[]): Map<string, TreeNode> {
|
|
296
|
+
const treeNodes = new Map<string, TreeNode>()
|
|
297
|
+
|
|
298
|
+
for (const instance of virtualInstances) {
|
|
299
|
+
const node: TreeNode = {
|
|
300
|
+
text: instance.id,
|
|
301
|
+
children: [],
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
treeNodes.set(instance.id, node)
|
|
305
|
+
|
|
306
|
+
const parentNode = instance.parentId ? treeNodes.get(instance.parentId) : undefined
|
|
307
|
+
|
|
308
|
+
if (parentNode) {
|
|
309
|
+
parentNode.children.push(node)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return treeNodes
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
static renderEvaluationMessage(treeNodes: Map<string, TreeNode>, rootNodeId: string): string {
|
|
317
|
+
// get the root node
|
|
318
|
+
const rootNode = treeNodes.get(rootNodeId)
|
|
319
|
+
if (!rootNode) {
|
|
320
|
+
return `Composite instance evaluation completed successfully, but failed to build the tree structure.`
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// render the tree structure
|
|
324
|
+
const tree = renderTree(rootNode)
|
|
325
|
+
|
|
326
|
+
return `Composite instance evaluation completed successfully.\n\nInstance Tree:\n${tree}`
|
|
327
|
+
}
|
|
328
|
+
}
|
package/src/business/index.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
export * from "./api-key"
|
|
2
2
|
export * from "./artifact"
|
|
3
|
-
export * from "./backend-unlock"
|
|
4
3
|
export * from "./instance-lock"
|
|
5
4
|
export * from "./instance-state"
|
|
6
5
|
export * from "./operation"
|
|
6
|
+
export * from "./project"
|
|
7
|
+
export * from "./project-model"
|
|
7
8
|
export * from "./project-unlock"
|
|
8
9
|
export * from "./secret"
|
|
10
|
+
export * from "./settings"
|
|
11
|
+
export * from "./terminal-session"
|
|
12
|
+
export * from "./unit-extra"
|
|
9
13
|
export * from "./worker"
|