@shipfox/api-runners 12.3.0 → 12.4.1
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/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +36 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +9 -2
- package/dist/config.js.map +1 -1
- package/dist/core/demand.d.ts +4 -2
- package/dist/core/demand.d.ts.map +1 -1
- package/dist/core/demand.js +22 -6
- package/dist/core/demand.js.map +1 -1
- package/dist/core/entities/reservation.d.ts +1 -0
- package/dist/core/entities/reservation.d.ts.map +1 -1
- package/dist/core/entities/reservation.js.map +1 -1
- package/dist/core/entities/runner-instance.d.ts +3 -0
- package/dist/core/entities/runner-instance.d.ts.map +1 -1
- package/dist/core/entities/runner-instance.js.map +1 -1
- package/dist/core/errors.d.ts +5 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +9 -2
- package/dist/core/errors.js.map +1 -1
- package/dist/core/runner-activation.d.ts +4 -1
- package/dist/core/runner-activation.d.ts.map +1 -1
- package/dist/core/runner-activation.js +32 -3
- package/dist/core/runner-activation.js.map +1 -1
- package/dist/core/runner-control-sessions.d.ts +8 -4
- package/dist/core/runner-control-sessions.d.ts.map +1 -1
- package/dist/core/runner-control-sessions.js +116 -20
- package/dist/core/runner-control-sessions.js.map +1 -1
- package/dist/core/runner-instances.d.ts +1 -0
- package/dist/core/runner-instances.d.ts.map +1 -1
- package/dist/core/runner-instances.js +1 -0
- package/dist/core/runner-instances.js.map +1 -1
- package/dist/db/db.d.ts +68 -0
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/ephemeral-registration-tokens.d.ts.map +1 -1
- package/dist/db/ephemeral-registration-tokens.js +1 -1
- package/dist/db/ephemeral-registration-tokens.js.map +1 -1
- package/dist/db/job-executions.d.ts.map +1 -1
- package/dist/db/job-executions.js +35 -4
- package/dist/db/job-executions.js.map +1 -1
- package/dist/db/reservation-locks.d.ts +6 -0
- package/dist/db/reservation-locks.d.ts.map +1 -0
- package/dist/db/reservation-locks.js +15 -0
- package/dist/db/reservation-locks.js.map +1 -0
- package/dist/db/reservations.d.ts +17 -3
- package/dist/db/reservations.d.ts.map +1 -1
- package/dist/db/reservations.js +246 -51
- package/dist/db/reservations.js.map +1 -1
- package/dist/db/runner-assignments.d.ts +25 -1
- package/dist/db/runner-assignments.d.ts.map +1 -1
- package/dist/db/runner-assignments.js +160 -18
- package/dist/db/runner-assignments.js.map +1 -1
- package/dist/db/runner-instances.d.ts +11 -2
- package/dist/db/runner-instances.d.ts.map +1 -1
- package/dist/db/runner-instances.js +167 -24
- package/dist/db/runner-instances.js.map +1 -1
- package/dist/db/runner-sessions.d.ts.map +1 -1
- package/dist/db/runner-sessions.js +14 -1
- package/dist/db/runner-sessions.js.map +1 -1
- package/dist/db/runner-states.d.ts +2 -0
- package/dist/db/runner-states.d.ts.map +1 -0
- package/dist/db/runner-states.js +7 -0
- package/dist/db/runner-states.js.map +1 -0
- package/dist/db/schema/reservations.d.ts +18 -0
- package/dist/db/schema/reservations.d.ts.map +1 -1
- package/dist/db/schema/reservations.js +7 -1
- package/dist/db/schema/reservations.js.map +1 -1
- package/dist/db/schema/runner-instances.d.ts +18 -0
- package/dist/db/schema/runner-instances.d.ts.map +1 -1
- package/dist/db/schema/runner-instances.js +8 -0
- package/dist/db/schema/runner-instances.js.map +1 -1
- package/dist/metrics/index.d.ts +2 -2
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +1 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/instance.d.ts +72 -2
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +161 -1
- package/dist/metrics/instance.js.map +1 -1
- package/dist/metrics/service.d.ts.map +1 -1
- package/dist/metrics/service.js +25 -4
- package/dist/metrics/service.js.map +1 -1
- package/dist/presentation/dto/poll-demand.d.ts.map +1 -1
- package/dist/presentation/dto/poll-demand.js +3 -0
- package/dist/presentation/dto/poll-demand.js.map +1 -1
- package/dist/presentation/dto/runner-instances.d.ts +4 -1
- package/dist/presentation/dto/runner-instances.d.ts.map +1 -1
- package/dist/presentation/dto/runner-instances.js +4 -1
- package/dist/presentation/dto/runner-instances.js.map +1 -1
- package/dist/presentation/routes/assign-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/assign-runner-instances.js +10 -4
- package/dist/presentation/routes/assign-runner-instances.js.map +1 -1
- package/dist/presentation/routes/poll-demand.d.ts.map +1 -1
- package/dist/presentation/routes/poll-demand.js +1 -0
- package/dist/presentation/routes/poll-demand.js.map +1 -1
- package/dist/presentation/routes/reconcile-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/reconcile-runner-instances.js +4 -2
- package/dist/presentation/routes/reconcile-runner-instances.js.map +1 -1
- package/dist/presentation/routes/runner-enrollment.d.ts +4 -1
- package/dist/presentation/routes/runner-enrollment.d.ts.map +1 -1
- package/dist/presentation/routes/runner-enrollment.js +11 -6
- package/dist/presentation/routes/runner-enrollment.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0005_previous_lenny_balinger.sql +5 -0
- package/drizzle/meta/0005_snapshot.json +2220 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +6 -6
- package/src/config.test.ts +22 -0
- package/src/config.ts +15 -2
- package/src/core/demand.test.ts +192 -3
- package/src/core/demand.ts +44 -4
- package/src/core/entities/reservation.ts +1 -0
- package/src/core/entities/runner-instance.ts +4 -0
- package/src/core/errors.ts +30 -1
- package/src/core/runner-activation.ts +48 -2
- package/src/core/runner-control-sessions.test.ts +135 -3
- package/src/core/runner-control-sessions.ts +141 -19
- package/src/core/runner-instances.test.ts +19 -0
- package/src/core/runner-instances.ts +2 -0
- package/src/core/runner-sessions.test.ts +121 -1
- package/src/db/ephemeral-registration-tokens.test.ts +20 -1
- package/src/db/ephemeral-registration-tokens.ts +1 -0
- package/src/db/job-executions.test.ts +98 -12
- package/src/db/job-executions.ts +52 -4
- package/src/db/reservation-locks.ts +22 -0
- package/src/db/reservations.test.ts +733 -22
- package/src/db/reservations.ts +408 -144
- package/src/db/runner-assignments.test.ts +105 -1
- package/src/db/runner-assignments.ts +245 -25
- package/src/db/runner-instances.test.ts +357 -2
- package/src/db/runner-instances.ts +289 -55
- package/src/db/runner-sessions.ts +19 -1
- package/src/db/runner-states.ts +7 -0
- package/src/db/schema/reservations.ts +5 -1
- package/src/db/schema/runner-instances.ts +9 -0
- package/src/metrics/index.ts +24 -1
- package/src/metrics/instance.test.ts +118 -0
- package/src/metrics/instance.ts +247 -3
- package/src/metrics/service.test.ts +46 -1
- package/src/metrics/service.ts +55 -8
- package/src/presentation/dto/poll-demand.ts +3 -0
- package/src/presentation/dto/runner-instances.ts +8 -1
- package/src/presentation/routes/assign-runner-instances.ts +14 -2
- package/src/presentation/routes/late-runner-enrollment.test.ts +219 -2
- package/src/presentation/routes/poll-demand.test.ts +56 -0
- package/src/presentation/routes/poll-demand.ts +1 -0
- package/src/presentation/routes/reconcile-runner-instances.test.ts +34 -2
- package/src/presentation/routes/reconcile-runner-instances.ts +7 -1
- package/src/presentation/routes/runner-enrollment.test.ts +316 -3
- package/src/presentation/routes/runner-enrollment.ts +8 -5
- package/test/factories/reservation.ts +2 -0
- package/test/factories/runner-instance.ts +6 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["export class RunningJobExecutionNotFoundError extends Error {\n constructor(jobExecutionId: string) {\n super(`Running job execution not found: ${jobExecutionId}`);\n this.name = 'RunningJobExecutionNotFoundError';\n }\n}\n\nexport class ManualRegistrationTokenNotFoundError extends Error {\n constructor(tokenId: string) {\n super(`Manual registration token not found: ${tokenId}`);\n this.name = 'ManualRegistrationTokenNotFoundError';\n }\n}\n\nexport class ProvisionerTokenNotFoundError extends Error {\n constructor(tokenId: string) {\n super(`Provisioner token not found: ${tokenId}`);\n this.name = 'ProvisionerTokenNotFoundError';\n }\n}\n\nexport class ProvisionerAdminIdempotencyKeyReuseError extends Error {\n constructor() {\n super('Idempotency-Key was already used for a different provisioner token command');\n this.name = 'ProvisionerAdminIdempotencyKeyReuseError';\n }\n}\n\nexport class ProvisionerAdminIdempotencyReplayUnavailableError extends Error {\n constructor() {\n super('Idempotency-Key replay cannot reproduce the original provisioner token');\n this.name = 'ProvisionerAdminIdempotencyReplayUnavailableError';\n }\n}\n\nexport class EmptyRunnerLabelsError extends Error {\n constructor() {\n super('Runner labels cannot be empty');\n this.name = 'EmptyRunnerLabelsError';\n }\n}\n\nexport class RunnerLabelsReservedError extends Error {\n constructor(public readonly labels: string[]) {\n super(\n `All supplied runner labels are reserved for installation-scope provisioners: ${labels.join(', ')}`,\n );\n this.name = 'RunnerLabelsReservedError';\n }\n}\n\nexport class EmptyRequiredLabelsError extends Error {\n constructor() {\n super('Required labels cannot be empty');\n this.name = 'EmptyRequiredLabelsError';\n }\n}\n\nexport class RegistrationTokenConsumedError extends Error {\n constructor(public readonly ephemeralTokenId: string) {\n super(`Ephemeral registration token has already been consumed: ${ephemeralTokenId}`);\n this.name = 'RegistrationTokenConsumedError';\n }\n}\n\nexport class RegistrationTokenExpiredError extends Error {\n constructor(public readonly ephemeralTokenId: string) {\n super(`Ephemeral registration token has expired: ${ephemeralTokenId}`);\n this.name = 'RegistrationTokenExpiredError';\n }\n}\n\nexport class RegistrationTokenWorkspaceMismatchError extends Error {\n constructor(\n public readonly ephemeralTokenId: string,\n public readonly workspaceId: string,\n ) {\n super(\n `Ephemeral registration token ${ephemeralTokenId} does not belong to workspace ${workspaceId}`,\n );\n this.name = 'RegistrationTokenWorkspaceMismatchError';\n }\n}\n\nexport class ActiveEphemeralRegistrationTokenExistsError extends Error {\n constructor(\n public readonly workspaceId: string,\n public readonly provisionerId: string,\n public readonly providerRunnerId: string,\n ) {\n super(\n `Active ephemeral registration token already exists for provisioned runner ${providerRunnerId} in workspace ${workspaceId}`,\n );\n this.name = 'ActiveEphemeralRegistrationTokenExistsError';\n }\n}\n\nexport class ReservationNotFoundError extends Error {\n constructor(public readonly reservationId: string) {\n super(`Reservation not found: ${reservationId}`);\n this.name = 'ReservationNotFoundError';\n }\n}\n\nexport class ReservationExpiredError extends Error {\n constructor(public readonly reservationId: string) {\n super(`Reservation has expired: ${reservationId}`);\n this.name = 'ReservationExpiredError';\n }\n}\n\nexport class RunnerInstanceNotAssignableError extends Error {\n constructor(public readonly runnerInstanceId: string) {\n super(`Runner instance cannot be assigned: ${runnerInstanceId}`);\n this.name = 'RunnerInstanceNotAssignableError';\n }\n}\nexport class RunnerInstanceAlreadyAssignedError extends Error {\n constructor(public readonly runnerInstanceId: string) {\n super(`Runner instance is already assigned: ${runnerInstanceId}`);\n this.name = 'RunnerInstanceAlreadyAssignedError';\n }\n}\nexport class ReservationAlreadyAssignedError extends Error {\n constructor(public readonly reservationId: string) {\n super(`Reservation is already assigned: ${reservationId}`);\n this.name = 'ReservationAlreadyAssignedError';\n }\n}\n\nexport class RegistrationTokenBatchTooLargeError extends Error {\n constructor(\n public readonly requested: number,\n public readonly max: number,\n ) {\n super(\n `Registration token batch requested ${requested} provisioned runners, exceeding max ${max}`,\n );\n this.name = 'RegistrationTokenBatchTooLargeError';\n }\n}\n\nexport class RegistrationTokenBatchExceedsReservationError extends Error {\n constructor(\n public readonly requested: number,\n public readonly reservationCount: number,\n public readonly alreadyMinted: number = 0,\n ) {\n super(\n `Registration token batch requested ${requested} provisioned runners with ${alreadyMinted} already minted, exceeding reservation count ${reservationCount}`,\n );\n this.name = 'RegistrationTokenBatchExceedsReservationError';\n }\n}\n\nexport class ActiveEphemeralRegistrationTokensExistError extends Error {\n constructor(public readonly providerRunnerIds: string[]) {\n super(\n `Active ephemeral registration tokens already exist for provisioned runners: ${providerRunnerIds.join(', ')}`,\n );\n this.name = 'ActiveEphemeralRegistrationTokensExistError';\n }\n}\n\nexport class RunnerSessionExhaustedError extends Error {\n constructor(public readonly runnerSessionId: string) {\n super(`Runner session claim limit exhausted: ${runnerSessionId}`);\n this.name = 'RunnerSessionExhaustedError';\n }\n}\n"],"names":["RunningJobExecutionNotFoundError","Error","jobExecutionId","name","ManualRegistrationTokenNotFoundError","tokenId","ProvisionerTokenNotFoundError","ProvisionerAdminIdempotencyKeyReuseError","ProvisionerAdminIdempotencyReplayUnavailableError","EmptyRunnerLabelsError","RunnerLabelsReservedError","labels","join","EmptyRequiredLabelsError","RegistrationTokenConsumedError","ephemeralTokenId","RegistrationTokenExpiredError","RegistrationTokenWorkspaceMismatchError","workspaceId","ActiveEphemeralRegistrationTokenExistsError","provisionerId","providerRunnerId","ReservationNotFoundError","reservationId","ReservationExpiredError","RunnerInstanceNotAssignableError","runnerInstanceId","RunnerInstanceAlreadyAssignedError","ReservationAlreadyAssignedError","RegistrationTokenBatchTooLargeError","requested","max","RegistrationTokenBatchExceedsReservationError","reservationCount","alreadyMinted","ActiveEphemeralRegistrationTokensExistError","providerRunnerIds","RunnerSessionExhaustedError","runnerSessionId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["export class RunningJobExecutionNotFoundError extends Error {\n constructor(jobExecutionId: string) {\n super(`Running job execution not found: ${jobExecutionId}`);\n this.name = 'RunningJobExecutionNotFoundError';\n }\n}\n\nexport class ManualRegistrationTokenNotFoundError extends Error {\n constructor(tokenId: string) {\n super(`Manual registration token not found: ${tokenId}`);\n this.name = 'ManualRegistrationTokenNotFoundError';\n }\n}\n\nexport class ProvisionerTokenNotFoundError extends Error {\n constructor(tokenId: string) {\n super(`Provisioner token not found: ${tokenId}`);\n this.name = 'ProvisionerTokenNotFoundError';\n }\n}\n\nexport class ProvisionerAdminIdempotencyKeyReuseError extends Error {\n constructor() {\n super('Idempotency-Key was already used for a different provisioner token command');\n this.name = 'ProvisionerAdminIdempotencyKeyReuseError';\n }\n}\n\nexport class ProvisionerAdminIdempotencyReplayUnavailableError extends Error {\n constructor() {\n super('Idempotency-Key replay cannot reproduce the original provisioner token');\n this.name = 'ProvisionerAdminIdempotencyReplayUnavailableError';\n }\n}\n\nexport class EmptyRunnerLabelsError extends Error {\n constructor() {\n super('Runner labels cannot be empty');\n this.name = 'EmptyRunnerLabelsError';\n }\n}\n\nexport class RunnerLabelsReservedError extends Error {\n constructor(public readonly labels: string[]) {\n super(\n `All supplied runner labels are reserved for installation-scope provisioners: ${labels.join(', ')}`,\n );\n this.name = 'RunnerLabelsReservedError';\n }\n}\n\nexport class EmptyRequiredLabelsError extends Error {\n constructor() {\n super('Required labels cannot be empty');\n this.name = 'EmptyRequiredLabelsError';\n }\n}\n\nexport class RegistrationTokenConsumedError extends Error {\n constructor(public readonly ephemeralTokenId: string) {\n super(`Ephemeral registration token has already been consumed: ${ephemeralTokenId}`);\n this.name = 'RegistrationTokenConsumedError';\n }\n}\n\nexport class RegistrationTokenExpiredError extends Error {\n constructor(public readonly ephemeralTokenId: string) {\n super(`Ephemeral registration token has expired: ${ephemeralTokenId}`);\n this.name = 'RegistrationTokenExpiredError';\n }\n}\n\nexport class RegistrationTokenWorkspaceMismatchError extends Error {\n constructor(\n public readonly ephemeralTokenId: string,\n public readonly workspaceId: string,\n ) {\n super(\n `Ephemeral registration token ${ephemeralTokenId} does not belong to workspace ${workspaceId}`,\n );\n this.name = 'RegistrationTokenWorkspaceMismatchError';\n }\n}\n\nexport class ActiveEphemeralRegistrationTokenExistsError extends Error {\n constructor(\n public readonly workspaceId: string,\n public readonly provisionerId: string,\n public readonly providerRunnerId: string,\n ) {\n super(\n `Active ephemeral registration token already exists for provisioned runner ${providerRunnerId} in workspace ${workspaceId}`,\n );\n this.name = 'ActiveEphemeralRegistrationTokenExistsError';\n }\n}\n\nexport class ReservationNotFoundError extends Error {\n constructor(public readonly reservationId: string) {\n super(`Reservation not found: ${reservationId}`);\n this.name = 'ReservationNotFoundError';\n }\n}\n\nexport class ReservationExpiredError extends Error {\n constructor(public readonly reservationId: string) {\n super(`Reservation has expired: ${reservationId}`);\n this.name = 'ReservationExpiredError';\n }\n}\n\nexport type RunnerInstanceNotAssignableReason =\n | 'runner-not-found'\n | 'runner-not-running'\n | 'provider-identity-missing'\n | 'control-session-not-active'\n | 'labels-mismatch'\n | 'capacity-exhausted';\n\nexport type RunnerAssignmentRejectionReason =\n | 'reservation-not-found'\n | 'reservation-expired'\n | 'already-assigned'\n | RunnerInstanceNotAssignableReason;\n\nexport class RunnerInstanceNotAssignableError extends Error {\n constructor(\n public readonly runnerInstanceId: string,\n public readonly reason: RunnerInstanceNotAssignableReason,\n ) {\n super(`Runner instance cannot be assigned: ${runnerInstanceId}`);\n this.name = 'RunnerInstanceNotAssignableError';\n }\n}\n\nexport class RunnerInstanceAlreadyAssignedError extends Error {\n constructor(public readonly runnerInstanceId: string) {\n super(`Runner instance is already assigned: ${runnerInstanceId}`);\n this.name = 'RunnerInstanceAlreadyAssignedError';\n }\n}\n\nexport function getRunnerAssignmentRejectionReason(\n error: unknown,\n): RunnerAssignmentRejectionReason | null {\n if (error instanceof ReservationNotFoundError) return 'reservation-not-found';\n if (error instanceof ReservationExpiredError) return 'reservation-expired';\n if (error instanceof RunnerInstanceAlreadyAssignedError) return 'already-assigned';\n if (error instanceof RunnerInstanceNotAssignableError) return error.reason;\n return null;\n}\n\nexport class ReservationAlreadyAssignedError extends Error {\n constructor(public readonly reservationId: string) {\n super(`Reservation is already assigned: ${reservationId}`);\n this.name = 'ReservationAlreadyAssignedError';\n }\n}\n\nexport class RegistrationTokenBatchTooLargeError extends Error {\n constructor(\n public readonly requested: number,\n public readonly max: number,\n ) {\n super(\n `Registration token batch requested ${requested} provisioned runners, exceeding max ${max}`,\n );\n this.name = 'RegistrationTokenBatchTooLargeError';\n }\n}\n\nexport class RegistrationTokenBatchExceedsReservationError extends Error {\n constructor(\n public readonly requested: number,\n public readonly reservationCount: number,\n public readonly alreadyMinted: number = 0,\n ) {\n super(\n `Registration token batch requested ${requested} provisioned runners with ${alreadyMinted} already minted, exceeding reservation count ${reservationCount}`,\n );\n this.name = 'RegistrationTokenBatchExceedsReservationError';\n }\n}\n\nexport class ActiveEphemeralRegistrationTokensExistError extends Error {\n constructor(public readonly providerRunnerIds: string[]) {\n super(\n `Active ephemeral registration tokens already exist for provisioned runners: ${providerRunnerIds.join(', ')}`,\n );\n this.name = 'ActiveEphemeralRegistrationTokensExistError';\n }\n}\n\nexport class RunnerSessionExhaustedError extends Error {\n constructor(public readonly runnerSessionId: string) {\n super(`Runner session claim limit exhausted: ${runnerSessionId}`);\n this.name = 'RunnerSessionExhaustedError';\n }\n}\n"],"names":["RunningJobExecutionNotFoundError","Error","jobExecutionId","name","ManualRegistrationTokenNotFoundError","tokenId","ProvisionerTokenNotFoundError","ProvisionerAdminIdempotencyKeyReuseError","ProvisionerAdminIdempotencyReplayUnavailableError","EmptyRunnerLabelsError","RunnerLabelsReservedError","labels","join","EmptyRequiredLabelsError","RegistrationTokenConsumedError","ephemeralTokenId","RegistrationTokenExpiredError","RegistrationTokenWorkspaceMismatchError","workspaceId","ActiveEphemeralRegistrationTokenExistsError","provisionerId","providerRunnerId","ReservationNotFoundError","reservationId","ReservationExpiredError","RunnerInstanceNotAssignableError","runnerInstanceId","reason","RunnerInstanceAlreadyAssignedError","getRunnerAssignmentRejectionReason","error","ReservationAlreadyAssignedError","RegistrationTokenBatchTooLargeError","requested","max","RegistrationTokenBatchExceedsReservationError","reservationCount","alreadyMinted","ActiveEphemeralRegistrationTokensExistError","providerRunnerIds","RunnerSessionExhaustedError","runnerSessionId"],"mappings":"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"}
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import type { Tx } from '#db/db.js';
|
|
2
|
+
import { type RunnerActivationTokenNotIssuedSurface } from '#metrics/instance.js';
|
|
2
3
|
export declare function issueRunnerActivationToken(params: {
|
|
3
4
|
runnerInstanceId: string;
|
|
4
5
|
provisionerId: string;
|
|
5
6
|
ttlSeconds: number;
|
|
7
|
+
surface: RunnerActivationTokenNotIssuedSurface;
|
|
6
8
|
}): Promise<string | null>;
|
|
7
9
|
export declare function issueRunnerActivationTokenTx(tx: Tx, params: {
|
|
8
10
|
runnerInstanceId: string;
|
|
9
11
|
provisionerId: string;
|
|
10
12
|
ttlSeconds: number;
|
|
13
|
+
surface: RunnerActivationTokenNotIssuedSurface;
|
|
11
14
|
}): Promise<string | null>;
|
|
12
15
|
export declare function getRunnerAssignment(params: {
|
|
13
16
|
runnerInstanceId: string;
|
|
14
17
|
provisionerId: string;
|
|
15
18
|
}): Promise<{
|
|
16
|
-
workspaceId: string
|
|
19
|
+
workspaceId: string;
|
|
17
20
|
runnerSessionId: string | null;
|
|
18
21
|
} | null>;
|
|
19
22
|
//# sourceMappingURL=runner-activation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-activation.d.ts","sourceRoot":"","sources":["../../src/core/runner-activation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner-activation.d.ts","sourceRoot":"","sources":["../../src/core/runner-activation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,WAAW,CAAC;AAKlC,OAAO,EAEL,KAAK,qCAAqC,EAE3C,MAAM,sBAAsB,CAAC;AAE9B,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,qCAAqC,CAAC;CAChD,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAEzB;AAED,wBAAsB,4BAA4B,CAChD,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,qCAAqC,CAAC;CAChD,GACA,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA2CxB;AAED,wBAAsB,mBAAmB,CAAC,MAAM,EAAE;IAChD,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB;;;UAkBA"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
1
2
|
import { extractDisplayPrefix, generateOpaqueToken, hashOpaqueToken } from '@shipfox/node-tokens';
|
|
2
3
|
import { and, eq, isNull, sql } from 'drizzle-orm';
|
|
3
4
|
import { db } from '#db/db.js';
|
|
4
5
|
import { runnerActivationTokens } from '#db/schema/runner-activation-tokens.js';
|
|
5
6
|
import { providerRunners } from '#db/schema/runner-instances.js';
|
|
7
|
+
import { recordRunnerActivationTokenNotIssued } from '#metrics/instance.js';
|
|
6
8
|
export async function issueRunnerActivationToken(params) {
|
|
7
9
|
return await db().transaction(async (tx)=>issueRunnerActivationTokenTx(tx, params));
|
|
8
10
|
}
|
|
@@ -13,7 +15,11 @@ export async function issueRunnerActivationTokenTx(tx, params) {
|
|
|
13
15
|
runnerSessionId: providerRunners.runnerSessionId,
|
|
14
16
|
state: providerRunners.state
|
|
15
17
|
}).from(providerRunners).where(and(eq(providerRunners.id, params.runnerInstanceId), eq(providerRunners.provisionerId, params.provisionerId))).limit(1).for('update');
|
|
16
|
-
|
|
18
|
+
const notIssuedReason = getRunnerActivationTokenNotIssuedReason(runner);
|
|
19
|
+
if (notIssuedReason) {
|
|
20
|
+
recordRunnerActivationTokenNotIssuedWithLog(notIssuedReason, params);
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
17
23
|
await tx.update(runnerActivationTokens).set({
|
|
18
24
|
revokedAt: sql`now()`
|
|
19
25
|
}).where(and(eq(runnerActivationTokens.runnerInstanceId, params.runnerInstanceId), isNull(runnerActivationTokens.consumedAt), isNull(runnerActivationTokens.revokedAt)));
|
|
@@ -29,9 +35,32 @@ export async function issueRunnerActivationTokenTx(tx, params) {
|
|
|
29
35
|
export async function getRunnerAssignment(params) {
|
|
30
36
|
const [runner] = await db().select({
|
|
31
37
|
workspaceId: providerRunners.workspaceId,
|
|
32
|
-
runnerSessionId: providerRunners.runnerSessionId
|
|
38
|
+
runnerSessionId: providerRunners.runnerSessionId,
|
|
39
|
+
state: providerRunners.state
|
|
33
40
|
}).from(providerRunners).where(and(eq(providerRunners.id, params.runnerInstanceId), eq(providerRunners.provisionerId, params.provisionerId))).limit(1);
|
|
34
|
-
return runner?.workspaceId && !runner.runnerSessionId
|
|
41
|
+
return runner?.workspaceId && !runner.runnerSessionId && runner.state === 'running' ? {
|
|
42
|
+
workspaceId: runner.workspaceId,
|
|
43
|
+
runnerSessionId: runner.runnerSessionId
|
|
44
|
+
} : null;
|
|
45
|
+
}
|
|
46
|
+
function getRunnerActivationTokenNotIssuedReason(runner) {
|
|
47
|
+
if (!runner) return 'runner-not-found';
|
|
48
|
+
if (!runner.workspaceId) return 'missing-workspace';
|
|
49
|
+
if (runner.runnerSessionId) return 'existing-session';
|
|
50
|
+
if (runner.state !== 'running') return 'not-running';
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
function recordRunnerActivationTokenNotIssuedWithLog(reason, params) {
|
|
54
|
+
recordRunnerActivationTokenNotIssued({
|
|
55
|
+
reason,
|
|
56
|
+
surface: params.surface
|
|
57
|
+
});
|
|
58
|
+
logger().debug({
|
|
59
|
+
runnerInstanceId: params.runnerInstanceId,
|
|
60
|
+
provisionerId: params.provisionerId,
|
|
61
|
+
reason,
|
|
62
|
+
surface: params.surface
|
|
63
|
+
}, 'Runner activation token was not issued');
|
|
35
64
|
}
|
|
36
65
|
|
|
37
66
|
//# sourceMappingURL=runner-activation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/runner-activation.ts"],"sourcesContent":["import {extractDisplayPrefix, generateOpaqueToken, hashOpaqueToken} from '@shipfox/node-tokens';\nimport {and, eq, isNull, sql} from 'drizzle-orm';\nimport type {Tx} from '#db/db.js';\nimport {db} from '#db/db.js';\nimport {runnerActivationTokens} from '#db/schema/runner-activation-tokens.js';\nimport {providerRunners} from '#db/schema/runner-instances.js';\n\nexport async function issueRunnerActivationToken(params: {\n runnerInstanceId: string;\n provisionerId: string;\n ttlSeconds: number;\n}): Promise<string | null> {\n return await db().transaction(async (tx) => issueRunnerActivationTokenTx(tx, params));\n}\n\nexport async function issueRunnerActivationTokenTx(\n tx: Tx,\n params: {\n runnerInstanceId: string;\n provisionerId: string;\n ttlSeconds: number;\n },\n): Promise<string | null> {\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${`runners_activation:${params.runnerInstanceId}`}))`,\n );\n const [runner] = await tx\n .select({\n workspaceId: providerRunners.workspaceId,\n runnerSessionId: providerRunners.runnerSessionId,\n state: providerRunners.state,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n ),\n )\n .limit(1)\n .for('update');\n
|
|
1
|
+
{"version":3,"sources":["../../src/core/runner-activation.ts"],"sourcesContent":["import {logger} from '@shipfox/node-opentelemetry';\nimport {extractDisplayPrefix, generateOpaqueToken, hashOpaqueToken} from '@shipfox/node-tokens';\nimport {and, eq, isNull, sql} from 'drizzle-orm';\nimport type {Tx} from '#db/db.js';\nimport {db} from '#db/db.js';\nimport {runnerActivationTokens} from '#db/schema/runner-activation-tokens.js';\nimport type {RunnerInstanceDb} from '#db/schema/runner-instances.js';\nimport {providerRunners} from '#db/schema/runner-instances.js';\nimport {\n type RunnerActivationTokenNotIssuedReason,\n type RunnerActivationTokenNotIssuedSurface,\n recordRunnerActivationTokenNotIssued,\n} from '#metrics/instance.js';\n\nexport async function issueRunnerActivationToken(params: {\n runnerInstanceId: string;\n provisionerId: string;\n ttlSeconds: number;\n surface: RunnerActivationTokenNotIssuedSurface;\n}): Promise<string | null> {\n return await db().transaction(async (tx) => issueRunnerActivationTokenTx(tx, params));\n}\n\nexport async function issueRunnerActivationTokenTx(\n tx: Tx,\n params: {\n runnerInstanceId: string;\n provisionerId: string;\n ttlSeconds: number;\n surface: RunnerActivationTokenNotIssuedSurface;\n },\n): Promise<string | null> {\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${`runners_activation:${params.runnerInstanceId}`}))`,\n );\n const [runner] = await tx\n .select({\n workspaceId: providerRunners.workspaceId,\n runnerSessionId: providerRunners.runnerSessionId,\n state: providerRunners.state,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n ),\n )\n .limit(1)\n .for('update');\n const notIssuedReason = getRunnerActivationTokenNotIssuedReason(runner);\n if (notIssuedReason) {\n recordRunnerActivationTokenNotIssuedWithLog(notIssuedReason, params);\n return null;\n }\n\n await tx\n .update(runnerActivationTokens)\n .set({revokedAt: sql`now()`})\n .where(\n and(\n eq(runnerActivationTokens.runnerInstanceId, params.runnerInstanceId),\n isNull(runnerActivationTokens.consumedAt),\n isNull(runnerActivationTokens.revokedAt),\n ),\n );\n const rawToken = generateOpaqueToken('runnerActivationToken');\n await tx.insert(runnerActivationTokens).values({\n runnerInstanceId: params.runnerInstanceId,\n hashedToken: hashOpaqueToken(rawToken),\n prefix: extractDisplayPrefix(rawToken),\n expiresAt: new Date(Date.now() + params.ttlSeconds * 1000),\n });\n return rawToken;\n}\n\nexport async function getRunnerAssignment(params: {\n runnerInstanceId: string;\n provisionerId: string;\n}) {\n const [runner] = await db()\n .select({\n workspaceId: providerRunners.workspaceId,\n runnerSessionId: providerRunners.runnerSessionId,\n state: providerRunners.state,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n ),\n )\n .limit(1);\n return runner?.workspaceId && !runner.runnerSessionId && runner.state === 'running'\n ? {workspaceId: runner.workspaceId, runnerSessionId: runner.runnerSessionId}\n : null;\n}\n\nfunction getRunnerActivationTokenNotIssuedReason(\n runner: Pick<RunnerInstanceDb, 'workspaceId' | 'runnerSessionId' | 'state'> | undefined,\n): RunnerActivationTokenNotIssuedReason | null {\n if (!runner) return 'runner-not-found';\n if (!runner.workspaceId) return 'missing-workspace';\n if (runner.runnerSessionId) return 'existing-session';\n if (runner.state !== 'running') return 'not-running';\n return null;\n}\n\nfunction recordRunnerActivationTokenNotIssuedWithLog(\n reason: RunnerActivationTokenNotIssuedReason,\n params: {\n runnerInstanceId: string;\n provisionerId: string;\n surface: RunnerActivationTokenNotIssuedSurface;\n },\n): void {\n recordRunnerActivationTokenNotIssued({reason, surface: params.surface});\n logger().debug(\n {\n runnerInstanceId: params.runnerInstanceId,\n provisionerId: params.provisionerId,\n reason,\n surface: params.surface,\n },\n 'Runner activation token was not issued',\n );\n}\n"],"names":["logger","extractDisplayPrefix","generateOpaqueToken","hashOpaqueToken","and","eq","isNull","sql","db","runnerActivationTokens","providerRunners","recordRunnerActivationTokenNotIssued","issueRunnerActivationToken","params","transaction","tx","issueRunnerActivationTokenTx","execute","runnerInstanceId","runner","select","workspaceId","runnerSessionId","state","from","where","id","provisionerId","limit","for","notIssuedReason","getRunnerActivationTokenNotIssuedReason","recordRunnerActivationTokenNotIssuedWithLog","update","set","revokedAt","consumedAt","rawToken","insert","values","hashedToken","prefix","expiresAt","Date","now","ttlSeconds","getRunnerAssignment","reason","surface","debug"],"mappings":"AAAA,SAAQA,MAAM,QAAO,8BAA8B;AACnD,SAAQC,oBAAoB,EAAEC,mBAAmB,EAAEC,eAAe,QAAO,uBAAuB;AAChG,SAAQC,GAAG,EAAEC,EAAE,EAAEC,MAAM,EAAEC,GAAG,QAAO,cAAc;AAEjD,SAAQC,EAAE,QAAO,YAAY;AAC7B,SAAQC,sBAAsB,QAAO,yCAAyC;AAE9E,SAAQC,eAAe,QAAO,iCAAiC;AAC/D,SAGEC,oCAAoC,QAC/B,uBAAuB;AAE9B,OAAO,eAAeC,2BAA2BC,MAKhD;IACC,OAAO,MAAML,KAAKM,WAAW,CAAC,OAAOC,KAAOC,6BAA6BD,IAAIF;AAC/E;AAEA,OAAO,eAAeG,6BACpBD,EAAM,EACNF,MAKC;IAED,MAAME,GAAGE,OAAO,CACdV,GAAG,CAAC,sCAAsC,EAAE,CAAC,mBAAmB,EAAEM,OAAOK,gBAAgB,EAAE,CAAC,EAAE,CAAC;IAEjG,MAAM,CAACC,OAAO,GAAG,MAAMJ,GACpBK,MAAM,CAAC;QACNC,aAAaX,gBAAgBW,WAAW;QACxCC,iBAAiBZ,gBAAgBY,eAAe;QAChDC,OAAOb,gBAAgBa,KAAK;IAC9B,GACCC,IAAI,CAACd,iBACLe,KAAK,CACJrB,IACEC,GAAGK,gBAAgBgB,EAAE,EAAEb,OAAOK,gBAAgB,GAC9Cb,GAAGK,gBAAgBiB,aAAa,EAAEd,OAAOc,aAAa,IAGzDC,KAAK,CAAC,GACNC,GAAG,CAAC;IACP,MAAMC,kBAAkBC,wCAAwCZ;IAChE,IAAIW,iBAAiB;QACnBE,4CAA4CF,iBAAiBjB;QAC7D,OAAO;IACT;IAEA,MAAME,GACHkB,MAAM,CAACxB,wBACPyB,GAAG,CAAC;QAACC,WAAW5B,GAAG,CAAC,KAAK,CAAC;IAAA,GAC1BkB,KAAK,CACJrB,IACEC,GAAGI,uBAAuBS,gBAAgB,EAAEL,OAAOK,gBAAgB,GACnEZ,OAAOG,uBAAuB2B,UAAU,GACxC9B,OAAOG,uBAAuB0B,SAAS;IAG7C,MAAME,WAAWnC,oBAAoB;IACrC,MAAMa,GAAGuB,MAAM,CAAC7B,wBAAwB8B,MAAM,CAAC;QAC7CrB,kBAAkBL,OAAOK,gBAAgB;QACzCsB,aAAarC,gBAAgBkC;QAC7BI,QAAQxC,qBAAqBoC;QAC7BK,WAAW,IAAIC,KAAKA,KAAKC,GAAG,KAAK/B,OAAOgC,UAAU,GAAG;IACvD;IACA,OAAOR;AACT;AAEA,OAAO,eAAeS,oBAAoBjC,MAGzC;IACC,MAAM,CAACM,OAAO,GAAG,MAAMX,KACpBY,MAAM,CAAC;QACNC,aAAaX,gBAAgBW,WAAW;QACxCC,iBAAiBZ,gBAAgBY,eAAe;QAChDC,OAAOb,gBAAgBa,KAAK;IAC9B,GACCC,IAAI,CAACd,iBACLe,KAAK,CACJrB,IACEC,GAAGK,gBAAgBgB,EAAE,EAAEb,OAAOK,gBAAgB,GAC9Cb,GAAGK,gBAAgBiB,aAAa,EAAEd,OAAOc,aAAa,IAGzDC,KAAK,CAAC;IACT,OAAOT,QAAQE,eAAe,CAACF,OAAOG,eAAe,IAAIH,OAAOI,KAAK,KAAK,YACtE;QAACF,aAAaF,OAAOE,WAAW;QAAEC,iBAAiBH,OAAOG,eAAe;IAAA,IACzE;AACN;AAEA,SAASS,wCACPZ,MAAuF;IAEvF,IAAI,CAACA,QAAQ,OAAO;IACpB,IAAI,CAACA,OAAOE,WAAW,EAAE,OAAO;IAChC,IAAIF,OAAOG,eAAe,EAAE,OAAO;IACnC,IAAIH,OAAOI,KAAK,KAAK,WAAW,OAAO;IACvC,OAAO;AACT;AAEA,SAASS,4CACPe,MAA4C,EAC5ClC,MAIC;IAEDF,qCAAqC;QAACoC;QAAQC,SAASnC,OAAOmC,OAAO;IAAA;IACrEhD,SAASiD,KAAK,CACZ;QACE/B,kBAAkBL,OAAOK,gBAAgB;QACzCS,eAAed,OAAOc,aAAa;QACnCoB;QACAC,SAASnC,OAAOmC,OAAO;IACzB,GACA;AAEJ"}
|
|
@@ -13,10 +13,14 @@ export declare function createRunnerInstancesWithBootstrapTokens(params: {
|
|
|
13
13
|
reservationId?: string | null;
|
|
14
14
|
}>;
|
|
15
15
|
ttlSeconds: number;
|
|
16
|
-
}): Promise<
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
}): Promise<{
|
|
17
|
+
runnerInstances: Array<{
|
|
18
|
+
runnerInstanceId: string;
|
|
19
|
+
bootstrapToken: string;
|
|
20
|
+
requestIndex: number;
|
|
21
|
+
}>;
|
|
22
|
+
reservationUnavailable: boolean;
|
|
23
|
+
}>;
|
|
20
24
|
export declare function exchangeRunnerBootstrapToken(params: {
|
|
21
25
|
rawToken: string;
|
|
22
26
|
ttlSeconds: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-control-sessions.d.ts","sourceRoot":"","sources":["../../src/core/runner-control-sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"runner-control-sessions.d.ts","sourceRoot":"","sources":["../../src/core/runner-control-sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAiCxE,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,cAGC;CACF;AAED,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,cAGC;CACF;AAED,wBAAsB,wCAAwC,CAAC,MAAM,EAAE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,KAAK,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC/B,CAAC,CAAC;IACH,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC;IACV,eAAe,EAAE,KAAK,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,sBAAsB,EAAE,OAAO,CAAC;CACjC,CAAC,CAyED;AAED,wBAAsB,4BAA4B,CAAC,MAAM,EAAE;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,IAAI,CAAA;CAAC,CAAC,CA+DpF;AAED,wBAAsB,2BAA2B,CAAC,QAAQ,EAAE,MAAM;;;;eAmBjE;AAED,wBAAsB,0BAA0B,CAAC,MAAM,EAAE;IACvD,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAChD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4IzB;AAYD,wBAAsB,6BAA6B,CAAC,MAAM,EAAE;IAC1D,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,OAAO,CAAC,CAcnB;AAED,wBAAsB,yBAAyB,CAAC,gBAAgB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAW9F"}
|
|
@@ -2,15 +2,15 @@ import { logger } from '@shipfox/node-opentelemetry';
|
|
|
2
2
|
import { extractDisplayPrefix, generateOpaqueToken, hashOpaqueToken } from '@shipfox/node-tokens';
|
|
3
3
|
import { and, eq, gt, isNull, notInArray, or, sql } from 'drizzle-orm';
|
|
4
4
|
import { config } from '#config.js';
|
|
5
|
-
import { ReservationExpiredError, ReservationNotFoundError, RunnerInstanceAlreadyAssignedError, RunnerInstanceNotAssignableError } from '#core/errors.js';
|
|
5
|
+
import { getRunnerAssignmentRejectionReason, ReservationExpiredError, ReservationNotFoundError, RunnerInstanceAlreadyAssignedError, RunnerInstanceNotAssignableError } from '#core/errors.js';
|
|
6
6
|
import { sanitizeRunnerLabels } from '#core/runner-labels.js';
|
|
7
7
|
import { db } from '#db/db.js';
|
|
8
|
-
import { assignRunnerInstancesTx } from '#db/runner-assignments.js';
|
|
9
|
-
import { terminalStates } from '#db/runner-
|
|
8
|
+
import { assignRunnerInstancesTx, validateRunnerReservationCapacityTx } from '#db/runner-assignments.js';
|
|
9
|
+
import { terminalStates } from '#db/runner-states.js';
|
|
10
10
|
import { provisionerTokens } from '#db/schema/provisioner-tokens.js';
|
|
11
11
|
import { runnerBootstrapTokens, runnerControlSessions } from '#db/schema/runner-control-sessions.js';
|
|
12
12
|
import { providerRunners } from '#db/schema/runner-instances.js';
|
|
13
|
-
import { recordRunnerReservationPromotionFailure } from '#metrics/index.js';
|
|
13
|
+
import { recordProviderRunnerAssignmentRejected, recordProviderRunnerControlSessionToAssignment, recordProviderRunnerCreatedToControlSession, recordRunnerReservationCapacityFailure, recordRunnerReservationPromotionFailure } from '#metrics/index.js';
|
|
14
14
|
import { issueRunnerActivationTokenTx } from './runner-activation.js';
|
|
15
15
|
export class RunnerBootstrapTokenInvalidError extends Error {
|
|
16
16
|
constructor(){
|
|
@@ -27,21 +27,63 @@ export class RunnerControlSessionInvalidError extends Error {
|
|
|
27
27
|
export async function createRunnerInstancesWithBootstrapTokens(params) {
|
|
28
28
|
const expiresAt = new Date(Date.now() + params.ttlSeconds * 1000);
|
|
29
29
|
return await db().transaction(async (tx)=>{
|
|
30
|
-
const
|
|
30
|
+
const reservationValidation = await validateRunnerReservationCapacityTx(tx, {
|
|
31
|
+
provisionerId: params.provisionerId,
|
|
32
|
+
requests: params.runnerInstances.reduce((requests, runner)=>{
|
|
33
|
+
if (!runner.reservationId) return requests;
|
|
34
|
+
const request = requests.find((candidate)=>candidate.reservationId === runner.reservationId);
|
|
35
|
+
if (request) request.count += 1;
|
|
36
|
+
else requests.push({
|
|
37
|
+
reservationId: runner.reservationId,
|
|
38
|
+
count: 1
|
|
39
|
+
});
|
|
40
|
+
return requests;
|
|
41
|
+
}, [])
|
|
42
|
+
});
|
|
43
|
+
for (const { reason, count } of reservationValidation.unavailableByReservation.values())recordRunnerReservationCapacityFailure(reason, count);
|
|
44
|
+
const remainingAcceptedByReservation = new Map(reservationValidation.acceptedByReservation);
|
|
45
|
+
const runnerInstances = params.runnerInstances.flatMap((runner, requestIndex)=>{
|
|
46
|
+
if (!runner.reservationId) return [
|
|
47
|
+
{
|
|
48
|
+
...runner,
|
|
49
|
+
requestIndex
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
const remaining = remainingAcceptedByReservation.get(runner.reservationId) ?? 0;
|
|
53
|
+
if (remaining === 0) return [];
|
|
54
|
+
remainingAcceptedByReservation.set(runner.reservationId, remaining - 1);
|
|
55
|
+
return [
|
|
56
|
+
{
|
|
57
|
+
...runner,
|
|
58
|
+
requestIndex
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
});
|
|
62
|
+
if (runnerInstances.length === 0) return {
|
|
63
|
+
runnerInstances: [],
|
|
64
|
+
reservationUnavailable: reservationValidation.unavailableByReservation.size > 0
|
|
65
|
+
};
|
|
66
|
+
const instances = await tx.insert(providerRunners).values(runnerInstances.map((runner)=>({
|
|
31
67
|
provisionerId: params.provisionerId,
|
|
32
68
|
providerKind: params.providerKind ?? null,
|
|
33
69
|
templateKey: runner.templateKey ?? null,
|
|
34
70
|
intendedReservationId: runner.reservationId ?? null,
|
|
71
|
+
launchKind: runner.reservationId ? 'demand' : 'warm',
|
|
35
72
|
state: 'starting',
|
|
36
73
|
labels: [],
|
|
37
74
|
reportedAt: new Date()
|
|
38
75
|
}))).returning({
|
|
39
76
|
id: providerRunners.id
|
|
40
77
|
});
|
|
41
|
-
const results = instances.map((instance)=>
|
|
78
|
+
const results = instances.map((instance, index)=>{
|
|
79
|
+
const runner = runnerInstances[index];
|
|
80
|
+
if (!runner) throw new Error('Runner instance insert returned an unexpected row count');
|
|
81
|
+
return {
|
|
42
82
|
runnerInstanceId: instance.id,
|
|
43
|
-
bootstrapToken: generateOpaqueToken('runnerBootstrapToken')
|
|
44
|
-
|
|
83
|
+
bootstrapToken: generateOpaqueToken('runnerBootstrapToken'),
|
|
84
|
+
requestIndex: runner.requestIndex
|
|
85
|
+
};
|
|
86
|
+
});
|
|
45
87
|
await tx.insert(runnerBootstrapTokens).values(results.map((result)=>({
|
|
46
88
|
runnerInstanceId: result.runnerInstanceId,
|
|
47
89
|
provisionerId: params.provisionerId,
|
|
@@ -49,17 +91,26 @@ export async function createRunnerInstancesWithBootstrapTokens(params) {
|
|
|
49
91
|
prefix: extractDisplayPrefix(result.bootstrapToken),
|
|
50
92
|
expiresAt
|
|
51
93
|
})));
|
|
52
|
-
return
|
|
94
|
+
return {
|
|
95
|
+
runnerInstances: results,
|
|
96
|
+
reservationUnavailable: reservationValidation.unavailableByReservation.size > 0
|
|
97
|
+
};
|
|
53
98
|
});
|
|
54
99
|
}
|
|
55
100
|
export async function exchangeRunnerBootstrapToken(params) {
|
|
56
101
|
const controlSessionToken = generateOpaqueToken('runnerControlSession');
|
|
57
102
|
const expiresAt = new Date(Date.now() + params.ttlSeconds * 1000);
|
|
58
|
-
|
|
103
|
+
const result = await db().transaction(async (tx)=>{
|
|
59
104
|
const [bootstrap] = await tx.update(runnerBootstrapTokens).set({
|
|
60
105
|
consumedAt: sql`now()`
|
|
61
106
|
}).where(and(eq(runnerBootstrapTokens.hashedToken, hashOpaqueToken(params.rawToken)), isNull(runnerBootstrapTokens.consumedAt), isNull(runnerBootstrapTokens.revokedAt), gt(runnerBootstrapTokens.expiresAt, sql`now()`))).returning();
|
|
62
107
|
if (!bootstrap) throw new RunnerBootstrapTokenInvalidError();
|
|
108
|
+
const [runner] = await tx.select({
|
|
109
|
+
runnerInstanceId: providerRunners.id,
|
|
110
|
+
createdAt: providerRunners.createdAt,
|
|
111
|
+
provider: providerRunners.providerKind,
|
|
112
|
+
launchKind: providerRunners.launchKind
|
|
113
|
+
}).from(providerRunners).where(and(eq(providerRunners.id, bootstrap.runnerInstanceId), eq(providerRunners.provisionerId, bootstrap.provisionerId))).limit(1);
|
|
63
114
|
const [session] = await tx.insert(runnerControlSessions).values({
|
|
64
115
|
runnerInstanceId: bootstrap.runnerInstanceId,
|
|
65
116
|
provisionerId: bootstrap.provisionerId,
|
|
@@ -67,15 +118,28 @@ export async function exchangeRunnerBootstrapToken(params) {
|
|
|
67
118
|
prefix: extractDisplayPrefix(controlSessionToken),
|
|
68
119
|
expiresAt
|
|
69
120
|
}).returning({
|
|
70
|
-
|
|
121
|
+
createdAt: runnerControlSessions.createdAt
|
|
71
122
|
});
|
|
72
123
|
if (!session) throw new Error('Runner control session insert returned no row');
|
|
73
124
|
return {
|
|
125
|
+
runner,
|
|
126
|
+
session,
|
|
74
127
|
runnerInstanceId: bootstrap.runnerInstanceId,
|
|
75
128
|
controlSessionToken,
|
|
76
129
|
expiresAt
|
|
77
130
|
};
|
|
78
131
|
});
|
|
132
|
+
if (result.runner) recordProviderRunnerCreatedToControlSession({
|
|
133
|
+
durationMilliseconds: result.session.createdAt.getTime() - result.runner.createdAt.getTime(),
|
|
134
|
+
provider: result.runner.provider,
|
|
135
|
+
launchKind: result.runner.launchKind,
|
|
136
|
+
runnerInstanceId: result.runner.runnerInstanceId
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
runnerInstanceId: result.runnerInstanceId,
|
|
140
|
+
controlSessionToken: result.controlSessionToken,
|
|
141
|
+
expiresAt: result.expiresAt
|
|
142
|
+
};
|
|
79
143
|
}
|
|
80
144
|
export async function resolveRunnerControlSession(rawToken) {
|
|
81
145
|
const [session] = await db().select({
|
|
@@ -86,7 +150,7 @@ export async function resolveRunnerControlSession(rawToken) {
|
|
|
86
150
|
return session;
|
|
87
151
|
}
|
|
88
152
|
export async function enrollRunnerControlSession(params) {
|
|
89
|
-
|
|
153
|
+
const result = await db().transaction(async (tx)=>{
|
|
90
154
|
const [current] = await tx.select({
|
|
91
155
|
intendedReservationId: providerRunners.intendedReservationId,
|
|
92
156
|
provisionerScope: provisionerTokens.scope
|
|
@@ -125,23 +189,41 @@ export async function enrollRunnerControlSession(params) {
|
|
|
125
189
|
if (!updated) throw new RunnerControlSessionInvalidError();
|
|
126
190
|
await updateRunnerControlSessionLastSeen(tx, params.runnerInstanceId, params.provisionerId);
|
|
127
191
|
const intendedReservationId = updated.intendedReservationId;
|
|
128
|
-
if (!intendedReservationId) return
|
|
192
|
+
if (!intendedReservationId) return {
|
|
193
|
+
activationToken: null,
|
|
194
|
+
controlSessionToAssignment: [],
|
|
195
|
+
assignmentRejectedReason: null,
|
|
196
|
+
promotionFailureReason: null
|
|
197
|
+
};
|
|
129
198
|
try {
|
|
130
|
-
|
|
131
|
-
await assignRunnerInstancesTx(promotionTx, {
|
|
199
|
+
const promotion = await tx.transaction(async (promotionTx)=>{
|
|
200
|
+
const assignment = await assignRunnerInstancesTx(promotionTx, {
|
|
132
201
|
provisionerId: params.provisionerId,
|
|
133
202
|
reservationId: intendedReservationId,
|
|
134
203
|
runnerInstanceIds: [
|
|
135
204
|
params.runnerInstanceId
|
|
136
|
-
]
|
|
205
|
+
],
|
|
206
|
+
surface: 'enrollment'
|
|
137
207
|
});
|
|
138
|
-
|
|
208
|
+
const activationToken = await issueRunnerActivationTokenTx(promotionTx, {
|
|
139
209
|
runnerInstanceId: params.runnerInstanceId,
|
|
140
210
|
provisionerId: params.provisionerId,
|
|
141
|
-
ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS
|
|
211
|
+
ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS,
|
|
212
|
+
surface: 'enrollment'
|
|
142
213
|
});
|
|
214
|
+
return {
|
|
215
|
+
activationToken,
|
|
216
|
+
controlSessionToAssignment: assignment.controlSessionToAssignment
|
|
217
|
+
};
|
|
143
218
|
});
|
|
219
|
+
return {
|
|
220
|
+
activationToken: promotion.activationToken,
|
|
221
|
+
controlSessionToAssignment: promotion.controlSessionToAssignment,
|
|
222
|
+
assignmentRejectedReason: null,
|
|
223
|
+
promotionFailureReason: null
|
|
224
|
+
};
|
|
144
225
|
} catch (error) {
|
|
226
|
+
const assignmentRejectionReason = getRunnerAssignmentRejectionReason(error);
|
|
145
227
|
const expectedFailureReason = getRunnerReservationPromotionFailureReason(error);
|
|
146
228
|
const details = {
|
|
147
229
|
err: error,
|
|
@@ -150,14 +232,28 @@ export async function enrollRunnerControlSession(params) {
|
|
|
150
232
|
reservationId: intendedReservationId
|
|
151
233
|
};
|
|
152
234
|
if (expectedFailureReason) {
|
|
153
|
-
recordRunnerReservationPromotionFailure(expectedFailureReason);
|
|
154
235
|
logger().debug(details, 'Runner reservation could not be promoted during enrollment');
|
|
155
236
|
} else {
|
|
156
237
|
logger().error(details, 'Unexpected failure promoting runner reservation during enrollment');
|
|
157
238
|
}
|
|
158
|
-
return
|
|
239
|
+
return {
|
|
240
|
+
activationToken: null,
|
|
241
|
+
controlSessionToAssignment: [],
|
|
242
|
+
assignmentRejectedReason: assignmentRejectionReason,
|
|
243
|
+
promotionFailureReason: expectedFailureReason
|
|
244
|
+
};
|
|
159
245
|
}
|
|
160
246
|
});
|
|
247
|
+
for (const observation of result.controlSessionToAssignment)recordProviderRunnerControlSessionToAssignment(observation);
|
|
248
|
+
// These counters intentionally overlap: assignment_rejected records the assignment-facing
|
|
249
|
+
// reason, while reservation_promotion_failure records the enrollment recovery outcome. They
|
|
250
|
+
// answer different questions and must not be summed.
|
|
251
|
+
if (result.assignmentRejectedReason) recordProviderRunnerAssignmentRejected({
|
|
252
|
+
reason: result.assignmentRejectedReason,
|
|
253
|
+
surface: 'enrollment'
|
|
254
|
+
});
|
|
255
|
+
if (result.promotionFailureReason) recordRunnerReservationPromotionFailure(result.promotionFailureReason);
|
|
256
|
+
return result.activationToken;
|
|
161
257
|
}
|
|
162
258
|
function getRunnerReservationPromotionFailureReason(error) {
|
|
163
259
|
if (error instanceof ReservationExpiredError) return 'reservation-expired';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/runner-control-sessions.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport type {NodePgDatabase} from '@shipfox/node-drizzle';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {extractDisplayPrefix, generateOpaqueToken, hashOpaqueToken} from '@shipfox/node-tokens';\nimport {and, eq, gt, isNull, notInArray, or, sql} from 'drizzle-orm';\nimport {config} from '#config.js';\nimport {\n ReservationExpiredError,\n ReservationNotFoundError,\n RunnerInstanceAlreadyAssignedError,\n RunnerInstanceNotAssignableError,\n} from '#core/errors.js';\nimport {sanitizeRunnerLabels} from '#core/runner-labels.js';\nimport {db, type schema, type Tx} from '#db/db.js';\nimport {assignRunnerInstancesTx} from '#db/runner-assignments.js';\nimport {terminalStates} from '#db/runner-instances.js';\nimport {provisionerTokens} from '#db/schema/provisioner-tokens.js';\nimport {runnerBootstrapTokens, runnerControlSessions} from '#db/schema/runner-control-sessions.js';\nimport {providerRunners} from '#db/schema/runner-instances.js';\nimport {\n type RunnerReservationPromotionFailureReason,\n recordRunnerReservationPromotionFailure,\n} from '#metrics/index.js';\nimport {issueRunnerActivationTokenTx} from './runner-activation.js';\n\nexport class RunnerBootstrapTokenInvalidError extends Error {\n constructor() {\n super('Runner bootstrap token is invalid, expired, or has already been used');\n this.name = 'RunnerBootstrapTokenInvalidError';\n }\n}\n\nexport class RunnerControlSessionInvalidError extends Error {\n constructor() {\n super('Runner control session is invalid, expired, or closed');\n this.name = 'RunnerControlSessionInvalidError';\n }\n}\n\nexport async function createRunnerInstancesWithBootstrapTokens(params: {\n provisionerId: string;\n providerKind?: string | null;\n runnerInstances: Array<{\n templateKey?: string | null;\n reservationId?: string | null;\n }>;\n ttlSeconds: number;\n}): Promise<Array<{runnerInstanceId: string; bootstrapToken: string}>> {\n const expiresAt = new Date(Date.now() + params.ttlSeconds * 1000);\n return await db().transaction(async (tx) => {\n const instances = await tx\n .insert(providerRunners)\n .values(\n params.runnerInstances.map((runner) => ({\n provisionerId: params.provisionerId,\n providerKind: params.providerKind ?? null,\n templateKey: runner.templateKey ?? null,\n intendedReservationId: runner.reservationId ?? null,\n state: 'starting' as const,\n labels: [],\n reportedAt: new Date(),\n })),\n )\n .returning({id: providerRunners.id});\n const results = instances.map((instance) => ({\n runnerInstanceId: instance.id,\n bootstrapToken: generateOpaqueToken('runnerBootstrapToken'),\n }));\n await tx.insert(runnerBootstrapTokens).values(\n results.map((result) => ({\n runnerInstanceId: result.runnerInstanceId,\n provisionerId: params.provisionerId,\n hashedToken: hashOpaqueToken(result.bootstrapToken),\n prefix: extractDisplayPrefix(result.bootstrapToken),\n expiresAt,\n })),\n );\n return results;\n });\n}\n\nexport async function exchangeRunnerBootstrapToken(params: {\n rawToken: string;\n ttlSeconds: number;\n}): Promise<{runnerInstanceId: string; controlSessionToken: string; expiresAt: Date}> {\n const controlSessionToken = generateOpaqueToken('runnerControlSession');\n const expiresAt = new Date(Date.now() + params.ttlSeconds * 1000);\n return await db().transaction(async (tx) => {\n const [bootstrap] = await tx\n .update(runnerBootstrapTokens)\n .set({consumedAt: sql`now()`})\n .where(\n and(\n eq(runnerBootstrapTokens.hashedToken, hashOpaqueToken(params.rawToken)),\n isNull(runnerBootstrapTokens.consumedAt),\n isNull(runnerBootstrapTokens.revokedAt),\n gt(runnerBootstrapTokens.expiresAt, sql`now()`),\n ),\n )\n .returning();\n if (!bootstrap) throw new RunnerBootstrapTokenInvalidError();\n const [session] = await tx\n .insert(runnerControlSessions)\n .values({\n runnerInstanceId: bootstrap.runnerInstanceId,\n provisionerId: bootstrap.provisionerId,\n hashedToken: hashOpaqueToken(controlSessionToken),\n prefix: extractDisplayPrefix(controlSessionToken),\n expiresAt,\n })\n .returning({id: runnerControlSessions.id});\n if (!session) throw new Error('Runner control session insert returned no row');\n return {runnerInstanceId: bootstrap.runnerInstanceId, controlSessionToken, expiresAt};\n });\n}\n\nexport async function resolveRunnerControlSession(rawToken: string) {\n const [session] = await db()\n .select({\n id: runnerControlSessions.id,\n runnerInstanceId: runnerControlSessions.runnerInstanceId,\n provisionerId: runnerControlSessions.provisionerId,\n })\n .from(runnerControlSessions)\n .leftJoin(provisionerTokens, eq(provisionerTokens.id, runnerControlSessions.provisionerId))\n .where(\n and(\n eq(runnerControlSessions.hashedToken, hashOpaqueToken(rawToken)),\n isNull(runnerControlSessions.closedAt),\n or(isNull(provisionerTokens.id), isNull(provisionerTokens.revokedAt)),\n gt(runnerControlSessions.expiresAt, sql`now()`),\n ),\n )\n .limit(1);\n return session;\n}\n\nexport async function enrollRunnerControlSession(params: {\n runnerInstanceId: string;\n provisionerId: string;\n labels: string[];\n capabilities?: RunnerToolCapabilitiesDto | null;\n providerKind: string;\n protocolVersion: string;\n}): Promise<string | null> {\n return await db().transaction(async (tx) => {\n const [current] = await tx\n .select({\n intendedReservationId: providerRunners.intendedReservationId,\n provisionerScope: provisionerTokens.scope,\n })\n .from(providerRunners)\n .innerJoin(provisionerTokens, eq(provisionerTokens.id, providerRunners.provisionerId))\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n ),\n );\n if (!current) throw new RunnerControlSessionInvalidError();\n if (current.intendedReservationId)\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${`runners_assignment:${params.provisionerId}:${current.intendedReservationId}`}))`,\n );\n\n // Provider reports may populate reservationId before the assignment commits. assignedAt is\n // written by the assignment transaction, so keep the guard on that write boundary.\n const [metadataUpdated] = await tx\n .update(providerRunners)\n .set({\n labels: sanitizeRunnerLabels(params.labels, {\n scope: current.provisionerScope,\n source: 'runner control enrollment',\n }),\n providerKind: params.providerKind,\n protocolVersion: params.protocolVersion,\n capabilities: params.capabilities ?? null,\n })\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.assignedAt),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({id: providerRunners.id});\n if (!metadataUpdated)\n logger().debug(\n {runnerInstanceId: params.runnerInstanceId, provisionerId: params.provisionerId},\n 'Runner enrollment metadata update skipped for assigned or terminal runner',\n );\n\n const [updated] = await tx\n .update(providerRunners)\n .set({\n state: 'running',\n reportedAt: sql`now()`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({\n id: providerRunners.id,\n intendedReservationId: providerRunners.intendedReservationId,\n });\n if (!updated) throw new RunnerControlSessionInvalidError();\n\n await updateRunnerControlSessionLastSeen(tx, params.runnerInstanceId, params.provisionerId);\n\n const intendedReservationId = updated.intendedReservationId;\n if (!intendedReservationId) return null;\n\n try {\n return await tx.transaction(async (promotionTx) => {\n await assignRunnerInstancesTx(promotionTx, {\n provisionerId: params.provisionerId,\n reservationId: intendedReservationId,\n runnerInstanceIds: [params.runnerInstanceId],\n });\n return await issueRunnerActivationTokenTx(promotionTx, {\n runnerInstanceId: params.runnerInstanceId,\n provisionerId: params.provisionerId,\n ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS,\n });\n });\n } catch (error) {\n const expectedFailureReason = getRunnerReservationPromotionFailureReason(error);\n const details = {\n err: error,\n runnerInstanceId: params.runnerInstanceId,\n provisionerId: params.provisionerId,\n reservationId: intendedReservationId,\n };\n if (expectedFailureReason) {\n recordRunnerReservationPromotionFailure(expectedFailureReason);\n logger().debug(details, 'Runner reservation could not be promoted during enrollment');\n } else {\n logger().error(\n details,\n 'Unexpected failure promoting runner reservation during enrollment',\n );\n }\n return null;\n }\n });\n}\n\nfunction getRunnerReservationPromotionFailureReason(\n error: unknown,\n): RunnerReservationPromotionFailureReason | null {\n if (error instanceof ReservationExpiredError) return 'reservation-expired';\n if (error instanceof ReservationNotFoundError) return 'reservation-not-found';\n if (error instanceof RunnerInstanceAlreadyAssignedError) return 'already-assigned';\n if (error instanceof RunnerInstanceNotAssignableError) return 'not-assignable';\n return null;\n}\n\nexport async function attachRunnerControlProviderId(params: {\n runnerInstanceId: string;\n provisionerId: string;\n providerRunnerId: string;\n}): Promise<boolean> {\n const rows = await db()\n .update(providerRunners)\n .set({providerRunnerId: params.providerRunnerId, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.providerRunnerId),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({id: providerRunners.id});\n return rows.length === 1;\n}\n\nexport async function touchRunnerControlSession(runnerInstanceId: string, provisionerId: string) {\n await updateRunnerControlSessionLastSeen(db(), runnerInstanceId, provisionerId);\n await db()\n .update(providerRunners)\n .set({reportedAt: sql`now()`, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, runnerInstanceId),\n eq(providerRunners.provisionerId, provisionerId),\n ),\n );\n}\n\nasync function updateRunnerControlSessionLastSeen(\n tx: Tx | NodePgDatabase<typeof schema>,\n runnerInstanceId: string,\n provisionerId: string,\n) {\n await tx\n .update(runnerControlSessions)\n .set({lastSeenAt: sql`now()`})\n .where(\n and(\n eq(runnerControlSessions.runnerInstanceId, runnerInstanceId),\n eq(runnerControlSessions.provisionerId, provisionerId),\n isNull(runnerControlSessions.closedAt),\n ),\n );\n}\n"],"names":["logger","extractDisplayPrefix","generateOpaqueToken","hashOpaqueToken","and","eq","gt","isNull","notInArray","or","sql","config","ReservationExpiredError","ReservationNotFoundError","RunnerInstanceAlreadyAssignedError","RunnerInstanceNotAssignableError","sanitizeRunnerLabels","db","assignRunnerInstancesTx","terminalStates","provisionerTokens","runnerBootstrapTokens","runnerControlSessions","providerRunners","recordRunnerReservationPromotionFailure","issueRunnerActivationTokenTx","RunnerBootstrapTokenInvalidError","Error","name","RunnerControlSessionInvalidError","createRunnerInstancesWithBootstrapTokens","params","expiresAt","Date","now","ttlSeconds","transaction","tx","instances","insert","values","runnerInstances","map","runner","provisionerId","providerKind","templateKey","intendedReservationId","reservationId","state","labels","reportedAt","returning","id","results","instance","runnerInstanceId","bootstrapToken","result","hashedToken","prefix","exchangeRunnerBootstrapToken","controlSessionToken","bootstrap","update","set","consumedAt","where","rawToken","revokedAt","session","resolveRunnerControlSession","select","from","leftJoin","closedAt","limit","enrollRunnerControlSession","current","provisionerScope","scope","innerJoin","execute","metadataUpdated","source","protocolVersion","capabilities","assignedAt","debug","updated","updatedAt","updateRunnerControlSessionLastSeen","promotionTx","runnerInstanceIds","RUNNER_ACTIVATION_TOKEN_TTL_SECONDS","error","expectedFailureReason","getRunnerReservationPromotionFailureReason","details","err","attachRunnerControlProviderId","rows","providerRunnerId","length","touchRunnerControlSession","lastSeenAt"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/runner-control-sessions.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport type {NodePgDatabase} from '@shipfox/node-drizzle';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {extractDisplayPrefix, generateOpaqueToken, hashOpaqueToken} from '@shipfox/node-tokens';\nimport {and, eq, gt, isNull, notInArray, or, sql} from 'drizzle-orm';\nimport {config} from '#config.js';\nimport {\n getRunnerAssignmentRejectionReason,\n ReservationExpiredError,\n ReservationNotFoundError,\n RunnerInstanceAlreadyAssignedError,\n RunnerInstanceNotAssignableError,\n} from '#core/errors.js';\nimport {sanitizeRunnerLabels} from '#core/runner-labels.js';\nimport {db, type schema, type Tx} from '#db/db.js';\nimport {\n assignRunnerInstancesTx,\n validateRunnerReservationCapacityTx,\n} from '#db/runner-assignments.js';\nimport {terminalStates} from '#db/runner-states.js';\nimport {provisionerTokens} from '#db/schema/provisioner-tokens.js';\nimport {runnerBootstrapTokens, runnerControlSessions} from '#db/schema/runner-control-sessions.js';\nimport {providerRunners} from '#db/schema/runner-instances.js';\nimport {\n type RunnerReservationPromotionFailureReason,\n recordProviderRunnerAssignmentRejected,\n recordProviderRunnerControlSessionToAssignment,\n recordProviderRunnerCreatedToControlSession,\n recordRunnerReservationCapacityFailure,\n recordRunnerReservationPromotionFailure,\n} from '#metrics/index.js';\nimport {issueRunnerActivationTokenTx} from './runner-activation.js';\n\nexport class RunnerBootstrapTokenInvalidError extends Error {\n constructor() {\n super('Runner bootstrap token is invalid, expired, or has already been used');\n this.name = 'RunnerBootstrapTokenInvalidError';\n }\n}\n\nexport class RunnerControlSessionInvalidError extends Error {\n constructor() {\n super('Runner control session is invalid, expired, or closed');\n this.name = 'RunnerControlSessionInvalidError';\n }\n}\n\nexport async function createRunnerInstancesWithBootstrapTokens(params: {\n provisionerId: string;\n providerKind?: string | null;\n runnerInstances: Array<{\n templateKey?: string | null;\n reservationId?: string | null;\n }>;\n ttlSeconds: number;\n}): Promise<{\n runnerInstances: Array<{\n runnerInstanceId: string;\n bootstrapToken: string;\n requestIndex: number;\n }>;\n reservationUnavailable: boolean;\n}> {\n const expiresAt = new Date(Date.now() + params.ttlSeconds * 1000);\n return await db().transaction(async (tx) => {\n const reservationValidation = await validateRunnerReservationCapacityTx(tx, {\n provisionerId: params.provisionerId,\n requests: params.runnerInstances.reduce(\n (requests, runner) => {\n if (!runner.reservationId) return requests;\n const request = requests.find(\n (candidate) => candidate.reservationId === runner.reservationId,\n );\n if (request) request.count += 1;\n else requests.push({reservationId: runner.reservationId, count: 1});\n return requests;\n },\n [] as Array<{reservationId: string; count: number}>,\n ),\n });\n for (const {reason, count} of reservationValidation.unavailableByReservation.values())\n recordRunnerReservationCapacityFailure(reason, count);\n const remainingAcceptedByReservation = new Map(reservationValidation.acceptedByReservation);\n const runnerInstances = params.runnerInstances.flatMap((runner, requestIndex) => {\n if (!runner.reservationId) return [{...runner, requestIndex}];\n const remaining = remainingAcceptedByReservation.get(runner.reservationId) ?? 0;\n if (remaining === 0) return [];\n remainingAcceptedByReservation.set(runner.reservationId, remaining - 1);\n return [{...runner, requestIndex}];\n });\n\n if (runnerInstances.length === 0)\n return {\n runnerInstances: [],\n reservationUnavailable: reservationValidation.unavailableByReservation.size > 0,\n };\n\n const instances = await tx\n .insert(providerRunners)\n .values(\n runnerInstances.map((runner) => ({\n provisionerId: params.provisionerId,\n providerKind: params.providerKind ?? null,\n templateKey: runner.templateKey ?? null,\n intendedReservationId: runner.reservationId ?? null,\n launchKind: runner.reservationId ? ('demand' as const) : ('warm' as const),\n state: 'starting' as const,\n labels: [],\n reportedAt: new Date(),\n })),\n )\n .returning({id: providerRunners.id});\n const results = instances.map((instance, index) => {\n const runner = runnerInstances[index];\n if (!runner) throw new Error('Runner instance insert returned an unexpected row count');\n return {\n runnerInstanceId: instance.id,\n bootstrapToken: generateOpaqueToken('runnerBootstrapToken'),\n requestIndex: runner.requestIndex,\n };\n });\n await tx.insert(runnerBootstrapTokens).values(\n results.map((result) => ({\n runnerInstanceId: result.runnerInstanceId,\n provisionerId: params.provisionerId,\n hashedToken: hashOpaqueToken(result.bootstrapToken),\n prefix: extractDisplayPrefix(result.bootstrapToken),\n expiresAt,\n })),\n );\n return {\n runnerInstances: results,\n reservationUnavailable: reservationValidation.unavailableByReservation.size > 0,\n };\n });\n}\n\nexport async function exchangeRunnerBootstrapToken(params: {\n rawToken: string;\n ttlSeconds: number;\n}): Promise<{runnerInstanceId: string; controlSessionToken: string; expiresAt: Date}> {\n const controlSessionToken = generateOpaqueToken('runnerControlSession');\n const expiresAt = new Date(Date.now() + params.ttlSeconds * 1000);\n const result = await db().transaction(async (tx) => {\n const [bootstrap] = await tx\n .update(runnerBootstrapTokens)\n .set({consumedAt: sql`now()`})\n .where(\n and(\n eq(runnerBootstrapTokens.hashedToken, hashOpaqueToken(params.rawToken)),\n isNull(runnerBootstrapTokens.consumedAt),\n isNull(runnerBootstrapTokens.revokedAt),\n gt(runnerBootstrapTokens.expiresAt, sql`now()`),\n ),\n )\n .returning();\n if (!bootstrap) throw new RunnerBootstrapTokenInvalidError();\n const [runner] = await tx\n .select({\n runnerInstanceId: providerRunners.id,\n createdAt: providerRunners.createdAt,\n provider: providerRunners.providerKind,\n launchKind: providerRunners.launchKind,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.id, bootstrap.runnerInstanceId),\n eq(providerRunners.provisionerId, bootstrap.provisionerId),\n ),\n )\n .limit(1);\n const [session] = await tx\n .insert(runnerControlSessions)\n .values({\n runnerInstanceId: bootstrap.runnerInstanceId,\n provisionerId: bootstrap.provisionerId,\n hashedToken: hashOpaqueToken(controlSessionToken),\n prefix: extractDisplayPrefix(controlSessionToken),\n expiresAt,\n })\n .returning({createdAt: runnerControlSessions.createdAt});\n if (!session) throw new Error('Runner control session insert returned no row');\n return {\n runner,\n session,\n runnerInstanceId: bootstrap.runnerInstanceId,\n controlSessionToken,\n expiresAt,\n };\n });\n if (result.runner)\n recordProviderRunnerCreatedToControlSession({\n durationMilliseconds: result.session.createdAt.getTime() - result.runner.createdAt.getTime(),\n provider: result.runner.provider,\n launchKind: result.runner.launchKind,\n runnerInstanceId: result.runner.runnerInstanceId,\n });\n return {\n runnerInstanceId: result.runnerInstanceId,\n controlSessionToken: result.controlSessionToken,\n expiresAt: result.expiresAt,\n };\n}\n\nexport async function resolveRunnerControlSession(rawToken: string) {\n const [session] = await db()\n .select({\n id: runnerControlSessions.id,\n runnerInstanceId: runnerControlSessions.runnerInstanceId,\n provisionerId: runnerControlSessions.provisionerId,\n })\n .from(runnerControlSessions)\n .leftJoin(provisionerTokens, eq(provisionerTokens.id, runnerControlSessions.provisionerId))\n .where(\n and(\n eq(runnerControlSessions.hashedToken, hashOpaqueToken(rawToken)),\n isNull(runnerControlSessions.closedAt),\n or(isNull(provisionerTokens.id), isNull(provisionerTokens.revokedAt)),\n gt(runnerControlSessions.expiresAt, sql`now()`),\n ),\n )\n .limit(1);\n return session;\n}\n\nexport async function enrollRunnerControlSession(params: {\n runnerInstanceId: string;\n provisionerId: string;\n labels: string[];\n capabilities?: RunnerToolCapabilitiesDto | null;\n providerKind: string;\n protocolVersion: string;\n}): Promise<string | null> {\n const result = await db().transaction(async (tx) => {\n const [current] = await tx\n .select({\n intendedReservationId: providerRunners.intendedReservationId,\n provisionerScope: provisionerTokens.scope,\n })\n .from(providerRunners)\n .innerJoin(provisionerTokens, eq(provisionerTokens.id, providerRunners.provisionerId))\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n ),\n );\n if (!current) throw new RunnerControlSessionInvalidError();\n if (current.intendedReservationId)\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${`runners_assignment:${params.provisionerId}:${current.intendedReservationId}`}))`,\n );\n\n // Provider reports may populate reservationId before the assignment commits. assignedAt is\n // written by the assignment transaction, so keep the guard on that write boundary.\n const [metadataUpdated] = await tx\n .update(providerRunners)\n .set({\n labels: sanitizeRunnerLabels(params.labels, {\n scope: current.provisionerScope,\n source: 'runner control enrollment',\n }),\n providerKind: params.providerKind,\n protocolVersion: params.protocolVersion,\n capabilities: params.capabilities ?? null,\n })\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.assignedAt),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({id: providerRunners.id});\n if (!metadataUpdated)\n logger().debug(\n {runnerInstanceId: params.runnerInstanceId, provisionerId: params.provisionerId},\n 'Runner enrollment metadata update skipped for assigned or terminal runner',\n );\n\n const [updated] = await tx\n .update(providerRunners)\n .set({\n state: 'running',\n reportedAt: sql`now()`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({\n id: providerRunners.id,\n intendedReservationId: providerRunners.intendedReservationId,\n });\n if (!updated) throw new RunnerControlSessionInvalidError();\n\n await updateRunnerControlSessionLastSeen(tx, params.runnerInstanceId, params.provisionerId);\n\n const intendedReservationId = updated.intendedReservationId;\n if (!intendedReservationId)\n return {\n activationToken: null,\n controlSessionToAssignment: [],\n assignmentRejectedReason: null,\n promotionFailureReason: null,\n };\n\n try {\n const promotion = await tx.transaction(async (promotionTx) => {\n const assignment = await assignRunnerInstancesTx(promotionTx, {\n provisionerId: params.provisionerId,\n reservationId: intendedReservationId,\n runnerInstanceIds: [params.runnerInstanceId],\n surface: 'enrollment',\n });\n const activationToken = await issueRunnerActivationTokenTx(promotionTx, {\n runnerInstanceId: params.runnerInstanceId,\n provisionerId: params.provisionerId,\n ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS,\n surface: 'enrollment',\n });\n return {activationToken, controlSessionToAssignment: assignment.controlSessionToAssignment};\n });\n return {\n activationToken: promotion.activationToken,\n controlSessionToAssignment: promotion.controlSessionToAssignment,\n assignmentRejectedReason: null,\n promotionFailureReason: null,\n };\n } catch (error) {\n const assignmentRejectionReason = getRunnerAssignmentRejectionReason(error);\n const expectedFailureReason = getRunnerReservationPromotionFailureReason(error);\n const details = {\n err: error,\n runnerInstanceId: params.runnerInstanceId,\n provisionerId: params.provisionerId,\n reservationId: intendedReservationId,\n };\n if (expectedFailureReason) {\n logger().debug(details, 'Runner reservation could not be promoted during enrollment');\n } else {\n logger().error(\n details,\n 'Unexpected failure promoting runner reservation during enrollment',\n );\n }\n return {\n activationToken: null,\n controlSessionToAssignment: [],\n assignmentRejectedReason: assignmentRejectionReason,\n promotionFailureReason: expectedFailureReason,\n };\n }\n });\n for (const observation of result.controlSessionToAssignment)\n recordProviderRunnerControlSessionToAssignment(observation);\n // These counters intentionally overlap: assignment_rejected records the assignment-facing\n // reason, while reservation_promotion_failure records the enrollment recovery outcome. They\n // answer different questions and must not be summed.\n if (result.assignmentRejectedReason)\n recordProviderRunnerAssignmentRejected({\n reason: result.assignmentRejectedReason,\n surface: 'enrollment',\n });\n if (result.promotionFailureReason)\n recordRunnerReservationPromotionFailure(result.promotionFailureReason);\n return result.activationToken;\n}\n\nfunction getRunnerReservationPromotionFailureReason(\n error: unknown,\n): RunnerReservationPromotionFailureReason | null {\n if (error instanceof ReservationExpiredError) return 'reservation-expired';\n if (error instanceof ReservationNotFoundError) return 'reservation-not-found';\n if (error instanceof RunnerInstanceAlreadyAssignedError) return 'already-assigned';\n if (error instanceof RunnerInstanceNotAssignableError) return 'not-assignable';\n return null;\n}\n\nexport async function attachRunnerControlProviderId(params: {\n runnerInstanceId: string;\n provisionerId: string;\n providerRunnerId: string;\n}): Promise<boolean> {\n const rows = await db()\n .update(providerRunners)\n .set({providerRunnerId: params.providerRunnerId, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.providerRunnerId),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({id: providerRunners.id});\n return rows.length === 1;\n}\n\nexport async function touchRunnerControlSession(runnerInstanceId: string, provisionerId: string) {\n await updateRunnerControlSessionLastSeen(db(), runnerInstanceId, provisionerId);\n await db()\n .update(providerRunners)\n .set({reportedAt: sql`now()`, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, runnerInstanceId),\n eq(providerRunners.provisionerId, provisionerId),\n ),\n );\n}\n\nasync function updateRunnerControlSessionLastSeen(\n tx: Tx | NodePgDatabase<typeof schema>,\n runnerInstanceId: string,\n provisionerId: string,\n) {\n await tx\n .update(runnerControlSessions)\n .set({lastSeenAt: sql`now()`})\n .where(\n and(\n eq(runnerControlSessions.runnerInstanceId, runnerInstanceId),\n eq(runnerControlSessions.provisionerId, provisionerId),\n isNull(runnerControlSessions.closedAt),\n ),\n );\n}\n"],"names":["logger","extractDisplayPrefix","generateOpaqueToken","hashOpaqueToken","and","eq","gt","isNull","notInArray","or","sql","config","getRunnerAssignmentRejectionReason","ReservationExpiredError","ReservationNotFoundError","RunnerInstanceAlreadyAssignedError","RunnerInstanceNotAssignableError","sanitizeRunnerLabels","db","assignRunnerInstancesTx","validateRunnerReservationCapacityTx","terminalStates","provisionerTokens","runnerBootstrapTokens","runnerControlSessions","providerRunners","recordProviderRunnerAssignmentRejected","recordProviderRunnerControlSessionToAssignment","recordProviderRunnerCreatedToControlSession","recordRunnerReservationCapacityFailure","recordRunnerReservationPromotionFailure","issueRunnerActivationTokenTx","RunnerBootstrapTokenInvalidError","Error","name","RunnerControlSessionInvalidError","createRunnerInstancesWithBootstrapTokens","params","expiresAt","Date","now","ttlSeconds","transaction","tx","reservationValidation","provisionerId","requests","runnerInstances","reduce","runner","reservationId","request","find","candidate","count","push","reason","unavailableByReservation","values","remainingAcceptedByReservation","Map","acceptedByReservation","flatMap","requestIndex","remaining","get","set","length","reservationUnavailable","size","instances","insert","map","providerKind","templateKey","intendedReservationId","launchKind","state","labels","reportedAt","returning","id","results","instance","index","runnerInstanceId","bootstrapToken","result","hashedToken","prefix","exchangeRunnerBootstrapToken","controlSessionToken","bootstrap","update","consumedAt","where","rawToken","revokedAt","select","createdAt","provider","from","limit","session","durationMilliseconds","getTime","resolveRunnerControlSession","leftJoin","closedAt","enrollRunnerControlSession","current","provisionerScope","scope","innerJoin","execute","metadataUpdated","source","protocolVersion","capabilities","assignedAt","debug","updated","updatedAt","updateRunnerControlSessionLastSeen","activationToken","controlSessionToAssignment","assignmentRejectedReason","promotionFailureReason","promotion","promotionTx","assignment","runnerInstanceIds","surface","RUNNER_ACTIVATION_TOKEN_TTL_SECONDS","error","assignmentRejectionReason","expectedFailureReason","getRunnerReservationPromotionFailureReason","details","err","observation","attachRunnerControlProviderId","rows","providerRunnerId","touchRunnerControlSession","lastSeenAt"],"mappings":"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"}
|
|
@@ -33,6 +33,7 @@ export interface ReconciledBoundJobExecution {
|
|
|
33
33
|
export interface ReconciledRunnerInstance {
|
|
34
34
|
providerRunnerId: string;
|
|
35
35
|
state: RunnerInstanceState | null;
|
|
36
|
+
intendedReservationId: string | null;
|
|
36
37
|
reservationId: string | null;
|
|
37
38
|
runnerSessionId: string | null;
|
|
38
39
|
boundJobExecution: ReconciledBoundJobExecution | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../src/core/runner-instances.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../src/core/runner-instances.ts"],"names":[],"mappings":"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"}
|
|
@@ -57,6 +57,7 @@ export function reconcileRunnerInstancesFromDbResult(params) {
|
|
|
57
57
|
return {
|
|
58
58
|
providerRunnerId,
|
|
59
59
|
state: row?.state ?? null,
|
|
60
|
+
intendedReservationId: row?.intendedReservationId ?? null,
|
|
60
61
|
reservationId: row?.reservationId ?? null,
|
|
61
62
|
runnerSessionId: row?.runnerSessionId ?? null,
|
|
62
63
|
boundJobExecution: boundJobExecution ? toReconciledBoundJobExecution(boundJobExecution) : null,
|