@shipfox/api-runners 12.2.0 → 12.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +34 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -3
- 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/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 +69 -11
- 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/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.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 +256 -45
- package/dist/db/reservations.js.map +1 -1
- package/dist/db/runner-assignments.d.ts +17 -0
- package/dist/db/runner-assignments.d.ts.map +1 -1
- package/dist/db/runner-assignments.js +103 -8
- package/dist/db/runner-assignments.js.map +1 -1
- package/dist/db/runner-instances.d.ts +5 -2
- package/dist/db/runner-instances.d.ts.map +1 -1
- package/dist/db/runner-instances.js +134 -25
- 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 +22 -15
- 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 +24 -2
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +23 -0
- package/dist/metrics/instance.js.map +1 -1
- package/dist/metrics/service.d.ts.map +1 -1
- package/dist/metrics/service.js +20 -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 +3 -3
- 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 +4 -4
- package/src/config.test.ts +24 -2
- package/src/config.ts +16 -3
- 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/runner-activation.ts +48 -2
- package/src/core/runner-control-sessions.test.ts +230 -4
- package/src/core/runner-control-sessions.ts +84 -10
- 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/index.ts +1 -0
- package/src/db/reservation-locks.ts +22 -0
- package/src/db/reservations.test.ts +1110 -31
- package/src/db/reservations.ts +434 -105
- package/src/db/runner-assignments.test.ts +105 -1
- package/src/db/runner-assignments.ts +178 -9
- package/src/db/runner-instances.test.ts +496 -2
- package/src/db/runner-instances.ts +247 -56
- package/src/db/runner-sessions.ts +26 -15
- 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 +10 -1
- package/src/metrics/instance.ts +59 -2
- package/src/metrics/service.test.ts +106 -0
- package/src/metrics/service.ts +24 -4
- 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 +6 -2
- package/src/presentation/routes/late-runner-enrollment.test.ts +447 -0
- package/src/presentation/routes/poll-demand.test.ts +79 -6
- 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/test/fixtures/late-runner-enrollment.ts +103 -0
- package/test/index.ts +5 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -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":"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"}
|
|
@@ -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;AA6BxE,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,CA8BpF;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,CA4GzB;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"}
|
|
@@ -5,12 +5,12 @@ import { config } from '#config.js';
|
|
|
5
5
|
import { 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 { 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,7 +91,10 @@ 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) {
|
|
@@ -93,14 +138,26 @@ export async function enrollRunnerControlSession(params) {
|
|
|
93
138
|
}).from(providerRunners).innerJoin(provisionerTokens, eq(provisionerTokens.id, providerRunners.provisionerId)).where(and(eq(providerRunners.id, params.runnerInstanceId), eq(providerRunners.provisionerId, params.provisionerId)));
|
|
94
139
|
if (!current) throw new RunnerControlSessionInvalidError();
|
|
95
140
|
if (current.intendedReservationId) await tx.execute(sql`select pg_advisory_xact_lock(hashtext(${`runners_assignment:${params.provisionerId}:${current.intendedReservationId}`}))`);
|
|
96
|
-
|
|
141
|
+
// Provider reports may populate reservationId before the assignment commits. assignedAt is
|
|
142
|
+
// written by the assignment transaction, so keep the guard on that write boundary.
|
|
143
|
+
const [metadataUpdated] = await tx.update(providerRunners).set({
|
|
97
144
|
labels: sanitizeRunnerLabels(params.labels, {
|
|
98
145
|
scope: current.provisionerScope,
|
|
99
146
|
source: 'runner control enrollment'
|
|
100
147
|
}),
|
|
101
148
|
providerKind: params.providerKind,
|
|
102
149
|
protocolVersion: params.protocolVersion,
|
|
103
|
-
capabilities: params.capabilities ?? null
|
|
150
|
+
capabilities: params.capabilities ?? null
|
|
151
|
+
}).where(and(eq(providerRunners.id, params.runnerInstanceId), eq(providerRunners.provisionerId, params.provisionerId), isNull(providerRunners.assignedAt), notInArray(providerRunners.state, [
|
|
152
|
+
...terminalStates
|
|
153
|
+
]))).returning({
|
|
154
|
+
id: providerRunners.id
|
|
155
|
+
});
|
|
156
|
+
if (!metadataUpdated) logger().debug({
|
|
157
|
+
runnerInstanceId: params.runnerInstanceId,
|
|
158
|
+
provisionerId: params.provisionerId
|
|
159
|
+
}, 'Runner enrollment metadata update skipped for assigned or terminal runner');
|
|
160
|
+
const [updated] = await tx.update(providerRunners).set({
|
|
104
161
|
state: 'running',
|
|
105
162
|
reportedAt: sql`now()`,
|
|
106
163
|
updatedAt: sql`now()`
|
|
@@ -126,7 +183,8 @@ export async function enrollRunnerControlSession(params) {
|
|
|
126
183
|
return await issueRunnerActivationTokenTx(promotionTx, {
|
|
127
184
|
runnerInstanceId: params.runnerInstanceId,
|
|
128
185
|
provisionerId: params.provisionerId,
|
|
129
|
-
ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS
|
|
186
|
+
ttlSeconds: config.RUNNER_ACTIVATION_TOKEN_TTL_SECONDS,
|
|
187
|
+
surface: 'enrollment'
|
|
130
188
|
});
|
|
131
189
|
});
|
|
132
190
|
} catch (error) {
|
|
@@ -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 const [updated] = 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 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","updated","source","protocolVersion","capabilities","updatedAt","updateRunnerControlSessionLastSeen","promotionTx","runnerInstanceIds","RUNNER_ACTIVATION_TOKEN_TTL_SECONDS","error","expectedFailureReason","getRunnerReservationPromotionFailureReason","details","err","debug","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 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 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 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 surface: 'enrollment',\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","validateRunnerReservationCapacityTx","terminalStates","provisionerTokens","runnerBootstrapTokens","runnerControlSessions","providerRunners","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","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","surface","error","expectedFailureReason","getRunnerReservationPromotionFailureReason","details","err","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,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/runner-instances.ts"],"sourcesContent":["import type {RunnerInstance, RunnerInstanceState} from '#core/entities/runner-instance.js';\nimport {\n attachRunnerInstanceProviderId as attachRunnerInstanceProviderIdDb,\n isTerminalState,\n listActiveRunnerInstances,\n listActiveRunningJobExecutions,\n type RunnerInstanceReportEvent,\n reconcileRunnerInstances as reconcileRunnerInstancesDb,\n reportRunnerInstances as reportRunnerInstancesDb,\n} from '#db/index.js';\nimport type {\n ActiveRunningJobExecution,\n RunnerInstanceBoundJobExecution,\n} from '#db/job-executions.js';\nimport {\n providerRunnerAbsentTerminatedCount,\n providerRunnerReconcileCallCount,\n providerRunnerReportCount,\n providerRunnerTerminateIntentHonoredCount,\n providerRunnerTerminateIntentIssuedCount,\n reservationReleasedCount,\n} from '#metrics/instance.js';\nimport {config} from '../config.js';\n\nexport interface ReportRunnerInstancesParams {\n scope: 'installation' | 'workspace';\n workspaceId: string | null;\n provisionerId: string;\n events: RunnerInstanceReportEvent[];\n}\n\nexport function attachRunnerInstanceProviderId(params: {\n runnerInstanceId: string;\n provisionerId: string;\n providerRunnerId: string;\n}): Promise<boolean> {\n return attachRunnerInstanceProviderIdDb(params);\n}\n\nexport interface ReportRunnerInstancesResult {\n accepted: number;\n reservationsReleased: number;\n}\n\nexport interface ReconcileRunnerInstancesParams {\n workspaceId: string | null;\n provisionerId: string;\n observedRunnerInstanceIds: string[];\n}\n\nexport type ReconcileDesiredIntent = 'keep' | 'terminate';\ntype ReconcileDesiredIntentReason = 'job-cancelled' | 'terminal-state';\n\nexport interface ReconciledBoundJobExecution {\n jobId: string;\n jobExecutionId: string;\n workflowRunAttemptId: string;\n lastHeartbeatAt: Date;\n cancellationRequestedAt: Date | null;\n}\n\nexport interface ReconciledRunnerInstance {\n providerRunnerId: string;\n state: RunnerInstanceState | null;\n reservationId: string | null;\n runnerSessionId: string | null;\n boundJobExecution: ReconciledBoundJobExecution | null;\n desiredIntent: ReconcileDesiredIntent;\n desiredIntentReason: ReconcileDesiredIntentReason | null;\n}\n\nexport interface ReconcileRunnerInstancesResult {\n runners: ReconciledRunnerInstance[];\n terminatedAbsentRunnerInstanceIds: string[];\n}\n\nexport type ActiveRunnerState = 'starting' | 'running' | 'stopping' | 'busy';\n\nexport interface ActiveRunner {\n runnerSessionId: string | null;\n providerRunnerId: string | null;\n provisionerId: string | null;\n state: ActiveRunnerState;\n labels: string[];\n templateKey: string | null;\n providerKind: string | null;\n jobId: string | null;\n workflowRunAttemptId: string | null;\n projectId: string | null;\n reportedAt: Date | null;\n lastHeartbeatAt: Date | null;\n}\n\nexport async function reportRunnerInstances(\n params: ReportRunnerInstancesParams,\n): Promise<ReportRunnerInstancesResult> {\n const result = await reportRunnerInstancesDb(params);\n\n for (const event of params.events) {\n providerRunnerReportCount.add(1, {state: event.state});\n }\n for (const intent of result.terminateIntentsHonored) {\n providerRunnerTerminateIntentHonoredCount.add(1, {reason: intent.reason});\n }\n if (result.reservationsReleased > 0) reservationReleasedCount.add(result.reservationsReleased);\n\n return result;\n}\n\nexport async function reconcileRunnerInstances(\n params: ReconcileRunnerInstancesParams,\n): Promise<ReconcileRunnerInstancesResult> {\n const result = await reconcileRunnerInstancesDb({\n ...params,\n terminateGraceSeconds: config.RUNNER_RECONCILE_TERMINATE_GRACE_SECONDS,\n });\n\n if (result.reservationsReleased > 0) reservationReleasedCount.add(result.reservationsReleased);\n providerRunnerReconcileCallCount.add(1);\n if (result.absentIds.length > 0) providerRunnerAbsentTerminatedCount.add(result.absentIds.length);\n\n const runners = reconcileRunnerInstancesFromDbResult({\n observedRunnerInstanceIds: params.observedRunnerInstanceIds,\n observedRows: result.observedRows,\n boundJobExecutionsByRunnerInstanceId: result.boundJobExecutionsByRunnerInstanceId,\n });\n for (const runner of runners) {\n if (runner.desiredIntentReason) {\n providerRunnerTerminateIntentIssuedCount.add(1, {\n surface: 'reconcile',\n reason: runner.desiredIntentReason,\n });\n }\n }\n\n return {\n runners,\n terminatedAbsentRunnerInstanceIds: result.absentIds,\n };\n}\n\nexport function reconcileRunnerInstancesFromDbResult(params: {\n observedRunnerInstanceIds: string[];\n observedRows: RunnerInstance[];\n boundJobExecutionsByRunnerInstanceId: Map<string, RunnerInstanceBoundJobExecution>;\n}): ReconciledRunnerInstance[] {\n const rowsByRunnerInstanceId = new Map(\n params.observedRows.map((row) => [row.providerRunnerId, row]),\n );\n\n return params.observedRunnerInstanceIds.map((providerRunnerId) => {\n const row = rowsByRunnerInstanceId.get(providerRunnerId);\n const boundJobExecution = params.boundJobExecutionsByRunnerInstanceId.get(providerRunnerId);\n\n const desiredIntentReason = getDesiredIntentReason(row, boundJobExecution);\n\n return {\n providerRunnerId,\n state: row?.state ?? null,\n reservationId: row?.reservationId ?? null,\n runnerSessionId: row?.runnerSessionId ?? null,\n boundJobExecution: boundJobExecution\n ? toReconciledBoundJobExecution(boundJobExecution)\n : null,\n desiredIntent: desiredIntentReason ? 'terminate' : 'keep',\n desiredIntentReason,\n };\n });\n}\n\nexport async function listActiveRunners(params: {workspaceId: string}): Promise<ActiveRunner[]> {\n const [providerRunnerRows, jobExecutionRows] = await Promise.all([\n listActiveRunnerInstances({\n workspaceId: params.workspaceId,\n windowSeconds: config.RUNNER_ACTIVE_WINDOW_SECONDS,\n }),\n listActiveRunningJobExecutions({\n workspaceId: params.workspaceId,\n windowSeconds: config.RUNNER_ACTIVE_WINDOW_SECONDS,\n }),\n ]);\n\n return mergeActiveRunners(providerRunnerRows, jobExecutionRows);\n}\n\nfunction toReconciledBoundJobExecution(\n jobExecution: RunnerInstanceBoundJobExecution,\n): ReconciledBoundJobExecution {\n return {\n jobId: jobExecution.jobId,\n jobExecutionId: jobExecution.jobExecutionId,\n workflowRunAttemptId: jobExecution.workflowRunAttemptId,\n lastHeartbeatAt: jobExecution.lastHeartbeatAt,\n cancellationRequestedAt: jobExecution.cancellationRequestedAt,\n };\n}\n\nexport function desiredIntent(\n row: RunnerInstance | undefined,\n boundJobExecution: RunnerInstanceBoundJobExecution | undefined,\n): ReconcileDesiredIntent {\n return getDesiredIntentReason(row, boundJobExecution) ? 'terminate' : 'keep';\n}\n\nfunction getDesiredIntentReason(\n row: RunnerInstance | undefined,\n boundJobExecution: RunnerInstanceBoundJobExecution | undefined,\n): ReconcileDesiredIntentReason | null {\n if (!row) return null;\n if (isTerminalState(row.state)) return 'terminal-state';\n if (boundJobExecution?.cancellationRequestedAt) return 'job-cancelled';\n return null;\n}\n\nfunction mergeActiveRunners(\n providerRunners: RunnerInstance[],\n jobExecutions: ActiveRunningJobExecution[],\n): ActiveRunner[] {\n const jobExecutionsByRunnerSessionId = new Map<string, ActiveRunningJobExecution[]>();\n const jobExecutionsByRunnerInstanceId = new Map<string, ActiveRunningJobExecution[]>();\n for (const jobExecution of jobExecutions) {\n const runnerJobExecutions =\n jobExecutionsByRunnerSessionId.get(jobExecution.runnerSessionId) ?? [];\n runnerJobExecutions.push(jobExecution);\n jobExecutionsByRunnerSessionId.set(jobExecution.runnerSessionId, runnerJobExecutions);\n\n if (jobExecution.provisionerId && jobExecution.providerRunnerId) {\n const key = providerRunnerKey(jobExecution.provisionerId, jobExecution.providerRunnerId);\n const providerRunnerJobExecutions = jobExecutionsByRunnerInstanceId.get(key) ?? [];\n providerRunnerJobExecutions.push(jobExecution);\n jobExecutionsByRunnerInstanceId.set(key, providerRunnerJobExecutions);\n }\n }\n\n const merged: ActiveRunner[] = [];\n const usedJobExecutionIds = new Set<string>();\n\n for (const providerRunner of providerRunners) {\n const providerRunnerJobExecutions =\n jobExecutionsByRunnerInstanceId.get(\n providerRunnerKey(providerRunner.provisionerId, providerRunner.providerRunnerId),\n ) ??\n (providerRunner.runnerSessionId\n ? jobExecutionsByRunnerSessionId.get(providerRunner.runnerSessionId)\n : undefined);\n if (!providerRunnerJobExecutions || providerRunnerJobExecutions.length === 0) {\n merged.push(toActiveRunner(providerRunner, undefined));\n continue;\n }\n\n let emitted = false;\n for (const jobExecution of providerRunnerJobExecutions) {\n if (usedJobExecutionIds.has(jobExecution.jobExecutionId)) continue;\n usedJobExecutionIds.add(jobExecution.jobExecutionId);\n merged.push(toActiveRunner(providerRunner, jobExecution));\n emitted = true;\n }\n if (!emitted) merged.push(toActiveRunner(providerRunner, undefined));\n }\n\n for (const jobExecution of jobExecutions) {\n if (usedJobExecutionIds.has(jobExecution.jobExecutionId)) continue;\n merged.push(toActiveRunner(undefined, jobExecution));\n }\n\n return merged.sort(compareActiveRunners);\n}\n\nfunction providerRunnerKey(provisionerId: string, providerRunnerId: string): string {\n return `${provisionerId}:${providerRunnerId}`;\n}\n\nfunction toActiveRunner(\n providerRunner: RunnerInstance | undefined,\n jobExecution: ActiveRunningJobExecution | undefined,\n): ActiveRunner {\n return {\n runnerSessionId: providerRunner?.runnerSessionId ?? jobExecution?.runnerSessionId ?? null,\n providerRunnerId: providerRunner?.providerRunnerId ?? jobExecution?.providerRunnerId ?? null,\n provisionerId: providerRunner?.provisionerId ?? jobExecution?.provisionerId ?? null,\n state: jobExecution ? 'busy' : toActiveRunnerState(providerRunner?.state ?? 'running'),\n labels: providerRunner?.labels ?? jobExecution?.runnerLabels ?? [],\n templateKey: providerRunner?.templateKey ?? null,\n providerKind: providerRunner?.providerKind ?? null,\n jobId: jobExecution?.jobId ?? null,\n workflowRunAttemptId: jobExecution?.workflowRunAttemptId ?? null,\n projectId: jobExecution?.projectId ?? null,\n reportedAt: providerRunner?.reportedAt ?? null,\n lastHeartbeatAt: jobExecution?.lastHeartbeatAt ?? null,\n };\n}\n\nfunction toActiveRunnerState(state: RunnerInstanceState): ActiveRunnerState {\n if (state === 'starting' || state === 'stopping') return state;\n return 'running';\n}\n\nfunction compareActiveRunners(a: ActiveRunner, b: ActiveRunner): number {\n const aTime = Math.max(a.lastHeartbeatAt?.getTime() ?? 0, a.reportedAt?.getTime() ?? 0);\n const bTime = Math.max(b.lastHeartbeatAt?.getTime() ?? 0, b.reportedAt?.getTime() ?? 0);\n return bTime - aTime;\n}\n"],"names":["attachRunnerInstanceProviderId","attachRunnerInstanceProviderIdDb","isTerminalState","listActiveRunnerInstances","listActiveRunningJobExecutions","reconcileRunnerInstances","reconcileRunnerInstancesDb","reportRunnerInstances","reportRunnerInstancesDb","providerRunnerAbsentTerminatedCount","providerRunnerReconcileCallCount","providerRunnerReportCount","providerRunnerTerminateIntentHonoredCount","providerRunnerTerminateIntentIssuedCount","reservationReleasedCount","config","params","result","event","events","add","state","intent","terminateIntentsHonored","reason","reservationsReleased","terminateGraceSeconds","RUNNER_RECONCILE_TERMINATE_GRACE_SECONDS","absentIds","length","runners","reconcileRunnerInstancesFromDbResult","observedRunnerInstanceIds","observedRows","boundJobExecutionsByRunnerInstanceId","runner","desiredIntentReason","surface","terminatedAbsentRunnerInstanceIds","rowsByRunnerInstanceId","Map","map","row","providerRunnerId","get","boundJobExecution","getDesiredIntentReason","reservationId","runnerSessionId","toReconciledBoundJobExecution","desiredIntent","listActiveRunners","providerRunnerRows","jobExecutionRows","Promise","all","workspaceId","windowSeconds","RUNNER_ACTIVE_WINDOW_SECONDS","mergeActiveRunners","jobExecution","jobId","jobExecutionId","workflowRunAttemptId","lastHeartbeatAt","cancellationRequestedAt","providerRunners","jobExecutions","jobExecutionsByRunnerSessionId","jobExecutionsByRunnerInstanceId","runnerJobExecutions","push","set","provisionerId","key","providerRunnerKey","providerRunnerJobExecutions","merged","usedJobExecutionIds","Set","providerRunner","undefined","toActiveRunner","emitted","has","sort","compareActiveRunners","toActiveRunnerState","labels","runnerLabels","templateKey","providerKind","projectId","reportedAt","a","b","aTime","Math","max","getTime","bTime"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/runner-instances.ts"],"sourcesContent":["import type {RunnerInstance, RunnerInstanceState} from '#core/entities/runner-instance.js';\nimport {\n attachRunnerInstanceProviderId as attachRunnerInstanceProviderIdDb,\n isTerminalState,\n listActiveRunnerInstances,\n listActiveRunningJobExecutions,\n type RunnerInstanceReportEvent,\n reconcileRunnerInstances as reconcileRunnerInstancesDb,\n reportRunnerInstances as reportRunnerInstancesDb,\n} from '#db/index.js';\nimport type {\n ActiveRunningJobExecution,\n RunnerInstanceBoundJobExecution,\n} from '#db/job-executions.js';\nimport {\n providerRunnerAbsentTerminatedCount,\n providerRunnerReconcileCallCount,\n providerRunnerReportCount,\n providerRunnerTerminateIntentHonoredCount,\n providerRunnerTerminateIntentIssuedCount,\n reservationReleasedCount,\n} from '#metrics/instance.js';\nimport {config} from '../config.js';\n\nexport interface ReportRunnerInstancesParams {\n scope: 'installation' | 'workspace';\n workspaceId: string | null;\n provisionerId: string;\n events: RunnerInstanceReportEvent[];\n}\n\nexport function attachRunnerInstanceProviderId(params: {\n runnerInstanceId: string;\n provisionerId: string;\n providerRunnerId: string;\n}): Promise<boolean> {\n return attachRunnerInstanceProviderIdDb(params);\n}\n\nexport interface ReportRunnerInstancesResult {\n accepted: number;\n reservationsReleased: number;\n}\n\nexport interface ReconcileRunnerInstancesParams {\n workspaceId: string | null;\n provisionerId: string;\n observedRunnerInstanceIds: string[];\n}\n\nexport type ReconcileDesiredIntent = 'keep' | 'terminate';\ntype ReconcileDesiredIntentReason = 'job-cancelled' | 'terminal-state';\n\nexport interface ReconciledBoundJobExecution {\n jobId: string;\n jobExecutionId: string;\n workflowRunAttemptId: string;\n lastHeartbeatAt: Date;\n cancellationRequestedAt: Date | null;\n}\n\nexport interface ReconciledRunnerInstance {\n providerRunnerId: string;\n state: RunnerInstanceState | null;\n intendedReservationId: string | null;\n reservationId: string | null;\n runnerSessionId: string | null;\n boundJobExecution: ReconciledBoundJobExecution | null;\n desiredIntent: ReconcileDesiredIntent;\n desiredIntentReason: ReconcileDesiredIntentReason | null;\n}\n\nexport interface ReconcileRunnerInstancesResult {\n runners: ReconciledRunnerInstance[];\n terminatedAbsentRunnerInstanceIds: string[];\n}\n\nexport type ActiveRunnerState = 'starting' | 'running' | 'stopping' | 'busy';\n\nexport interface ActiveRunner {\n runnerSessionId: string | null;\n providerRunnerId: string | null;\n provisionerId: string | null;\n state: ActiveRunnerState;\n labels: string[];\n templateKey: string | null;\n providerKind: string | null;\n jobId: string | null;\n workflowRunAttemptId: string | null;\n projectId: string | null;\n reportedAt: Date | null;\n lastHeartbeatAt: Date | null;\n}\n\nexport async function reportRunnerInstances(\n params: ReportRunnerInstancesParams,\n): Promise<ReportRunnerInstancesResult> {\n const result = await reportRunnerInstancesDb(params);\n\n for (const event of params.events) {\n providerRunnerReportCount.add(1, {state: event.state});\n }\n for (const intent of result.terminateIntentsHonored) {\n providerRunnerTerminateIntentHonoredCount.add(1, {reason: intent.reason});\n }\n if (result.reservationsReleased > 0) reservationReleasedCount.add(result.reservationsReleased);\n\n return result;\n}\n\nexport async function reconcileRunnerInstances(\n params: ReconcileRunnerInstancesParams,\n): Promise<ReconcileRunnerInstancesResult> {\n const result = await reconcileRunnerInstancesDb({\n ...params,\n terminateGraceSeconds: config.RUNNER_RECONCILE_TERMINATE_GRACE_SECONDS,\n });\n\n if (result.reservationsReleased > 0) reservationReleasedCount.add(result.reservationsReleased);\n providerRunnerReconcileCallCount.add(1);\n if (result.absentIds.length > 0) providerRunnerAbsentTerminatedCount.add(result.absentIds.length);\n\n const runners = reconcileRunnerInstancesFromDbResult({\n observedRunnerInstanceIds: params.observedRunnerInstanceIds,\n observedRows: result.observedRows,\n boundJobExecutionsByRunnerInstanceId: result.boundJobExecutionsByRunnerInstanceId,\n });\n for (const runner of runners) {\n if (runner.desiredIntentReason) {\n providerRunnerTerminateIntentIssuedCount.add(1, {\n surface: 'reconcile',\n reason: runner.desiredIntentReason,\n });\n }\n }\n\n return {\n runners,\n terminatedAbsentRunnerInstanceIds: result.absentIds,\n };\n}\n\nexport function reconcileRunnerInstancesFromDbResult(params: {\n observedRunnerInstanceIds: string[];\n observedRows: RunnerInstance[];\n boundJobExecutionsByRunnerInstanceId: Map<string, RunnerInstanceBoundJobExecution>;\n}): ReconciledRunnerInstance[] {\n const rowsByRunnerInstanceId = new Map(\n params.observedRows.map((row) => [row.providerRunnerId, row]),\n );\n\n return params.observedRunnerInstanceIds.map((providerRunnerId) => {\n const row = rowsByRunnerInstanceId.get(providerRunnerId);\n const boundJobExecution = params.boundJobExecutionsByRunnerInstanceId.get(providerRunnerId);\n\n const desiredIntentReason = getDesiredIntentReason(row, boundJobExecution);\n\n return {\n providerRunnerId,\n state: row?.state ?? null,\n intendedReservationId: row?.intendedReservationId ?? null,\n reservationId: row?.reservationId ?? null,\n runnerSessionId: row?.runnerSessionId ?? null,\n boundJobExecution: boundJobExecution\n ? toReconciledBoundJobExecution(boundJobExecution)\n : null,\n desiredIntent: desiredIntentReason ? 'terminate' : 'keep',\n desiredIntentReason,\n };\n });\n}\n\nexport async function listActiveRunners(params: {workspaceId: string}): Promise<ActiveRunner[]> {\n const [providerRunnerRows, jobExecutionRows] = await Promise.all([\n listActiveRunnerInstances({\n workspaceId: params.workspaceId,\n windowSeconds: config.RUNNER_ACTIVE_WINDOW_SECONDS,\n }),\n listActiveRunningJobExecutions({\n workspaceId: params.workspaceId,\n windowSeconds: config.RUNNER_ACTIVE_WINDOW_SECONDS,\n }),\n ]);\n\n return mergeActiveRunners(providerRunnerRows, jobExecutionRows);\n}\n\nfunction toReconciledBoundJobExecution(\n jobExecution: RunnerInstanceBoundJobExecution,\n): ReconciledBoundJobExecution {\n return {\n jobId: jobExecution.jobId,\n jobExecutionId: jobExecution.jobExecutionId,\n workflowRunAttemptId: jobExecution.workflowRunAttemptId,\n lastHeartbeatAt: jobExecution.lastHeartbeatAt,\n cancellationRequestedAt: jobExecution.cancellationRequestedAt,\n };\n}\n\nexport function desiredIntent(\n row: RunnerInstance | undefined,\n boundJobExecution: RunnerInstanceBoundJobExecution | undefined,\n): ReconcileDesiredIntent {\n return getDesiredIntentReason(row, boundJobExecution) ? 'terminate' : 'keep';\n}\n\nfunction getDesiredIntentReason(\n row: RunnerInstance | undefined,\n boundJobExecution: RunnerInstanceBoundJobExecution | undefined,\n): ReconcileDesiredIntentReason | null {\n if (!row) return null;\n if (isTerminalState(row.state)) return 'terminal-state';\n if (boundJobExecution?.cancellationRequestedAt) return 'job-cancelled';\n return null;\n}\n\nfunction mergeActiveRunners(\n providerRunners: RunnerInstance[],\n jobExecutions: ActiveRunningJobExecution[],\n): ActiveRunner[] {\n const jobExecutionsByRunnerSessionId = new Map<string, ActiveRunningJobExecution[]>();\n const jobExecutionsByRunnerInstanceId = new Map<string, ActiveRunningJobExecution[]>();\n for (const jobExecution of jobExecutions) {\n const runnerJobExecutions =\n jobExecutionsByRunnerSessionId.get(jobExecution.runnerSessionId) ?? [];\n runnerJobExecutions.push(jobExecution);\n jobExecutionsByRunnerSessionId.set(jobExecution.runnerSessionId, runnerJobExecutions);\n\n if (jobExecution.provisionerId && jobExecution.providerRunnerId) {\n const key = providerRunnerKey(jobExecution.provisionerId, jobExecution.providerRunnerId);\n const providerRunnerJobExecutions = jobExecutionsByRunnerInstanceId.get(key) ?? [];\n providerRunnerJobExecutions.push(jobExecution);\n jobExecutionsByRunnerInstanceId.set(key, providerRunnerJobExecutions);\n }\n }\n\n const merged: ActiveRunner[] = [];\n const usedJobExecutionIds = new Set<string>();\n\n for (const providerRunner of providerRunners) {\n const providerRunnerJobExecutions =\n jobExecutionsByRunnerInstanceId.get(\n providerRunnerKey(providerRunner.provisionerId, providerRunner.providerRunnerId),\n ) ??\n (providerRunner.runnerSessionId\n ? jobExecutionsByRunnerSessionId.get(providerRunner.runnerSessionId)\n : undefined);\n if (!providerRunnerJobExecutions || providerRunnerJobExecutions.length === 0) {\n merged.push(toActiveRunner(providerRunner, undefined));\n continue;\n }\n\n let emitted = false;\n for (const jobExecution of providerRunnerJobExecutions) {\n if (usedJobExecutionIds.has(jobExecution.jobExecutionId)) continue;\n usedJobExecutionIds.add(jobExecution.jobExecutionId);\n merged.push(toActiveRunner(providerRunner, jobExecution));\n emitted = true;\n }\n if (!emitted) merged.push(toActiveRunner(providerRunner, undefined));\n }\n\n for (const jobExecution of jobExecutions) {\n if (usedJobExecutionIds.has(jobExecution.jobExecutionId)) continue;\n merged.push(toActiveRunner(undefined, jobExecution));\n }\n\n return merged.sort(compareActiveRunners);\n}\n\nfunction providerRunnerKey(provisionerId: string, providerRunnerId: string): string {\n return `${provisionerId}:${providerRunnerId}`;\n}\n\nfunction toActiveRunner(\n providerRunner: RunnerInstance | undefined,\n jobExecution: ActiveRunningJobExecution | undefined,\n): ActiveRunner {\n return {\n runnerSessionId: providerRunner?.runnerSessionId ?? jobExecution?.runnerSessionId ?? null,\n providerRunnerId: providerRunner?.providerRunnerId ?? jobExecution?.providerRunnerId ?? null,\n provisionerId: providerRunner?.provisionerId ?? jobExecution?.provisionerId ?? null,\n state: jobExecution ? 'busy' : toActiveRunnerState(providerRunner?.state ?? 'running'),\n labels: providerRunner?.labels ?? jobExecution?.runnerLabels ?? [],\n templateKey: providerRunner?.templateKey ?? null,\n providerKind: providerRunner?.providerKind ?? null,\n jobId: jobExecution?.jobId ?? null,\n workflowRunAttemptId: jobExecution?.workflowRunAttemptId ?? null,\n projectId: jobExecution?.projectId ?? null,\n reportedAt: providerRunner?.reportedAt ?? null,\n lastHeartbeatAt: jobExecution?.lastHeartbeatAt ?? null,\n };\n}\n\nfunction toActiveRunnerState(state: RunnerInstanceState): ActiveRunnerState {\n if (state === 'starting' || state === 'stopping') return state;\n return 'running';\n}\n\nfunction compareActiveRunners(a: ActiveRunner, b: ActiveRunner): number {\n const aTime = Math.max(a.lastHeartbeatAt?.getTime() ?? 0, a.reportedAt?.getTime() ?? 0);\n const bTime = Math.max(b.lastHeartbeatAt?.getTime() ?? 0, b.reportedAt?.getTime() ?? 0);\n return bTime - aTime;\n}\n"],"names":["attachRunnerInstanceProviderId","attachRunnerInstanceProviderIdDb","isTerminalState","listActiveRunnerInstances","listActiveRunningJobExecutions","reconcileRunnerInstances","reconcileRunnerInstancesDb","reportRunnerInstances","reportRunnerInstancesDb","providerRunnerAbsentTerminatedCount","providerRunnerReconcileCallCount","providerRunnerReportCount","providerRunnerTerminateIntentHonoredCount","providerRunnerTerminateIntentIssuedCount","reservationReleasedCount","config","params","result","event","events","add","state","intent","terminateIntentsHonored","reason","reservationsReleased","terminateGraceSeconds","RUNNER_RECONCILE_TERMINATE_GRACE_SECONDS","absentIds","length","runners","reconcileRunnerInstancesFromDbResult","observedRunnerInstanceIds","observedRows","boundJobExecutionsByRunnerInstanceId","runner","desiredIntentReason","surface","terminatedAbsentRunnerInstanceIds","rowsByRunnerInstanceId","Map","map","row","providerRunnerId","get","boundJobExecution","getDesiredIntentReason","intendedReservationId","reservationId","runnerSessionId","toReconciledBoundJobExecution","desiredIntent","listActiveRunners","providerRunnerRows","jobExecutionRows","Promise","all","workspaceId","windowSeconds","RUNNER_ACTIVE_WINDOW_SECONDS","mergeActiveRunners","jobExecution","jobId","jobExecutionId","workflowRunAttemptId","lastHeartbeatAt","cancellationRequestedAt","providerRunners","jobExecutions","jobExecutionsByRunnerSessionId","jobExecutionsByRunnerInstanceId","runnerJobExecutions","push","set","provisionerId","key","providerRunnerKey","providerRunnerJobExecutions","merged","usedJobExecutionIds","Set","providerRunner","undefined","toActiveRunner","emitted","has","sort","compareActiveRunners","toActiveRunnerState","labels","runnerLabels","templateKey","providerKind","projectId","reportedAt","a","b","aTime","Math","max","getTime","bTime"],"mappings":"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"}
|
package/dist/db/db.d.ts
CHANGED
|
@@ -614,6 +614,23 @@ export declare const schema: {
|
|
|
614
614
|
identity: undefined;
|
|
615
615
|
generated: undefined;
|
|
616
616
|
}, {}, {}>;
|
|
617
|
+
launchKind: import("drizzle-orm/pg-core").PgColumn<{
|
|
618
|
+
name: "launch_kind";
|
|
619
|
+
tableName: "runner_instances";
|
|
620
|
+
dataType: "string";
|
|
621
|
+
columnType: "PgEnumColumn";
|
|
622
|
+
data: "demand" | "manual" | "warm";
|
|
623
|
+
driverParam: string;
|
|
624
|
+
notNull: true;
|
|
625
|
+
hasDefault: true;
|
|
626
|
+
isPrimaryKey: false;
|
|
627
|
+
isAutoincrement: false;
|
|
628
|
+
hasRuntimeDefault: false;
|
|
629
|
+
enumValues: ["demand", "warm", "manual"];
|
|
630
|
+
baseColumn: never;
|
|
631
|
+
identity: undefined;
|
|
632
|
+
generated: undefined;
|
|
633
|
+
}, {}, {}>;
|
|
617
634
|
assignedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
618
635
|
name: "assigned_at";
|
|
619
636
|
tableName: "runner_instances";
|
|
@@ -1675,6 +1692,23 @@ export declare const schema: {
|
|
|
1675
1692
|
identity: undefined;
|
|
1676
1693
|
generated: undefined;
|
|
1677
1694
|
}, {}, {}>;
|
|
1695
|
+
kind: import("drizzle-orm/pg-core").PgColumn<{
|
|
1696
|
+
name: "kind";
|
|
1697
|
+
tableName: "reservations";
|
|
1698
|
+
dataType: "string";
|
|
1699
|
+
columnType: "PgEnumColumn";
|
|
1700
|
+
data: "bound" | "launch";
|
|
1701
|
+
driverParam: string;
|
|
1702
|
+
notNull: true;
|
|
1703
|
+
hasDefault: true;
|
|
1704
|
+
isPrimaryKey: false;
|
|
1705
|
+
isAutoincrement: false;
|
|
1706
|
+
hasRuntimeDefault: false;
|
|
1707
|
+
enumValues: ["bound", "launch"];
|
|
1708
|
+
baseColumn: never;
|
|
1709
|
+
identity: undefined;
|
|
1710
|
+
generated: undefined;
|
|
1711
|
+
}, {}, {}>;
|
|
1678
1712
|
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
1679
1713
|
name: "created_at";
|
|
1680
1714
|
tableName: "reservations";
|
|
@@ -3835,6 +3869,23 @@ export declare function db(): NodePgDatabase<{
|
|
|
3835
3869
|
identity: undefined;
|
|
3836
3870
|
generated: undefined;
|
|
3837
3871
|
}, {}, {}>;
|
|
3872
|
+
launchKind: import("drizzle-orm/pg-core").PgColumn<{
|
|
3873
|
+
name: "launch_kind";
|
|
3874
|
+
tableName: "runner_instances";
|
|
3875
|
+
dataType: "string";
|
|
3876
|
+
columnType: "PgEnumColumn";
|
|
3877
|
+
data: "demand" | "manual" | "warm";
|
|
3878
|
+
driverParam: string;
|
|
3879
|
+
notNull: true;
|
|
3880
|
+
hasDefault: true;
|
|
3881
|
+
isPrimaryKey: false;
|
|
3882
|
+
isAutoincrement: false;
|
|
3883
|
+
hasRuntimeDefault: false;
|
|
3884
|
+
enumValues: ["demand", "warm", "manual"];
|
|
3885
|
+
baseColumn: never;
|
|
3886
|
+
identity: undefined;
|
|
3887
|
+
generated: undefined;
|
|
3888
|
+
}, {}, {}>;
|
|
3838
3889
|
assignedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
3839
3890
|
name: "assigned_at";
|
|
3840
3891
|
tableName: "runner_instances";
|
|
@@ -4896,6 +4947,23 @@ export declare function db(): NodePgDatabase<{
|
|
|
4896
4947
|
identity: undefined;
|
|
4897
4948
|
generated: undefined;
|
|
4898
4949
|
}, {}, {}>;
|
|
4950
|
+
kind: import("drizzle-orm/pg-core").PgColumn<{
|
|
4951
|
+
name: "kind";
|
|
4952
|
+
tableName: "reservations";
|
|
4953
|
+
dataType: "string";
|
|
4954
|
+
columnType: "PgEnumColumn";
|
|
4955
|
+
data: "bound" | "launch";
|
|
4956
|
+
driverParam: string;
|
|
4957
|
+
notNull: true;
|
|
4958
|
+
hasDefault: true;
|
|
4959
|
+
isPrimaryKey: false;
|
|
4960
|
+
isAutoincrement: false;
|
|
4961
|
+
hasRuntimeDefault: false;
|
|
4962
|
+
enumValues: ["bound", "launch"];
|
|
4963
|
+
baseColumn: never;
|
|
4964
|
+
identity: undefined;
|
|
4965
|
+
generated: undefined;
|
|
4966
|
+
}, {}, {}>;
|
|
4899
4967
|
createdAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
4900
4968
|
name: "created_at";
|
|
4901
4969
|
tableName: "reservations";
|
package/dist/db/db.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAiBnE,eAAO,MAAM,MAAM
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAiBnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBlB,CAAC;AAIF,wBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGjB;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED,MAAM,MAAM,EAAE,GAAG,UAAU,CAAC,UAAU,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ephemeral-registration-tokens.d.ts","sourceRoot":"","sources":["../../src/db/ephemeral-registration-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,gDAAgD,CAAC;AAuB/F,MAAM,WAAW,sCAAsC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,yCAAyC;IACxD,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,4CAA4C;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,yCAAyC,EAAE,CAAC;CACnD;AAED,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,sCAAsC,GAC7C,OAAO,CAAC,0BAA0B,CAAC,CAiDrC;AAED,wBAAsB,sCAAsC,CAC1D,MAAM,EAAE,4CAA4C,GACnD,OAAO,CAAC,0BAA0B,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"ephemeral-registration-tokens.d.ts","sourceRoot":"","sources":["../../src/db/ephemeral-registration-tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,gDAAgD,CAAC;AAuB/F,MAAM,WAAW,sCAAsC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,yCAAyC;IACxD,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,4CAA4C;IAC3D,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,IAAI,CAAC;IAChB,IAAI,EAAE,yCAAyC,EAAE,CAAC;CACnD;AAED,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,sCAAsC,GAC7C,OAAO,CAAC,0BAA0B,CAAC,CAiDrC;AAED,wBAAsB,sCAAsC,CAC1D,MAAM,EAAE,4CAA4C,GACnD,OAAO,CAAC,0BAA0B,EAAE,CAAC,CAqGvC;AAED,wBAAsB,uCAAuC,CAC3D,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAUjD;AAED,MAAM,WAAW,8CAA8C;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,wCAAwC,CAC5D,MAAM,EAAE,8CAA8C,GACrD,OAAO,CAAC,MAAM,CAAC,CAqBjB;AAED,wBAAsB,0CAA0C,CAAC,MAAM,EAAE;IACvE,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gBAAgB,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB,qDAiGA"}
|
|
@@ -58,7 +58,7 @@ export async function createEphemeralRegistrationTokensBatch(params) {
|
|
|
58
58
|
const [reservation] = await tx.select({
|
|
59
59
|
count: reservations.count,
|
|
60
60
|
isExpired: sql`${reservations.expiresAt} <= now()`
|
|
61
|
-
}).from(reservations).where(and(eq(reservations.id, params.reservationId), eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId))).limit(1);
|
|
61
|
+
}).from(reservations).where(and(eq(reservations.id, params.reservationId), eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId), eq(reservations.kind, 'launch'))).limit(1);
|
|
62
62
|
if (!reservation) throw new ReservationNotFoundError(params.reservationId);
|
|
63
63
|
if (reservation.isExpired) throw new ReservationExpiredError(params.reservationId);
|
|
64
64
|
if (params.rows.length > reservation.count) {
|