@highstate/backend 0.9.18 → 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-OU5OQBLB.js → chunk-I7BWSAN6.js} +3 -28
- package/dist/{chunk-OU5OQBLB.js.map → chunk-I7BWSAN6.js.map} +1 -1
- package/dist/chunk-VB4YL327.js +139 -0
- 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 +2 -1
- package/dist/index.js +7587 -7291
- package/dist/index.js.map +1 -1
- package/dist/library/package-resolution-worker.js +1 -1
- package/dist/library/package-resolution-worker.js.map +1 -1
- package/dist/library/worker/main.js +35 -29
- package/dist/library/worker/main.js.map +1 -1
- package/dist/shared/index.js +2 -2
- package/package.json +18 -9
- 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 +30 -54
- package/src/artifact/factory.ts +6 -9
- package/src/artifact/local.ts +33 -46
- package/src/business/api-key.ts +24 -36
- package/src/business/artifact.test.ts +978 -0
- package/src/business/artifact.ts +136 -216
- package/src/business/evaluation.ts +328 -0
- package/src/business/index.ts +5 -2
- package/src/business/instance-lock.test.ts +1060 -0
- package/src/business/instance-lock.ts +387 -78
- package/src/business/instance-state.test.ts +735 -0
- package/src/business/instance-state.ts +582 -337
- 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 +168 -126
- package/src/business/project.ts +287 -179
- package/src/business/secret.test.ts +465 -130
- package/src/business/secret.ts +186 -217
- 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 +356 -579
- package/src/business/worker.ts +238 -339
- package/src/common/codebase.ts +65 -0
- package/src/common/index.ts +3 -5
- package/src/common/logger.ts +5 -0
- package/src/common/utils.ts +4 -3
- package/src/config.ts +10 -11
- 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 +3 -5
- package/src/library/factory.ts +1 -1
- package/src/library/local.ts +81 -26
- package/src/library/package-resolution-worker.ts +1 -1
- package/src/library/worker/evaluator.ts +40 -23
- package/src/library/worker/loader.lite.ts +1 -1
- package/src/library/worker/main.ts +3 -10
- package/src/library/worker/protocol.ts +0 -1
- package/src/lock/index.ts +0 -1
- package/src/lock/manager.ts +0 -10
- package/src/orchestrator/manager.ts +190 -104
- 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 +233 -578
- package/src/orchestrator/operation.ts +435 -948
- 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 +29 -13
- package/src/pubsub/memory.ts +31 -0
- package/src/runner/abstractions.ts +33 -41
- package/src/runner/artifact-env.ts +19 -8
- package/src/runner/factory.ts +6 -6
- package/src/runner/force-abort.ts +3 -6
- package/src/runner/local.ts +64 -67
- package/src/runner/pulumi.ts +23 -63
- package/src/services.ts +181 -123
- package/src/shared/models/backend/index.ts +3 -1
- package/src/shared/models/backend/library.ts +9 -1
- package/src/shared/models/backend/project.ts +43 -42
- 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 -26
- 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 -59
- package/src/shared/models/project/artifact.ts +16 -76
- package/src/shared/models/project/custom-status.ts +12 -0
- package/src/shared/models/project/index.ts +8 -7
- package/src/shared/models/project/lock.ts +10 -78
- package/src/shared/models/project/model.ts +19 -1
- 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 -89
- package/src/shared/models/project/service-account.ts +12 -17
- package/src/shared/models/project/state.ts +100 -407
- package/src/shared/models/project/terminal.ts +75 -88
- package/src/shared/models/project/trigger.ts +13 -49
- package/src/shared/models/project/unlock-method.ts +20 -26
- package/src/shared/models/project/worker.ts +89 -90
- package/src/shared/resolvers/graph-resolver.ts +21 -0
- package/src/shared/resolvers/index.ts +1 -1
- package/src/shared/resolvers/input-hash.ts +24 -14
- package/src/shared/resolvers/input.ts +1 -1
- package/src/shared/resolvers/registry.ts +5 -4
- package/src/shared/resolvers/state.ts +12 -1
- package/src/shared/resolvers/validation.ts +7 -3
- package/src/shared/utils/index.ts +1 -2
- 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 +5 -23
- package/src/unlock/memory.ts +9 -14
- package/src/worker/abstractions.ts +7 -4
- package/src/worker/docker.ts +14 -19
- package/src/worker/manager.ts +366 -97
- package/dist/chunk-NAAIDR4U.js +0 -8499
- package/dist/chunk-NAAIDR4U.js.map +0 -1
- package/dist/chunk-Y7DXREVO.js +0 -1745
- package/dist/chunk-Y7DXREVO.js.map +0 -1
- package/dist/magic-string.es-5ABAC4JN.js +0 -1292
- package/dist/magic-string.es-5ABAC4JN.js.map +0 -1
- package/src/business/__traces__/secret/update-instance-secrets/create-and-delete-secrets-simultaneously.md +0 -356
- package/src/business/__traces__/secret/update-instance-secrets/create-new-secrets-for-instance.md +0 -274
- package/src/business/__traces__/secret/update-instance-secrets/delete-existing-secrets.md +0 -223
- package/src/business/__traces__/secret/update-instance-secrets/no-op-when-no-changes.md +0 -147
- package/src/business/__traces__/secret/update-instance-secrets/update-existing-secrets.md +0 -280
- package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration-when-other-exists.md +0 -360
- package/src/business/__traces__/worker/update-unit-registrations/add-new-unit-registration.md +0 -215
- package/src/business/__traces__/worker/update-unit-registrations/create-multiple-workers-with-different-identities.md +0 -427
- package/src/business/__traces__/worker/update-unit-registrations/handle-nonexistent-registration-id-gracefully.md +0 -217
- package/src/business/__traces__/worker/update-unit-registrations/no-op-when-no-changes.md +0 -132
- package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-changes.md +0 -454
- package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-when-image-version-changes.md +0 -426
- package/src/business/__traces__/worker/update-unit-registrations/recreate-worker-with-same-identity-reuses-service-account.md +0 -372
- package/src/business/__traces__/worker/update-unit-registrations/remove-one-of-multiple-unit-registrations.md +0 -383
- package/src/business/__traces__/worker/update-unit-registrations/remove-unit-registration.md +0 -245
- package/src/business/__traces__/worker/update-unit-registrations/update-existing-unit-registration-when-params-change.md +0 -174
- package/src/business/__traces__/worker/update-unit-registrations/update-params-and-image-simultaneously.md +0 -432
- package/src/business/__traces__/worker/update-unit-registrations/worker-with-multiple-registrations-not-deleted-when-one-removed.md +0 -220
- package/src/business/backend-unlock.ts +0 -10
- package/src/common/clock.ts +0 -18
- package/src/common/performance.ts +0 -44
- package/src/common/random.ts +0 -68
- package/src/common/test/index.ts +0 -2
- package/src/common/test/render.ts +0 -98
- package/src/common/test/tracer.ts +0 -359
- 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 -100
- package/src/lock/test.ts +0 -108
- package/src/project/abstractions.ts +0 -78
- package/src/project/evaluation.ts +0 -248
- package/src/project/factory.ts +0 -11
- package/src/project/index.ts +0 -3
- package/src/project/local.ts +0 -417
- package/src/pubsub/local.ts +0 -36
- package/src/pubsub/validation.ts +0 -33
- package/src/shared/utils/args.ts +0 -25
- package/src/state/abstractions.ts +0 -289
- package/src/state/encryption.ts +0 -98
- package/src/state/factory.ts +0 -20
- package/src/state/index.ts +0 -7
- package/src/state/local/backend.ts +0 -106
- package/src/state/local/collection.ts +0 -361
- package/src/state/local/index.ts +0 -2
- package/src/state/manager.ts +0 -890
- package/src/state/memory/backend.ts +0 -70
- package/src/state/memory/collection.ts +0 -270
- package/src/state/memory/index.ts +0 -2
- package/src/state/repository/index.ts +0 -2
- package/src/state/repository/repository.index.ts +0 -193
- package/src/state/repository/repository.ts +0 -507
- package/src/state/test.ts +0 -457
- /package/src/{state → database/local}/keyring.ts +0 -0
package/src/business/worker.ts
CHANGED
|
@@ -1,398 +1,297 @@
|
|
|
1
|
+
import type { CommonObjectMeta, UnitWorker } from "@highstate/contract"
|
|
1
2
|
import type { Logger } from "pino"
|
|
2
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
DatabaseManager,
|
|
5
|
+
ProjectTransaction,
|
|
6
|
+
Worker,
|
|
7
|
+
WorkerVersion,
|
|
8
|
+
WorkerVersionLog,
|
|
9
|
+
} from "../database"
|
|
10
|
+
import type { PubSubManager } from "../pubsub"
|
|
3
11
|
import type { WorkerManager } from "../worker"
|
|
4
|
-
import
|
|
12
|
+
import { randomBytes } from "node:crypto"
|
|
13
|
+
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/client"
|
|
14
|
+
import { createProjectLogger } from "../common"
|
|
5
15
|
import {
|
|
16
|
+
extractDigestFromImage,
|
|
6
17
|
getWorkerIdentity,
|
|
7
|
-
type
|
|
8
|
-
type ServiceAccount,
|
|
9
|
-
type UnitWorker,
|
|
10
|
-
type Worker,
|
|
11
|
-
type WorkerUnitRegistration,
|
|
18
|
+
type WorkerUnitRegistrationEvent,
|
|
12
19
|
} from "../shared"
|
|
13
|
-
import {
|
|
20
|
+
import { WorkerVersionNotFoundError } from "../shared/models/errors"
|
|
14
21
|
|
|
15
22
|
export class WorkerService {
|
|
16
23
|
constructor(
|
|
17
|
-
private readonly
|
|
24
|
+
private readonly database: DatabaseManager,
|
|
18
25
|
private readonly workerManager: WorkerManager,
|
|
19
|
-
private readonly
|
|
20
|
-
private readonly random: RandomProvider,
|
|
26
|
+
private readonly pubsubManager: PubSubManager,
|
|
21
27
|
private readonly logger: Logger,
|
|
22
28
|
) {}
|
|
23
29
|
|
|
24
30
|
/**
|
|
25
|
-
* Updates
|
|
26
|
-
*
|
|
27
|
-
* and deletes registrations that are no longer present.
|
|
31
|
+
* Updates unit worker registrations for an instance in a single transaction
|
|
32
|
+
* creates workers and worker versions as needed and cleans up removed registrations
|
|
28
33
|
*
|
|
29
|
-
* @param
|
|
30
|
-
* @param
|
|
31
|
-
* @param
|
|
32
|
-
* @param unitWorkers The list
|
|
33
|
-
* @returns A new mapping of unit worker names to their registration IDs.
|
|
34
|
+
* @param tx The transaction to use for database operations.
|
|
35
|
+
* @param projectId The ID of the project containing the instance.
|
|
36
|
+
* @param stateId The ID of the instance state to update registrations for.
|
|
37
|
+
* @param unitWorkers The list workers provided by the unit.
|
|
34
38
|
*/
|
|
35
39
|
async updateUnitRegistrations(
|
|
40
|
+
tx: ProjectTransaction,
|
|
36
41
|
projectId: string,
|
|
37
|
-
|
|
38
|
-
existingRegistrationIds: Record<string, string>,
|
|
42
|
+
stateId: string,
|
|
39
43
|
unitWorkers: UnitWorker[],
|
|
40
|
-
): Promise<
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const lockKeys = unitWorkers.map(
|
|
46
|
-
unitWorker => ["worker-image", projectId, unitWorker.image] as const,
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
const newRegistrationIds: Record<string, string> = {}
|
|
50
|
-
|
|
51
|
-
return await this.lockManager.acquire(lockKeys, async () => {
|
|
52
|
-
const existingRegistrations = await this.stateManager
|
|
53
|
-
.getWorkerRegistrationRepository(projectId)
|
|
54
|
-
.getManyRecord(Object.values(existingRegistrationIds))
|
|
55
|
-
|
|
56
|
-
const nameToExistingRegistration = new Map<string, WorkerUnitRegistration>()
|
|
57
|
-
for (const [name, registrationId] of Object.entries(existingRegistrationIds)) {
|
|
58
|
-
const existingRegistration = existingRegistrations[registrationId]
|
|
59
|
-
if (existingRegistration) {
|
|
60
|
-
nameToExistingRegistration.set(name, existingRegistration)
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const batch = this.stateManager.batch()
|
|
65
|
-
|
|
66
|
-
// create or update registrations for each unit worker
|
|
67
|
-
for (const unitWorker of unitWorkers) {
|
|
68
|
-
const workerId = await this.ensureWorkerCreated(projectId, unitWorker)
|
|
69
|
-
const existingRegistration = nameToExistingRegistration.get(unitWorker.name)
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
existingRegistration &&
|
|
73
|
-
existingRegistration.workerId === workerId &&
|
|
74
|
-
JSON.stringify(existingRegistration.params) === JSON.stringify(unitWorker.params)
|
|
75
|
-
) {
|
|
76
|
-
// no changes
|
|
77
|
-
newRegistrationIds[unitWorker.name] = existingRegistration.id
|
|
78
|
-
continue
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const registration: WorkerUnitRegistration = {
|
|
82
|
-
id: existingRegistration?.id ?? this.random.uuidv7(),
|
|
83
|
-
meta: existingRegistration?.meta ?? {},
|
|
84
|
-
image: unitWorker.image,
|
|
85
|
-
params: unitWorker.params,
|
|
86
|
-
instanceId,
|
|
87
|
-
workerId,
|
|
88
|
-
}
|
|
44
|
+
): Promise<void> {
|
|
45
|
+
// parse images first
|
|
46
|
+
const parsedWorkers = unitWorkers.map(w => {
|
|
47
|
+
const digest = extractDigestFromImage(w.image)
|
|
48
|
+
const identity = getWorkerIdentity(w.image)
|
|
89
49
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const isParamsChange =
|
|
93
|
-
existingRegistration &&
|
|
94
|
-
JSON.stringify(existingRegistration.params) !== JSON.stringify(unitWorker.params)
|
|
95
|
-
|
|
96
|
-
if (isNewRegistration) {
|
|
97
|
-
this.logger.info(
|
|
98
|
-
{
|
|
99
|
-
projectId,
|
|
100
|
-
registrationId: registration.id,
|
|
101
|
-
unitWorkerName: unitWorker.name,
|
|
102
|
-
workerId,
|
|
103
|
-
image: unitWorker.image,
|
|
104
|
-
},
|
|
105
|
-
`creating worker registration "%s" for unit worker "%s" in project "%s"`,
|
|
106
|
-
registration.id,
|
|
107
|
-
unitWorker.name,
|
|
108
|
-
projectId,
|
|
109
|
-
)
|
|
110
|
-
} else if (isWorkerChange) {
|
|
111
|
-
this.logger.info(
|
|
112
|
-
{
|
|
113
|
-
projectId,
|
|
114
|
-
registrationId: registration.id,
|
|
115
|
-
unitWorkerName: unitWorker.name,
|
|
116
|
-
oldWorkerId: existingRegistration?.workerId,
|
|
117
|
-
newWorkerId: workerId,
|
|
118
|
-
oldImage: existingRegistration?.image,
|
|
119
|
-
newImage: unitWorker.image,
|
|
120
|
-
},
|
|
121
|
-
`updating worker registration "%s" for unit worker "%s" in project "%s" (worker changed from "%s" to "%s")`,
|
|
122
|
-
registration.id,
|
|
123
|
-
unitWorker.name,
|
|
124
|
-
projectId,
|
|
125
|
-
existingRegistration?.workerId,
|
|
126
|
-
workerId,
|
|
127
|
-
)
|
|
128
|
-
} else if (isParamsChange) {
|
|
129
|
-
this.logger.info(
|
|
130
|
-
{
|
|
131
|
-
projectId,
|
|
132
|
-
registrationId: registration.id,
|
|
133
|
-
unitWorkerName: unitWorker.name,
|
|
134
|
-
workerId,
|
|
135
|
-
},
|
|
136
|
-
`updating worker registration "%s" for unit worker "%s" in project "%s" (params changed)`,
|
|
137
|
-
registration.id,
|
|
138
|
-
unitWorker.name,
|
|
139
|
-
projectId,
|
|
140
|
-
)
|
|
141
|
-
}
|
|
50
|
+
return { ...w, digest, identity }
|
|
51
|
+
})
|
|
142
52
|
|
|
143
|
-
|
|
144
|
-
.getWorkerRegistrationRepository(projectId)
|
|
145
|
-
.putItem(registration, batch)
|
|
53
|
+
const logger = createProjectLogger(this.logger, projectId)
|
|
146
54
|
|
|
147
|
-
|
|
148
|
-
if (existingRegistration?.workerId !== workerId) {
|
|
149
|
-
await this.stateManager
|
|
150
|
-
.getWorkerRegistrationIndexRepository(projectId, workerId)
|
|
151
|
-
.indexRepository.put(registration.id, SAME_KEY)
|
|
55
|
+
const eventsToPublish: { workerVersionId: string; event: WorkerUnitRegistrationEvent }[] = []
|
|
152
56
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
57
|
+
// query all registrations for the instance
|
|
58
|
+
const existingRegistrations = await tx.workerUnitRegistration.findMany({
|
|
59
|
+
where: { stateId },
|
|
60
|
+
select: { stateId: true, name: true, params: true, workerVersionId: true },
|
|
61
|
+
})
|
|
157
62
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
}
|
|
63
|
+
// the set of names we want to keep
|
|
64
|
+
const desiredNames = new Set(parsedWorkers.map(w => w.name))
|
|
162
65
|
|
|
163
|
-
|
|
164
|
-
|
|
66
|
+
for (const worker of parsedWorkers) {
|
|
67
|
+
const workerRecord = await this.ensureWorker(tx, worker.identity)
|
|
68
|
+
const workerVersionRecord = await this.ensureWorkerVersion(tx, workerRecord, worker.digest)
|
|
165
69
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (unitWorkers.some(unitWorker => unitWorker.name === name)) {
|
|
169
|
-
continue
|
|
170
|
-
}
|
|
70
|
+
const existing = existingRegistrations.find(r => r.name === worker.name)
|
|
71
|
+
const stringifiedParams = JSON.stringify(worker.params)
|
|
171
72
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
73
|
+
// create a new registration if it doesn't exist
|
|
74
|
+
if (!existing) {
|
|
75
|
+
await tx.workerUnitRegistration.create({
|
|
76
|
+
data: {
|
|
77
|
+
stateId,
|
|
78
|
+
name: worker.name,
|
|
79
|
+
params: worker.params,
|
|
80
|
+
workerVersionId: workerVersionRecord.id,
|
|
178
81
|
},
|
|
179
|
-
|
|
180
|
-
existingRegistration.id,
|
|
181
|
-
name,
|
|
182
|
-
projectId,
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
await this.stateManager
|
|
186
|
-
.getWorkerRegistrationRepository(projectId)
|
|
187
|
-
.delete(existingRegistration.id, batch)
|
|
188
|
-
|
|
189
|
-
await this.stateManager
|
|
190
|
-
.getWorkerRegistrationIndexRepository(projectId, existingRegistration.workerId)
|
|
191
|
-
.indexRepository.delete(existingRegistration.id)
|
|
192
|
-
|
|
193
|
-
// ensure the worker is deleted if it has no registrations left
|
|
194
|
-
await this.deleteWorkerIfHasNoRegistrations(projectId, existingRegistration.workerId)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
await batch.write()
|
|
82
|
+
})
|
|
198
83
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
84
|
+
eventsToPublish.push({
|
|
85
|
+
workerVersionId: workerVersionRecord.id,
|
|
86
|
+
event: { type: "registered", instanceId: stateId, params: worker.params },
|
|
87
|
+
})
|
|
202
88
|
|
|
203
|
-
|
|
204
|
-
const identity = getWorkerIdentity(unitWorker.image)
|
|
205
|
-
|
|
206
|
-
return await this.lockManager.acquire(["worker-image", projectId, identity], async () => {
|
|
207
|
-
// it is not critical to fetch all workers since their count is not expected to be high
|
|
208
|
-
const workers = await this.stateManager.getWorkerRepository(projectId).getAllItems()
|
|
209
|
-
|
|
210
|
-
const existingWorker = workers.find(worker => worker.image === unitWorker.image)
|
|
211
|
-
if (existingWorker) {
|
|
212
|
-
this.logger.debug(
|
|
213
|
-
{ projectId, workerId: existingWorker.id, image: unitWorker.image },
|
|
214
|
-
`worker with image "%s" already exists, reusing it`,
|
|
215
|
-
unitWorker.image,
|
|
216
|
-
)
|
|
217
|
-
return existingWorker.id
|
|
89
|
+
continue
|
|
218
90
|
}
|
|
219
91
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
`creating new worker for image "%s" with identity "%s" in project "%s"`,
|
|
223
|
-
unitWorker.image,
|
|
224
|
-
identity,
|
|
225
|
-
projectId,
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
let serviceAccountId: string | undefined
|
|
92
|
+
const paramsChanged = JSON.stringify(existing.params) !== stringifiedParams
|
|
93
|
+
const versionChanged = existing.workerVersionId !== workerVersionRecord.id
|
|
229
94
|
|
|
230
|
-
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
95
|
+
// update existing registration if params or version changed
|
|
96
|
+
if (paramsChanged || versionChanged) {
|
|
97
|
+
await tx.workerUnitRegistration.update({
|
|
98
|
+
where: { stateId_name: { stateId, name: worker.name } },
|
|
99
|
+
data: {
|
|
100
|
+
params: worker.params,
|
|
101
|
+
workerVersionId: workerVersionRecord.id,
|
|
102
|
+
},
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// deregister from old worker version if it changed
|
|
106
|
+
if (versionChanged) {
|
|
107
|
+
eventsToPublish.push({
|
|
108
|
+
workerVersionId: existing.workerVersionId,
|
|
109
|
+
event: { type: "deregistered", instanceId: stateId },
|
|
110
|
+
})
|
|
111
|
+
}
|
|
236
112
|
|
|
237
|
-
|
|
113
|
+
eventsToPublish.push({
|
|
114
|
+
workerVersionId: workerVersionRecord.id,
|
|
115
|
+
event: { type: "registered", instanceId: stateId, params: worker.params },
|
|
116
|
+
})
|
|
238
117
|
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// remove registrations that are no longer desired
|
|
121
|
+
for (const registration of existingRegistrations) {
|
|
122
|
+
if (!desiredNames.has(registration.name)) {
|
|
123
|
+
await tx.workerUnitRegistration.delete({
|
|
124
|
+
where: { stateId_name: { stateId, name: registration.name } },
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
eventsToPublish.push({
|
|
128
|
+
workerVersionId: registration.workerVersionId,
|
|
129
|
+
event: { type: "deregistered", instanceId: stateId },
|
|
130
|
+
})
|
|
131
|
+
}
|
|
132
|
+
}
|
|
239
133
|
|
|
240
|
-
|
|
134
|
+
await this.cleanupUnusedWorkerVersions(tx)
|
|
241
135
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
136
|
+
// publish events after transaction commits
|
|
137
|
+
for (const { workerVersionId, event } of eventsToPublish) {
|
|
138
|
+
void this.pubsubManager.publish(
|
|
139
|
+
["worker-unit-registration", projectId, workerVersionId],
|
|
140
|
+
event,
|
|
141
|
+
)
|
|
142
|
+
}
|
|
249
143
|
|
|
250
|
-
|
|
144
|
+
// ensure all worker versions are started
|
|
145
|
+
void this.workerManager.syncWorkers(projectId)
|
|
251
146
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
`creating service account "%s" for worker identity "%s" in project "%s"`,
|
|
255
|
-
serviceAccountId,
|
|
256
|
-
identity,
|
|
257
|
-
projectId,
|
|
258
|
-
)
|
|
147
|
+
logger.info(`updated worker registrations for instance state "%s"`, stateId)
|
|
148
|
+
}
|
|
259
149
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
150
|
+
private async ensureWorker(tx: ProjectTransaction, identity: string): Promise<Worker> {
|
|
151
|
+
const existing = await tx.worker.findUnique({ where: { identity } })
|
|
152
|
+
if (existing) {
|
|
153
|
+
return existing
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// create a new service account for the worker
|
|
157
|
+
const serviceAccount = await tx.serviceAccount.create({
|
|
158
|
+
select: { id: true },
|
|
159
|
+
data: {
|
|
160
|
+
meta: {
|
|
161
|
+
// this generic meta should be replaced by the worker when it starts
|
|
162
|
+
title: "Worker Service Account",
|
|
163
|
+
description: `Automatically created for worker "${identity}".`,
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
})
|
|
264
167
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
actions: ["full"],
|
|
273
|
-
serviceAccountIds: [serviceAccountId],
|
|
274
|
-
},
|
|
275
|
-
],
|
|
276
|
-
}
|
|
168
|
+
return await tx.worker.create({
|
|
169
|
+
data: {
|
|
170
|
+
identity,
|
|
171
|
+
serviceAccountId: serviceAccount.id,
|
|
172
|
+
},
|
|
173
|
+
})
|
|
174
|
+
}
|
|
277
175
|
|
|
278
|
-
|
|
176
|
+
private async ensureWorkerVersion(
|
|
177
|
+
tx: ProjectTransaction,
|
|
178
|
+
worker: Worker,
|
|
179
|
+
digest: string,
|
|
180
|
+
): Promise<WorkerVersion> {
|
|
181
|
+
const existing = await tx.workerVersion.findUnique({ where: { digest } })
|
|
182
|
+
if (existing) {
|
|
183
|
+
return existing
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// create an API key for the worker granting full access to its service account
|
|
187
|
+
const apiKey = await tx.apiKey.create({
|
|
188
|
+
data: {
|
|
189
|
+
meta: {
|
|
190
|
+
title: `Worker API Key for "${worker.identity}"`,
|
|
191
|
+
description: `Automatically created for worker "${worker.identity}" with digest "${digest}".`,
|
|
192
|
+
},
|
|
193
|
+
serviceAccountId: worker.serviceAccountId,
|
|
194
|
+
token: randomBytes(32).toString("hex"),
|
|
195
|
+
},
|
|
196
|
+
})
|
|
279
197
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
198
|
+
return await tx.workerVersion.create({
|
|
199
|
+
data: {
|
|
200
|
+
workerId: worker.id,
|
|
201
|
+
digest,
|
|
202
|
+
meta: {
|
|
203
|
+
title: "Worker Version",
|
|
204
|
+
description: `Worker version with digest ${digest}`,
|
|
205
|
+
},
|
|
288
206
|
apiKeyId: apiKey.id,
|
|
289
|
-
}
|
|
207
|
+
},
|
|
208
|
+
})
|
|
209
|
+
}
|
|
290
210
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
211
|
+
/**
|
|
212
|
+
* Performs cleanup of unused worker versions and syncs workers for a project.
|
|
213
|
+
* This method should be called after operations that may leave unused workers.
|
|
214
|
+
*
|
|
215
|
+
* @param projectId The ID of the project to cleanup and sync workers for.
|
|
216
|
+
*/
|
|
217
|
+
async cleanupWorkerUsageAndSync(projectId: string): Promise<void> {
|
|
218
|
+
const database = await this.database.forProject(projectId)
|
|
219
|
+
|
|
220
|
+
await database.$transaction(async tx => {
|
|
221
|
+
await this.cleanupUnusedWorkerVersions(tx)
|
|
222
|
+
})
|
|
298
223
|
|
|
299
|
-
|
|
300
|
-
|
|
224
|
+
// ensure all worker versions are started
|
|
225
|
+
void this.workerManager.syncWorkers(projectId)
|
|
226
|
+
}
|
|
301
227
|
|
|
302
|
-
|
|
228
|
+
private async cleanupUnusedWorkerVersions(tx: ProjectTransaction): Promise<void> {
|
|
229
|
+
const unused = await tx.workerVersion.findMany({
|
|
230
|
+
where: {
|
|
231
|
+
unitRegistrations: { none: {} },
|
|
232
|
+
},
|
|
233
|
+
select: { id: true },
|
|
234
|
+
})
|
|
303
235
|
|
|
304
|
-
|
|
236
|
+
if (unused.length === 0) {
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await tx.workerVersion.deleteMany({
|
|
241
|
+
where: { id: { in: unused.map(u => u.id) } },
|
|
305
242
|
})
|
|
306
243
|
}
|
|
307
244
|
|
|
308
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Updates the metadata for a worker version.
|
|
247
|
+
*
|
|
248
|
+
* @param projectId The ID of the project.
|
|
249
|
+
* @param workerVersionId The ID of the worker version to update.
|
|
250
|
+
* @param meta The new metadata to set.
|
|
251
|
+
*/
|
|
252
|
+
async updateWorkerVersionMeta(
|
|
309
253
|
projectId: string,
|
|
310
|
-
|
|
254
|
+
workerVersionId: string,
|
|
255
|
+
meta: CommonObjectMeta,
|
|
311
256
|
): Promise<void> {
|
|
312
|
-
await this.
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
registrations.length,
|
|
324
|
-
)
|
|
325
|
-
return
|
|
257
|
+
const database = await this.database.forProject(projectId)
|
|
258
|
+
const logger = createProjectLogger(this.logger, projectId)
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
await database.workerVersion.update({
|
|
262
|
+
where: { id: workerVersionId },
|
|
263
|
+
data: { meta },
|
|
264
|
+
})
|
|
265
|
+
} catch (error) {
|
|
266
|
+
if (error instanceof PrismaClientKnownRequestError && error.code === "P2025") {
|
|
267
|
+
throw new WorkerVersionNotFoundError(projectId, workerVersionId)
|
|
326
268
|
}
|
|
327
269
|
|
|
328
|
-
|
|
270
|
+
throw error
|
|
271
|
+
}
|
|
329
272
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
{ projectId, workerId },
|
|
333
|
-
`worker "%s" not found in project "%s" while deleting`,
|
|
334
|
-
workerId,
|
|
335
|
-
projectId,
|
|
336
|
-
)
|
|
337
|
-
return
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const batch = this.stateManager.batch()
|
|
341
|
-
|
|
342
|
-
this.logger.info(
|
|
343
|
-
{ projectId, workerId, image: worker.image, identity: worker.identity },
|
|
344
|
-
`deleting worker "%s" with image "%s" in project "%s" (no registrations remaining)`,
|
|
345
|
-
workerId,
|
|
346
|
-
worker.image,
|
|
347
|
-
projectId,
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
await this.stateManager.getWorkerRepository(projectId).delete(workerId, batch)
|
|
351
|
-
await this.stateManager.getApiKeyRepository(projectId).delete(worker.apiKeyId, batch)
|
|
352
|
-
|
|
353
|
-
const workers = await this.stateManager.getWorkerRepository(projectId).getAllItems()
|
|
354
|
-
const hasSiblingWorker = workers.some(
|
|
355
|
-
siblingWorker =>
|
|
356
|
-
siblingWorker.identity === worker.identity && siblingWorker.id !== workerId,
|
|
357
|
-
)
|
|
358
|
-
|
|
359
|
-
if (!hasSiblingWorker) {
|
|
360
|
-
this.logger.info(
|
|
361
|
-
{
|
|
362
|
-
projectId,
|
|
363
|
-
workerId,
|
|
364
|
-
serviceAccountId: worker.serviceAccountId,
|
|
365
|
-
identity: worker.identity,
|
|
366
|
-
},
|
|
367
|
-
`deleting service account "%s" for worker "%s" in project "%s" (no sibling workers remaining)`,
|
|
368
|
-
worker.serviceAccountId,
|
|
369
|
-
workerId,
|
|
370
|
-
projectId,
|
|
371
|
-
)
|
|
372
|
-
|
|
373
|
-
await this.stateManager
|
|
374
|
-
.getServiceAccountRepository(projectId)
|
|
375
|
-
.delete(worker.serviceAccountId, batch)
|
|
376
|
-
} else {
|
|
377
|
-
this.logger.debug(
|
|
378
|
-
{
|
|
379
|
-
projectId,
|
|
380
|
-
workerId,
|
|
381
|
-
serviceAccountId: worker.serviceAccountId,
|
|
382
|
-
identity: worker.identity,
|
|
383
|
-
},
|
|
384
|
-
`not deleting service account "%s" for worker "%s" in project "%s" (has sibling workers)`,
|
|
385
|
-
worker.serviceAccountId,
|
|
386
|
-
workerId,
|
|
387
|
-
projectId,
|
|
388
|
-
)
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// for now, we will keep the service account even if the last sibling worker is deleted
|
|
392
|
-
await batch.write()
|
|
273
|
+
logger.info(`updated worker version metadata for "%s"`, workerVersionId)
|
|
274
|
+
}
|
|
393
275
|
|
|
394
|
-
|
|
395
|
-
|
|
276
|
+
/**
|
|
277
|
+
* Gets logs for a worker version.
|
|
278
|
+
*
|
|
279
|
+
* @param projectId The ID of the project.
|
|
280
|
+
* @param workerVersionId The ID of the worker version to get logs for.
|
|
281
|
+
*/
|
|
282
|
+
async getWorkerVersionLogs(
|
|
283
|
+
projectId: string,
|
|
284
|
+
workerVersionId: string,
|
|
285
|
+
): Promise<WorkerVersionLog[]> {
|
|
286
|
+
const database = await this.database.forProject(projectId)
|
|
287
|
+
|
|
288
|
+
return await database.workerVersionLog.findMany({
|
|
289
|
+
where: {
|
|
290
|
+
workerVersionId,
|
|
291
|
+
},
|
|
292
|
+
orderBy: {
|
|
293
|
+
id: "asc",
|
|
294
|
+
},
|
|
396
295
|
})
|
|
397
296
|
}
|
|
398
297
|
}
|