@shipfox/api-runners 12.5.0 → 12.7.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.
Files changed (39) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +15 -0
  3. package/dist/db/job-executions.d.ts +3 -0
  4. package/dist/db/job-executions.d.ts.map +1 -1
  5. package/dist/db/job-executions.js +23 -1
  6. package/dist/db/job-executions.js.map +1 -1
  7. package/dist/db/provisioner-tokens.d.ts.map +1 -1
  8. package/dist/db/provisioner-tokens.js +14 -2
  9. package/dist/db/provisioner-tokens.js.map +1 -1
  10. package/dist/db/reservations.d.ts +10 -0
  11. package/dist/db/reservations.d.ts.map +1 -1
  12. package/dist/db/reservations.js +137 -17
  13. package/dist/db/reservations.js.map +1 -1
  14. package/dist/db/runner-assignments.d.ts.map +1 -1
  15. package/dist/db/runner-assignments.js +8 -5
  16. package/dist/db/runner-assignments.js.map +1 -1
  17. package/dist/db/runner-instances.d.ts +0 -1
  18. package/dist/db/runner-instances.d.ts.map +1 -1
  19. package/dist/db/runner-instances.js +85 -100
  20. package/dist/db/runner-instances.js.map +1 -1
  21. package/dist/db/runner-states.d.ts +3 -1
  22. package/dist/db/runner-states.d.ts.map +1 -1
  23. package/dist/db/runner-states.js +6 -4
  24. package/dist/db/runner-states.js.map +1 -1
  25. package/dist/tsconfig.test.tsbuildinfo +1 -1
  26. package/package.json +2 -2
  27. package/src/db/job-executions.test.ts +119 -0
  28. package/src/db/job-executions.ts +24 -2
  29. package/src/db/provisioner-tokens.test.ts +19 -0
  30. package/src/db/provisioner-tokens.ts +13 -2
  31. package/src/db/reservations.test.ts +138 -0
  32. package/src/db/reservations.ts +311 -35
  33. package/src/db/runner-assignments.test.ts +20 -0
  34. package/src/db/runner-assignments.ts +6 -7
  35. package/src/db/runner-instances.test.ts +250 -15
  36. package/src/db/runner-instances.ts +136 -198
  37. package/src/db/runner-states.test.ts +16 -0
  38. package/src/db/runner-states.ts +9 -4
  39. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,5 +1,5 @@
1
1
  import { canonicalizeLabels } from '@shipfox/runner-labels';
2
- import { and, arrayContains, asc, eq, exists, gt, inArray, isNotNull, isNull, lt, notExists, notInArray, or, sql } from 'drizzle-orm';
2
+ import { and, arrayContains, asc, eq, exists, gt, inArray, isNotNull, isNull, lt, lte, notExists, notInArray, or, sql } from 'drizzle-orm';
3
3
  import { recordProviderRunnerActivationOutcome } from '#metrics/instance.js';
4
4
  import { db } from './db.js';
5
5
  import { lockRunnerReservationAdvisoryKeysTx } from './reservation-locks.js';
@@ -11,6 +11,7 @@ import { reservations } from './schema/reservations.js';
11
11
  import { runnerActivationTokens } from './schema/runner-activation-tokens.js';
12
12
  import { runnerControlSessions } from './schema/runner-control-sessions.js';
13
13
  import { providerRunners } from './schema/runner-instances.js';
14
+ import { runningJobExecutions } from './schema/running-job-executions.js';
14
15
  export async function pollDemandAndReserve(params) {
15
16
  const result = await db().transaction(async (tx)=>{
16
17
  return await pollDemandAndReserveTx(tx, params);
@@ -238,9 +239,10 @@ async function listActiveProvisionerReservationRowsTx(tx, params) {
238
239
  const usedRunnerRows = await tx.select({
239
240
  id: providerRunners.id,
240
241
  reservationId: providerRunners.reservationId,
241
- intendedReservationId: providerRunners.intendedReservationId,
242
- state: providerRunners.state
243
- }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), isNull(providerRunners.reservationReleasedAt), or(inArray(providerRunners.reservationId, activeIds), and(inArray(providerRunners.intendedReservationId, activeIds), notInArray(providerRunners.state, [
242
+ intendedReservationId: providerRunners.intendedReservationId
243
+ }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), isNull(providerRunners.reservationReleasedAt), or(and(inArray(providerRunners.reservationId, activeIds), notInArray(providerRunners.state, [
244
+ ...terminalStates
245
+ ])), and(inArray(providerRunners.intendedReservationId, activeIds), notInArray(providerRunners.state, [
244
246
  ...terminalStates
245
247
  ])))));
246
248
  const usedByReservation = new Map();
@@ -248,7 +250,7 @@ async function listActiveProvisionerReservationRowsTx(tx, params) {
248
250
  if (runner.reservationId && activeIdSet.has(runner.reservationId)) {
249
251
  addUsedRunner(usedByReservation, runner.reservationId, runner.id);
250
252
  }
251
- if (runner.intendedReservationId && activeIdSet.has(runner.intendedReservationId) && !terminalStates.includes(runner.state)) {
253
+ if (runner.intendedReservationId && activeIdSet.has(runner.intendedReservationId)) {
252
254
  addUsedRunner(usedByReservation, runner.intendedReservationId, runner.id);
253
255
  }
254
256
  }
@@ -457,22 +459,140 @@ async function deleteReservationsWithCleanupTx(tx, ids, params = {}) {
457
459
  return deleted.length;
458
460
  }
459
461
  export async function releaseReservationUnits(tx, params) {
460
- let released = 0;
462
+ const releaseByReservationId = new Map();
461
463
  for (const release of params.releases){
462
464
  if (release.count <= 0) continue;
463
- const decremented = await tx.update(reservations).set({
464
- count: sql`${reservations.count} - ${release.count}`
465
- }).where(and(eq(reservations.id, release.reservationId), eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId), gt(reservations.count, release.count), gt(reservations.expiresAt, sql`now()`))).returning({
466
- id: reservations.id
465
+ releaseByReservationId.set(release.reservationId, (releaseByReservationId.get(release.reservationId) ?? 0) + release.count);
466
+ }
467
+ const reservationIds = [
468
+ ...releaseByReservationId.keys()
469
+ ];
470
+ if (reservationIds.length === 0) return 0;
471
+ const releaseCount = sql`CASE ${reservations.id}
472
+ ${sql.join([
473
+ ...releaseByReservationId
474
+ ].map(([reservationId, count])=>sql`WHEN ${reservationId} THEN ${count}`), sql` `)}
475
+ ELSE 0
476
+ END`;
477
+ const scope = and(eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId), inArray(reservations.id, reservationIds), gt(reservations.expiresAt, sql`now()`));
478
+ const decremented = await tx.update(reservations).set({
479
+ count: sql`${reservations.count} - ${releaseCount}`
480
+ }).where(and(scope, gt(reservations.count, releaseCount))).returning({
481
+ id: reservations.id
482
+ });
483
+ const releasedFromDecremented = decremented.reduce((total, row)=>total + (releaseByReservationId.get(row.id) ?? 0), 0);
484
+ const decrementedIds = decremented.map((row)=>row.id);
485
+ const deleted = await tx.delete(reservations).where(and(scope, sql`${reservations.count} <= ${releaseCount}`, decrementedIds.length > 0 ? notInArray(reservations.id, decrementedIds) : undefined)).returning({
486
+ count: reservations.count
487
+ });
488
+ const releasedFromDeleted = deleted.reduce((total, row)=>total + row.count, 0);
489
+ return releasedFromDeleted + releasedFromDecremented;
490
+ }
491
+ export async function releaseTerminalRunnerInstanceReservationsByIds(tx, params) {
492
+ if ((params.providerRunnerIds?.length ?? 0) === 0 && (params.runnerInstanceIds?.length ?? 0) === 0) return 0;
493
+ const reservationWorkspacePredicate = params.workspaceId === null ? sql`` : sql`and ${eq(reservations.workspaceId, params.workspaceId)}`;
494
+ const noRunningJobPredicate = notExists(tx.select({
495
+ id: runningJobExecutions.id
496
+ }).from(runningJobExecutions).where(and(eq(runningJobExecutions.provisionerId, params.provisionerId), eq(runningJobExecutions.providerRunnerId, providerRunners.providerRunnerId), params.workspaceId === null ? undefined : eq(runningJobExecutions.workspaceId, params.workspaceId))));
497
+ const reportFreshnessPredicate = params.reportedAtByProviderRunnerId && params.reportedAtByProviderRunnerId.size > 0 ? or(...[
498
+ ...params.reportedAtByProviderRunnerId
499
+ ].map(([providerRunnerId, reportedAt])=>and(eq(providerRunners.providerRunnerId, providerRunnerId), lte(providerRunners.reportedAt, reportedAt)))) : undefined;
500
+ const runnerIdentityPredicate = or(params.providerRunnerIds && params.providerRunnerIds.length > 0 ? inArray(providerRunners.providerRunnerId, params.providerRunnerIds) : undefined, params.runnerInstanceIds && params.runnerInstanceIds.length > 0 ? inArray(providerRunners.id, params.runnerInstanceIds) : undefined);
501
+ // Assignment locks these keys before changing runner links. Acquire them before locking or
502
+ // marking terminal runners so an assignment cannot consume a reservation concurrently with
503
+ // this release.
504
+ const reservationRowsToLock = await tx.select({
505
+ reservationId: providerRunners.reservationId,
506
+ intendedReservationId: providerRunners.intendedReservationId
507
+ }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), runnerIdentityPredicate, params.requireTerminalState === false ? undefined : inArray(providerRunners.state, terminalStates), or(isNotNull(providerRunners.reservationId), isNotNull(providerRunners.intendedReservationId)), isNull(providerRunners.reservationReleasedAt)));
508
+ const reservationIdsToLock = [
509
+ ...new Set(reservationRowsToLock.flatMap((row)=>[
510
+ row.reservationId,
511
+ row.intendedReservationId
512
+ ].filter((reservationId)=>reservationId !== null)))
513
+ ];
514
+ await lockRunnerReservationAdvisoryKeysTx(tx, {
515
+ provisionerId: params.provisionerId,
516
+ reservationIds: reservationIdsToLock
517
+ });
518
+ const rows = await tx.select({
519
+ id: providerRunners.id,
520
+ state: providerRunners.state,
521
+ releaseReservationId: sql`coalesce(
522
+ (select ${reservations.id}
523
+ from ${reservations}
524
+ where ${reservations.id} = ${providerRunners.intendedReservationId}
525
+ and ${reservations.provisionerId} = ${params.provisionerId}
526
+ ${reservationWorkspacePredicate}),
527
+ (select ${reservations.id}
528
+ from ${reservations}
529
+ where ${reservations.id} = ${providerRunners.reservationId}
530
+ and ${reservations.provisionerId} = ${params.provisionerId}
531
+ ${reservationWorkspacePredicate})
532
+ )`,
533
+ releaseReservationWorkspaceId: sql`coalesce(
534
+ (select ${reservations.workspaceId}
535
+ from ${reservations}
536
+ where ${reservations.id} = ${providerRunners.intendedReservationId}
537
+ and ${reservations.provisionerId} = ${params.provisionerId}
538
+ ${reservationWorkspacePredicate}),
539
+ (select ${reservations.workspaceId}
540
+ from ${reservations}
541
+ where ${reservations.id} = ${providerRunners.reservationId}
542
+ and ${reservations.provisionerId} = ${params.provisionerId}
543
+ ${reservationWorkspacePredicate})
544
+ )`
545
+ }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), runnerIdentityPredicate, params.requireTerminalState === false ? undefined : inArray(providerRunners.state, terminalStates), or(isNotNull(providerRunners.reservationId), isNotNull(providerRunners.intendedReservationId)), params.workspaceId === null ? undefined : or(and(eq(providerRunners.workspaceId, params.workspaceId), or(exists(tx.select({
546
+ id: reservations.id
547
+ }).from(reservations).where(and(eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId), eq(reservations.id, providerRunners.reservationId)))), exists(tx.select({
548
+ id: reservations.id
549
+ }).from(reservations).where(and(eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId), eq(reservations.id, providerRunners.intendedReservationId)))))), and(isNull(providerRunners.workspaceId), isNotNull(providerRunners.intendedReservationId), exists(tx.select({
550
+ id: reservations.id
551
+ }).from(reservations).where(and(eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId), eq(reservations.id, providerRunners.intendedReservationId)))))), params.requireUnlinkedSession === false ? undefined : isNull(providerRunners.runnerSessionId), noRunningJobPredicate, reportFreshnessPredicate, isNull(providerRunners.reservationReleasedAt))).for('update');
552
+ if (rows.length === 0) return 0;
553
+ // The lease-finalization path deliberately locks active rows too. If a terminal report is
554
+ // concurrently projecting the runner state, PostgreSQL rechecks this row after the lock and
555
+ // lets cleanup observe the committed terminal state without a cross-module advisory lock.
556
+ const terminalRows = params.requireTerminalState === false ? rows.filter((row)=>terminalStates.some((terminalState)=>terminalState === row.state)) : rows;
557
+ if (terminalRows.length === 0) return 0;
558
+ const updated = await tx.update(providerRunners).set({
559
+ intendedReservationId: null,
560
+ reservationReleasedAt: sql`now()`,
561
+ updatedAt: sql`now()`
562
+ }).where(and(inArray(providerRunners.id, terminalRows.map((row)=>row.id)), params.requireUnlinkedSession === false ? undefined : isNull(providerRunners.runnerSessionId), noRunningJobPredicate, reportFreshnessPredicate, isNull(providerRunners.reservationReleasedAt))).returning({
563
+ id: providerRunners.id
564
+ });
565
+ const releasesByReservationId = new Map();
566
+ const updatedIds = new Set(updated.map((row)=>row.id));
567
+ for (const row of terminalRows){
568
+ if (!updatedIds.has(row.id)) continue;
569
+ if (!row.releaseReservationId || !row.releaseReservationWorkspaceId) continue;
570
+ const key = `${row.releaseReservationWorkspaceId}:${row.releaseReservationId}`;
571
+ const release = releasesByReservationId.get(key) ?? {
572
+ workspaceId: row.releaseReservationWorkspaceId,
573
+ reservationId: row.releaseReservationId,
574
+ count: 0
575
+ };
576
+ release.count += 1;
577
+ releasesByReservationId.set(key, release);
578
+ }
579
+ if (releasesByReservationId.size === 0) return 0;
580
+ const releasesByWorkspaceId = new Map();
581
+ for (const release of releasesByReservationId.values()){
582
+ const releases = releasesByWorkspaceId.get(release.workspaceId) ?? [];
583
+ releases.push({
584
+ reservationId: release.reservationId,
585
+ count: release.count
467
586
  });
468
- if (decremented.length > 0) {
469
- released += release.count;
470
- continue;
471
- }
472
- const deleted = await tx.delete(reservations).where(and(eq(reservations.id, release.reservationId), eq(reservations.workspaceId, params.workspaceId), eq(reservations.provisionerId, params.provisionerId), sql`${reservations.count} <= ${release.count}`, gt(reservations.expiresAt, sql`now()`))).returning({
473
- count: reservations.count
587
+ releasesByWorkspaceId.set(release.workspaceId, releases);
588
+ }
589
+ let released = 0;
590
+ for (const [workspaceId, releases] of releasesByWorkspaceId){
591
+ released += await releaseReservationUnits(tx, {
592
+ workspaceId,
593
+ provisionerId: params.provisionerId,
594
+ releases
474
595
  });
475
- released += deleted.reduce((total, row)=>total + row.count, 0);
476
596
  }
477
597
  return released;
478
598
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/reservations.ts"],"sourcesContent":["import {canonicalizeLabels} from '@shipfox/runner-labels';\nimport {\n and,\n arrayContains,\n asc,\n eq,\n exists,\n gt,\n inArray,\n isNotNull,\n isNull,\n lt,\n notExists,\n notInArray,\n or,\n sql,\n} from 'drizzle-orm';\nimport {recordProviderRunnerActivationOutcome} from '#metrics/instance.js';\nimport type {Tx} from './db.js';\nimport {db} from './db.js';\nimport {lockRunnerReservationAdvisoryKeysTx} from './reservation-locks.js';\nimport {terminalStates} from './runner-states.js';\nimport {pendingJobExecutions} from './schema/pending-job-executions.js';\nimport {provisionerCapabilitySnapshots} from './schema/provisioner-capability-snapshots.js';\nimport {provisionerTokens} from './schema/provisioner-tokens.js';\nimport {reservations} from './schema/reservations.js';\nimport {runnerActivationTokens} from './schema/runner-activation-tokens.js';\nimport {runnerControlSessions} from './schema/runner-control-sessions.js';\nimport {type providerRunnerLaunchKindEnum, providerRunners} from './schema/runner-instances.js';\n\nexport interface ReservationTemplate {\n templateKey: string;\n labels: string[];\n availableSlots: number;\n starting: number;\n running: number;\n}\n\nexport interface DemandStat {\n workspaceId?: string;\n labels: string[];\n queued: number;\n reserved: number;\n oldestQueuedAt: Date;\n}\n\nexport interface ReservationGrant {\n reservationId: string;\n workspaceId?: string;\n labels: string[];\n count: number;\n expiresAt: Date;\n}\n\nexport interface PollDemandAndReserveParams {\n workspaceId: string;\n provisionerId: string;\n maxReservations: number;\n ttlSeconds: number;\n /** Lifetime of the short reservation that gives rebound runners time to activate. */\n activationGraceSeconds?: number;\n templates: ReservationTemplate[];\n capabilityWindowSeconds?: number;\n}\n\nexport interface InstallationPollDemandAndReserveParams {\n provisionerId: string;\n maxReservations: number;\n ttlSeconds: number;\n /** Lifetime of the short reservation that gives rebound runners time to activate. */\n activationGraceSeconds?: number;\n templates: ReservationTemplate[];\n capabilityWindowSeconds: number;\n eligibleWorkspaceIds: ReadonlySet<string>;\n signal?: AbortSignal;\n onReservations?: (reservations: ReservationGrant[]) => void;\n}\n\ntype DemandScope = 'installation' | 'workspace';\n\ninterface IdleRunnerCandidate {\n id: string;\n launchKind: (typeof providerRunnerLaunchKindEnum.enumValues)[number];\n}\n\ninterface BindableRunnerParams {\n provisionerId: string;\n workspaceId: string;\n requiredLabels: string[];\n scope: DemandScope;\n}\n\ninterface IdleRunnerSelectionParams extends BindableRunnerParams {\n count: number;\n}\n\ntype PollDemandAndReserveLockedParams = PollDemandAndReserveParams & {\n scope: DemandScope;\n};\n\ninterface NormalizedTemplate {\n templateKey: string;\n labels: string[];\n remainingSlots: number;\n}\n\ninterface DemandRow {\n requiredLabels: string[];\n queued: number;\n oldestQueuedAt: Date;\n}\n\ninterface NewReservationUnits {\n labels: string[];\n count: number;\n}\n\ninterface PollDemandAndReserveResult {\n stats: DemandStat[];\n /** Only launch reservations are exposed to the provisioner. */\n reservations: ReservationGrant[];\n /** Internal allocation accounting for bound and launch rows together. */\n newlyReservedUnits: NewReservationUnits[];\n}\n\nexport async function pollDemandAndReserve(\n params: PollDemandAndReserveParams,\n): Promise<{stats: DemandStat[]; reservations: ReservationGrant[]}> {\n const result = await db().transaction(async (tx) => {\n return await pollDemandAndReserveTx(tx, params);\n });\n return {stats: result.stats, reservations: result.reservations};\n}\n\nexport async function pollDemandAndReserveTx(\n tx: Tx,\n params: PollDemandAndReserveParams,\n): Promise<PollDemandAndReserveResult> {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext(${params.workspaceId}))`);\n return await pollDemandAndReserveLockedTx(tx, {...params, scope: 'workspace'});\n}\n\nexport async function pollInstallationDemandAndReserve(\n params: InstallationPollDemandAndReserveParams,\n): Promise<{\n stats: DemandStat[];\n reservations: ReservationGrant[];\n newlyReservedCount?: number;\n}> {\n const candidateWorkspaceIds = await listInstallationDemandWorkspaceIds(\n params.eligibleWorkspaceIds,\n );\n const results: PollDemandAndReserveResult[] = [];\n let remainingMaxReservations = params.maxReservations;\n const remainingTemplates = params.templates.map((template) => ({\n ...template,\n labels: [...canonicalizeLabels(template.labels)],\n remainingSlots: template.availableSlots,\n }));\n for (const workspaceId of candidateWorkspaceIds) {\n if (params.signal?.aborted || remainingMaxReservations === 0) break;\n const result = await db().transaction(async (tx) => {\n const lockResult = await tx.execute<{locked: boolean}>(\n sql`select pg_try_advisory_xact_lock(hashtext(${workspaceId})) as locked`,\n );\n const locked = lockResult.rows[0];\n if (!locked?.locked) return {stats: [], reservations: [], newlyReservedUnits: []};\n return await pollDemandAndReserveLockedTx(tx, {\n workspaceId,\n provisionerId: params.provisionerId,\n maxReservations: remainingMaxReservations,\n ttlSeconds: params.ttlSeconds,\n ...(params.activationGraceSeconds !== undefined\n ? {activationGraceSeconds: params.activationGraceSeconds}\n : {}),\n templates: remainingTemplates.map((template) => ({\n ...template,\n availableSlots: template.remainingSlots,\n })),\n capabilityWindowSeconds: params.capabilityWindowSeconds,\n scope: 'installation',\n });\n });\n results.push(result);\n consumeInstallationTemplateSlots(remainingTemplates, result.reservations);\n params.onReservations?.(result.reservations);\n remainingMaxReservations -= result.newlyReservedUnits.reduce(\n (total, reservation) => total + reservation.count,\n 0,\n );\n }\n const newlyReservedCount = results.reduce(\n (total, result) =>\n total +\n result.newlyReservedUnits.reduce((subtotal, reservation) => subtotal + reservation.count, 0),\n 0,\n );\n return {\n stats: results.flatMap((result) => result.stats),\n reservations: results.flatMap((result) => result.reservations),\n ...(newlyReservedCount > 0 ? {newlyReservedCount} : {}),\n };\n}\n\nfunction consumeInstallationTemplateSlots(\n templates: NormalizedTemplate[],\n launchGrants: ReservationGrant[],\n): void {\n // Adopted runners are already included in the running count behind availableSlots.\n // Only units that still need a launch consume advertised template capacity.\n for (const reservation of launchGrants) {\n const satisfyingTemplates = templates\n .filter((template) => isSubset(reservation.labels, template.labels))\n .sort(\n (a, b) => a.labels.length - b.labels.length || a.templateKey.localeCompare(b.templateKey),\n );\n drawSlots(satisfyingTemplates, reservation.count);\n }\n}\n\nasync function pollDemandAndReserveLockedTx(\n tx: Tx,\n params: PollDemandAndReserveLockedParams,\n): Promise<PollDemandAndReserveResult> {\n let demandRows = (\n await tx\n .select({\n requiredLabels: pendingJobExecutions.requiredLabels,\n queued: sql<number>`count(*)::int`,\n oldestQueuedAt: sql<Date | string>`min(${pendingJobExecutions.createdAt})`,\n })\n .from(pendingJobExecutions)\n .where(eq(pendingJobExecutions.workspaceId, params.workspaceId))\n .groupBy(pendingJobExecutions.requiredLabels)\n ).map((row) => ({\n ...row,\n oldestQueuedAt: new Date(row.oldestQueuedAt),\n }));\n if (params.capabilityWindowSeconds !== undefined) {\n const capabilityLabels = await listActiveWorkspaceCapabilityLabelsTx(tx, {\n workspaceId: params.workspaceId,\n windowSeconds: params.capabilityWindowSeconds,\n });\n demandRows = demandRows.filter(\n (demand) => !capabilityLabels.some((labels) => isSubset(demand.requiredLabels, labels)),\n );\n }\n\n const activeReservationRows = await tx\n .select({\n requiredLabels: reservations.requiredLabels,\n reserved: sql<number>`coalesce(sum(${reservations.count}), 0)::int`,\n })\n .from(reservations)\n .where(\n and(eq(reservations.workspaceId, params.workspaceId), gt(reservations.expiresAt, sql`now()`)),\n )\n .groupBy(reservations.requiredLabels);\n\n const reservedByLabels = new Map(\n activeReservationRows.map((row) => [labelKey(row.requiredLabels), row.reserved]),\n );\n const activeProvisionerReservationRows = await listActiveProvisionerReservationRowsTx(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n });\n\n const templates = params.templates.map((template) => ({\n templateKey: template.templateKey,\n labels: [...canonicalizeLabels(template.labels)],\n remainingSlots: template.availableSlots,\n }));\n deductProvisionerReservations(templates, activeProvisionerReservationRows);\n const stats: DemandStat[] = [];\n const grants: ReservationGrant[] = [];\n const newlyReservedUnits: NewReservationUnits[] = [];\n let remainingMaxReservations = params.maxReservations;\n const workspaceIdField =\n params.capabilityWindowSeconds === undefined ? {} : {workspaceId: params.workspaceId};\n\n for (const demand of sortDemandRows(demandRows)) {\n const satisfyingTemplates = templates\n .filter((template) => isSubset(demand.requiredLabels, template.labels))\n .sort(\n (a, b) => a.labels.length - b.labels.length || a.templateKey.localeCompare(b.templateKey),\n );\n\n if (satisfyingTemplates.length === 0) continue;\n\n const reserved = reservedByLabels.get(labelKey(demand.requiredLabels)) ?? 0;\n const unreserved = Math.max(0, demand.queued - reserved);\n const capacity = satisfyingTemplates.reduce(\n (total, template) => total + template.remainingSlots,\n 0,\n );\n const grant = Math.min(unreserved, capacity, remainingMaxReservations);\n let reservedAfterGrant = reserved;\n\n if (grant > 0 && params.maxReservations > 0) {\n const idleRunners = await listIdleRunnerInstancesTx(tx, {\n provisionerId: params.provisionerId,\n requiredLabels: demand.requiredLabels,\n count: grant,\n workspaceId: params.workspaceId,\n scope: params.scope,\n });\n\n remainingMaxReservations -= grant;\n\n const boundCount = idleRunners.length;\n if (boundCount > 0) {\n const [boundReservation] = await tx\n .insert(reservations)\n .values({\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n requiredLabels: demand.requiredLabels,\n count: boundCount,\n kind: 'bound',\n expiresAt: sql`now() + (${params.activationGraceSeconds ?? params.ttlSeconds} || ' seconds')::interval`,\n })\n .returning({id: reservations.id});\n\n if (!boundReservation) throw new Error('Insert returned no rows');\n\n await bindIdleRunnerInstancesTx(tx, {\n provisionerId: params.provisionerId,\n reservationId: boundReservation.id,\n workspaceId: params.workspaceId,\n requiredLabels: demand.requiredLabels,\n scope: params.scope,\n idleRunners,\n });\n }\n\n const launchCount = grant - boundCount;\n drawSlots(satisfyingTemplates, launchCount);\n let launchReservation: {id: string; expiresAt: Date} | undefined;\n if (launchCount > 0) {\n const [inserted] = await tx\n .insert(reservations)\n .values({\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n requiredLabels: demand.requiredLabels,\n count: launchCount,\n kind: 'launch',\n expiresAt: sql`now() + (${params.ttlSeconds} || ' seconds')::interval`,\n })\n .returning({id: reservations.id, expiresAt: reservations.expiresAt});\n\n if (!inserted) throw new Error('Insert returned no rows');\n launchReservation = inserted;\n }\n\n newlyReservedUnits.push({labels: demand.requiredLabels, count: grant});\n reservedAfterGrant += grant;\n if (launchReservation) {\n grants.push({\n reservationId: launchReservation.id,\n ...workspaceIdField,\n labels: demand.requiredLabels,\n count: launchCount,\n expiresAt: launchReservation.expiresAt,\n });\n }\n }\n\n stats.push({\n ...workspaceIdField,\n labels: demand.requiredLabels,\n queued: demand.queued,\n reserved: reservedAfterGrant,\n oldestQueuedAt: demand.oldestQueuedAt,\n });\n }\n\n return {stats, reservations: grants, newlyReservedUnits};\n}\n\nasync function listActiveProvisionerReservationRowsTx(\n tx: Tx,\n params: {workspaceId: string; provisionerId: string},\n): Promise<Array<{requiredLabels: string[]; reserved: number}>> {\n const candidateRows = await tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n );\n const candidateIds = candidateRows.map((row) => row.id);\n if (candidateIds.length === 0) return [];\n\n // Assignment and provider-report transactions use this key before changing runner\n // links. Lock it before counting so an in-flight assignment cannot expose its unit twice.\n await lockRunnerReservationAdvisoryKeysTx(tx, {\n provisionerId: params.provisionerId,\n reservationIds: candidateIds,\n });\n\n const activeRows = await tx\n .select({\n id: reservations.id,\n requiredLabels: reservations.requiredLabels,\n count: reservations.count,\n })\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n )\n .orderBy(asc(reservations.id))\n .for('update');\n if (activeRows.length === 0) return [];\n\n const activeIds = activeRows.map((row) => row.id);\n const activeIdSet = new Set(activeIds);\n const usedRunnerRows = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n intendedReservationId: providerRunners.intendedReservationId,\n state: providerRunners.state,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.reservationReleasedAt),\n or(\n inArray(providerRunners.reservationId, activeIds),\n and(\n inArray(providerRunners.intendedReservationId, activeIds),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n ),\n ),\n );\n const usedByReservation = new Map<string, Set<string>>();\n for (const runner of usedRunnerRows) {\n if (runner.reservationId && activeIdSet.has(runner.reservationId)) {\n addUsedRunner(usedByReservation, runner.reservationId, runner.id);\n }\n if (\n runner.intendedReservationId &&\n activeIdSet.has(runner.intendedReservationId) &&\n !terminalStates.includes(runner.state as (typeof terminalStates)[number])\n ) {\n addUsedRunner(usedByReservation, runner.intendedReservationId, runner.id);\n }\n }\n\n return activeRows.flatMap((reservation) => {\n const used = usedByReservation.get(reservation.id)?.size ?? 0;\n const pending = Math.max(0, reservation.count - used);\n return pending > 0 ? [{requiredLabels: reservation.requiredLabels, reserved: pending}] : [];\n });\n}\n\nfunction addUsedRunner(\n usedByReservation: Map<string, Set<string>>,\n reservationId: string,\n runnerId: string,\n): void {\n const runnerIds = usedByReservation.get(reservationId);\n if (runnerIds) runnerIds.add(runnerId);\n else usedByReservation.set(reservationId, new Set([runnerId]));\n}\n\n// An expired or missing reservation is stale. A live reservation protects a runner that is\n// still booting or waiting for its activation grace period.\nfunction canBindRunner(tx: Tx, params: BindableRunnerParams) {\n return and(\n or(\n and(isNull(providerRunners.workspaceId), isNull(providerRunners.reservationId)),\n and(\n isNotNull(providerRunners.reservationId),\n params.scope === 'installation'\n ? undefined\n : or(\n isNull(providerRunners.workspaceId),\n eq(providerRunners.workspaceId, params.workspaceId),\n ),\n notExists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.id, providerRunners.reservationId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n ),\n ),\n ),\n ),\n or(\n isNull(providerRunners.intendedReservationId),\n notExists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.id, providerRunners.intendedReservationId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n ),\n ),\n ),\n isNull(providerRunners.reservationReleasedAt),\n isNull(providerRunners.runnerSessionId),\n );\n}\n\nfunction isBindableRunner(tx: Tx, params: BindableRunnerParams) {\n return and(\n eq(providerRunners.provisionerId, params.provisionerId),\n canBindRunner(tx, params),\n isNotNull(providerRunners.providerRunnerId),\n eq(providerRunners.state, 'running'),\n arrayContains(providerRunners.labels, params.requiredLabels),\n exists(\n tx\n .select({id: runnerControlSessions.id})\n .from(runnerControlSessions)\n .where(\n and(\n eq(runnerControlSessions.runnerInstanceId, providerRunners.id),\n eq(runnerControlSessions.provisionerId, params.provisionerId),\n isNull(runnerControlSessions.closedAt),\n gt(runnerControlSessions.expiresAt, sql`now()`),\n ),\n ),\n ),\n );\n}\n\nasync function listIdleRunnerInstancesTx(\n tx: Tx,\n params: IdleRunnerSelectionParams & {count: number},\n): Promise<IdleRunnerCandidate[]> {\n const lockedRunners = await selectIdleRunnerInstancesTx(tx, params);\n if (lockedRunners.length === 0) return lockedRunners;\n\n // A SELECT ... FOR UPDATE can wake with a fresh target row but the original\n // statement snapshot for reservation subqueries. Re-check the full predicate\n // in a new statement while retaining the row locks from the first query.\n return await selectIdleRunnerInstancesTx(tx, {\n ...params,\n runnerIds: lockedRunners.map((runner) => runner.id),\n count: lockedRunners.length,\n });\n}\n\nasync function selectIdleRunnerInstancesTx(\n tx: Tx,\n params: IdleRunnerSelectionParams & {count: number; runnerIds?: string[]},\n): Promise<IdleRunnerCandidate[]> {\n if (params.runnerIds) {\n // The first pass retains the row locks. Recheck the full predicate in a fresh statement so\n // reservation subqueries see the state that was current when the lock was acquired.\n return await tx\n .select({id: providerRunners.id, launchKind: providerRunners.launchKind})\n .from(providerRunners)\n .where(and(inArray(providerRunners.id, params.runnerIds), isBindableRunner(tx, params)))\n .orderBy(asc(providerRunners.createdAt), asc(providerRunners.id))\n .limit(params.count);\n }\n\n // Select the oldest candidates first, but leave row locking to a second pass. The cleanup\n // path locks runner rows by id, so the locking pass must use that same order. A skipped row\n // rolls back only this nested savepoint and retries the bounded candidate scan, allowing the\n // next-oldest eligible runner to refill the grant without retaining a partial lock set.\n const retrySelection = Symbol('retry bindable runner selection');\n const idleRunners = await (async () => {\n while (true) {\n try {\n return await tx.transaction(async (lockTx) => {\n const candidateRunners = await lockTx\n .select({id: providerRunners.id, launchKind: providerRunners.launchKind})\n .from(providerRunners)\n .where(isBindableRunner(lockTx, params))\n .orderBy(asc(providerRunners.createdAt), asc(providerRunners.id))\n .limit(params.count);\n\n if (candidateRunners.length === 0) return candidateRunners;\n\n // PostgreSQL can acquire row locks before sorting a multi-row FOR UPDATE result. Lock\n // each selected candidate individually so both polling and cleanup use id order.\n const lockedRunners: typeof candidateRunners = [];\n for (const candidate of [...candidateRunners].sort(compareRunnerIds)) {\n const [runner] = await lockTx\n .select({id: providerRunners.id, launchKind: providerRunners.launchKind})\n .from(providerRunners)\n .where(and(eq(providerRunners.id, candidate.id), isBindableRunner(lockTx, params)))\n .for('update');\n if (runner) lockedRunners.push(runner);\n }\n\n if (lockedRunners.length !== candidateRunners.length) throw retrySelection;\n return lockedRunners;\n });\n } catch (error) {\n if (error !== retrySelection) throw error;\n }\n }\n })();\n\n return idleRunners;\n}\n\nasync function bindIdleRunnerInstancesTx(\n tx: Tx,\n params: {\n provisionerId: string;\n reservationId: string;\n workspaceId: string;\n requiredLabels: string[];\n scope: DemandScope;\n idleRunners: IdleRunnerCandidate[];\n },\n): Promise<void> {\n const idleRunnerIds = params.idleRunners.map((runner) => runner.id);\n\n await tx\n .update(runnerActivationTokens)\n .set({revokedAt: sql`now()`})\n .where(\n and(\n inArray(runnerActivationTokens.runnerInstanceId, idleRunnerIds),\n isNull(runnerActivationTokens.consumedAt),\n isNull(runnerActivationTokens.revokedAt),\n ),\n );\n\n // listIdleRunnerInstancesTx re-checks the full eligibility predicate in a fresh statement\n // after acquiring row locks. Those locks prevent the validated set from changing before this\n // update runs.\n const boundRunners = await tx\n .update(providerRunners)\n .set({\n workspaceId: params.workspaceId,\n reservationId: params.reservationId,\n intendedReservationId: null,\n assignedAt: sql`now()`,\n updatedAt: sql`now()`,\n })\n .where(and(inArray(providerRunners.id, idleRunnerIds), isBindableRunner(tx, params)))\n .returning({id: providerRunners.id, launchKind: providerRunners.launchKind});\n\n if (boundRunners.length !== params.idleRunners.length)\n throw new Error('Locked idle runner set changed before binding');\n\n const reboundCount = boundRunners.filter((runner) => runner.launchKind === 'demand').length;\n if (reboundCount > 0)\n recordProviderRunnerActivationOutcome({outcome: 'rebound', count: reboundCount});\n}\n\nasync function listInstallationDemandWorkspaceIds(eligibleWorkspaceIds: ReadonlySet<string>) {\n if (eligibleWorkspaceIds.size === 0) return [];\n const rows = await db()\n .select({\n workspaceId: pendingJobExecutions.workspaceId,\n oldestQueuedAt: sql<Date>`min(${pendingJobExecutions.createdAt})`,\n })\n .from(pendingJobExecutions)\n .where(inArray(pendingJobExecutions.workspaceId, [...eligibleWorkspaceIds]))\n .groupBy(pendingJobExecutions.workspaceId)\n .orderBy(\n asc(sql`min(${pendingJobExecutions.createdAt})`),\n asc(pendingJobExecutions.workspaceId),\n );\n return rows.map((row) => row.workspaceId);\n}\n\nexport async function listQueuedDemandWorkspaceIds(): Promise<string[]> {\n const rows = await db()\n .select({workspaceId: pendingJobExecutions.workspaceId})\n .from(pendingJobExecutions)\n .groupBy(pendingJobExecutions.workspaceId);\n return rows.map((row) => row.workspaceId);\n}\n\nasync function listActiveWorkspaceCapabilityLabelsTx(\n tx: Tx,\n params: {workspaceId: string; windowSeconds: number},\n): Promise<string[][]> {\n const rows = await tx\n .select({labels: provisionerCapabilitySnapshots.labels})\n .from(provisionerCapabilitySnapshots)\n .innerJoin(\n provisionerTokens,\n eq(provisionerTokens.id, provisionerCapabilitySnapshots.provisionerId),\n )\n .where(\n and(\n eq(provisionerCapabilitySnapshots.workspaceId, params.workspaceId),\n eq(provisionerTokens.workspaceId, params.workspaceId),\n eq(provisionerTokens.scope, 'workspace'),\n sql`${provisionerCapabilitySnapshots.advertisedAt} > now() - (${params.windowSeconds} || ' seconds')::interval`,\n sql`${provisionerTokens.revokedAt} is null`,\n sql`(${provisionerTokens.expiresAt} is null or ${provisionerTokens.expiresAt} > now())`,\n ),\n );\n return rows.map((row) => row.labels);\n}\n\nexport async function deleteExpiredReservations(params?: {limit?: number}): Promise<number> {\n return await db().transaction(async (tx) => {\n const expiredRows = await tx\n .select({id: reservations.id})\n .from(reservations)\n .where(lt(reservations.expiresAt, sql`now()`))\n .orderBy(asc(reservations.expiresAt))\n .limit(params?.limit ?? 1000);\n return await deleteReservationsWithCleanupTx(\n tx,\n expiredRows.map((reservation) => reservation.id),\n {expiredOnly: true},\n );\n });\n}\n\nexport async function deleteReservationsByIds(ids: string[]): Promise<number> {\n if (ids.length === 0) return 0;\n\n return await db().transaction(async (tx) => {\n return await deleteReservationsWithCleanupTx(tx, ids);\n });\n}\n\nasync function deleteReservationsWithCleanupTx(\n tx: Tx,\n ids: string[],\n params: {expiredOnly?: boolean} = {},\n): Promise<number> {\n if (ids.length === 0) return 0;\n\n const isAffectedRunner = () =>\n or(\n and(\n inArray(providerRunners.reservationId, ids),\n isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n inArray(providerRunners.intendedReservationId, ids),\n );\n const candidateRunners = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n intendedReservationId: providerRunners.intendedReservationId,\n runnerSessionId: providerRunners.runnerSessionId,\n reservationReleasedAt: providerRunners.reservationReleasedAt,\n })\n .from(providerRunners)\n .where(isAffectedRunner())\n .orderBy(asc(providerRunners.id));\n const affectedRunners: typeof candidateRunners = [];\n for (const candidate of [...candidateRunners].sort(compareRunnerIds)) {\n const [runner] = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n intendedReservationId: providerRunners.intendedReservationId,\n runnerSessionId: providerRunners.runnerSessionId,\n reservationReleasedAt: providerRunners.reservationReleasedAt,\n })\n .from(providerRunners)\n .where(and(eq(providerRunners.id, candidate.id), isAffectedRunner()))\n .for('update');\n if (runner) affectedRunners.push(runner);\n }\n const reservationRows = await tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n inArray(reservations.id, ids),\n params.expiredOnly ? lt(reservations.expiresAt, sql`now()`) : undefined,\n ),\n )\n .for('update');\n const reservationIds = reservationRows.map((reservation) => reservation.id);\n\n if (reservationIds.length === 0) return 0;\n\n const assignedRunnerIds = affectedRunners\n .filter(\n (runner) =>\n runner.reservationId &&\n reservationIds.includes(runner.reservationId) &&\n !runner.runnerSessionId &&\n !runner.reservationReleasedAt,\n )\n .map((runner) => runner.id);\n const intendedRunnerIds = affectedRunners\n .filter(\n (runner) =>\n runner.intendedReservationId && reservationIds.includes(runner.intendedReservationId),\n )\n .map((runner) => runner.id);\n if (assignedRunnerIds.length > 0) {\n await tx\n .update(runnerActivationTokens)\n .set({revokedAt: sql`now()`})\n .where(\n and(\n inArray(runnerActivationTokens.runnerInstanceId, assignedRunnerIds),\n isNull(runnerActivationTokens.consumedAt),\n isNull(runnerActivationTokens.revokedAt),\n ),\n );\n await tx\n .update(providerRunners)\n .set({\n workspaceId: null,\n reservationId: null,\n assignedAt: null,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(providerRunners.id, assignedRunnerIds),\n isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n );\n }\n if (intendedRunnerIds.length > 0) {\n await tx\n .update(providerRunners)\n .set({intendedReservationId: null, updatedAt: sql`now()`})\n .where(\n and(\n inArray(providerRunners.id, intendedRunnerIds),\n inArray(providerRunners.intendedReservationId, reservationIds),\n ),\n );\n }\n\n const deleted = await tx\n .delete(reservations)\n .where(inArray(reservations.id, reservationIds))\n .returning({id: reservations.id});\n\n return deleted.length;\n}\n\nexport async function releaseReservationUnits(\n tx: Tx,\n params: {\n workspaceId: string;\n provisionerId: string;\n releases: Array<{reservationId: string; count: number}>;\n },\n): Promise<number> {\n let released = 0;\n\n for (const release of params.releases) {\n if (release.count <= 0) continue;\n\n const decremented = await tx\n .update(reservations)\n .set({count: sql`${reservations.count} - ${release.count}`})\n .where(\n and(\n eq(reservations.id, release.reservationId),\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n gt(reservations.count, release.count),\n gt(reservations.expiresAt, sql`now()`),\n ),\n )\n .returning({id: reservations.id});\n\n if (decremented.length > 0) {\n released += release.count;\n continue;\n }\n\n const deleted = await tx\n .delete(reservations)\n .where(\n and(\n eq(reservations.id, release.reservationId),\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n sql`${reservations.count} <= ${release.count}`,\n gt(reservations.expiresAt, sql`now()`),\n ),\n )\n .returning({count: reservations.count});\n\n released += deleted.reduce((total, row) => total + row.count, 0);\n }\n\n return released;\n}\n\nfunction deductProvisionerReservations(\n templates: NormalizedTemplate[],\n activeReservations: {requiredLabels: string[]; reserved: number}[],\n): void {\n for (const reservation of sortReservationRows(activeReservations)) {\n const satisfyingTemplates = templates\n .filter((template) => isSubset(reservation.requiredLabels, template.labels))\n .sort(\n (a, b) => a.labels.length - b.labels.length || a.templateKey.localeCompare(b.templateKey),\n );\n drawSlots(satisfyingTemplates, reservation.reserved);\n }\n}\n\nfunction compareRunnerIds(left: {id: string}, right: {id: string}): number {\n return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;\n}\n\nfunction sortDemandRows(rows: DemandRow[]): DemandRow[] {\n return [...rows].sort((a, b) => {\n const specificity = b.requiredLabels.length - a.requiredLabels.length;\n if (specificity !== 0) return specificity;\n return a.oldestQueuedAt.getTime() - b.oldestQueuedAt.getTime();\n });\n}\n\nfunction sortReservationRows<T extends {requiredLabels: string[]}>(rows: T[]): T[] {\n return [...rows].sort((a, b) => {\n const specificity = b.requiredLabels.length - a.requiredLabels.length;\n if (specificity !== 0) return specificity;\n return labelKey(a.requiredLabels).localeCompare(labelKey(b.requiredLabels));\n });\n}\n\nfunction isSubset(requiredLabels: string[], availableLabels: string[]): boolean {\n return requiredLabels.every((label) => availableLabels.includes(label));\n}\n\nfunction drawSlots(templates: NormalizedTemplate[], count: number): void {\n let remaining = count;\n for (const template of templates) {\n if (remaining === 0) return;\n const used = Math.min(template.remainingSlots, remaining);\n template.remainingSlots -= used;\n remaining -= used;\n }\n}\n\nfunction labelKey(labels: string[]): string {\n return JSON.stringify(labels);\n}\n"],"names":["canonicalizeLabels","and","arrayContains","asc","eq","exists","gt","inArray","isNotNull","isNull","lt","notExists","notInArray","or","sql","recordProviderRunnerActivationOutcome","db","lockRunnerReservationAdvisoryKeysTx","terminalStates","pendingJobExecutions","provisionerCapabilitySnapshots","provisionerTokens","reservations","runnerActivationTokens","runnerControlSessions","providerRunners","pollDemandAndReserve","params","result","transaction","tx","pollDemandAndReserveTx","stats","execute","workspaceId","pollDemandAndReserveLockedTx","scope","pollInstallationDemandAndReserve","candidateWorkspaceIds","listInstallationDemandWorkspaceIds","eligibleWorkspaceIds","results","remainingMaxReservations","maxReservations","remainingTemplates","templates","map","template","labels","remainingSlots","availableSlots","signal","aborted","lockResult","locked","rows","newlyReservedUnits","provisionerId","ttlSeconds","activationGraceSeconds","undefined","capabilityWindowSeconds","push","consumeInstallationTemplateSlots","onReservations","reduce","total","reservation","count","newlyReservedCount","subtotal","flatMap","launchGrants","satisfyingTemplates","filter","isSubset","sort","a","b","length","templateKey","localeCompare","drawSlots","demandRows","select","requiredLabels","queued","oldestQueuedAt","createdAt","from","where","groupBy","row","Date","capabilityLabels","listActiveWorkspaceCapabilityLabelsTx","windowSeconds","demand","some","activeReservationRows","reserved","expiresAt","reservedByLabels","Map","labelKey","activeProvisionerReservationRows","listActiveProvisionerReservationRowsTx","deductProvisionerReservations","grants","workspaceIdField","sortDemandRows","get","unreserved","Math","max","capacity","grant","min","reservedAfterGrant","idleRunners","listIdleRunnerInstancesTx","boundCount","boundReservation","insert","values","kind","returning","id","Error","bindIdleRunnerInstancesTx","reservationId","launchCount","launchReservation","inserted","candidateRows","candidateIds","reservationIds","activeRows","orderBy","for","activeIds","activeIdSet","Set","usedRunnerRows","intendedReservationId","state","reservationReleasedAt","usedByReservation","runner","has","addUsedRunner","includes","used","size","pending","runnerId","runnerIds","add","set","canBindRunner","runnerSessionId","isBindableRunner","providerRunnerId","runnerInstanceId","closedAt","lockedRunners","selectIdleRunnerInstancesTx","launchKind","limit","retrySelection","Symbol","lockTx","candidateRunners","candidate","compareRunnerIds","error","idleRunnerIds","update","revokedAt","consumedAt","boundRunners","assignedAt","updatedAt","reboundCount","outcome","listQueuedDemandWorkspaceIds","innerJoin","advertisedAt","deleteExpiredReservations","expiredRows","deleteReservationsWithCleanupTx","expiredOnly","deleteReservationsByIds","ids","isAffectedRunner","affectedRunners","reservationRows","assignedRunnerIds","intendedRunnerIds","deleted","delete","releaseReservationUnits","released","release","releases","decremented","activeReservations","sortReservationRows","left","right","specificity","getTime","availableLabels","every","label","remaining","JSON","stringify"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/db/reservations.ts"],"sourcesContent":["import {canonicalizeLabels} from '@shipfox/runner-labels';\nimport {\n and,\n arrayContains,\n asc,\n eq,\n exists,\n gt,\n inArray,\n isNotNull,\n isNull,\n lt,\n lte,\n notExists,\n notInArray,\n or,\n sql,\n} from 'drizzle-orm';\nimport {recordProviderRunnerActivationOutcome} from '#metrics/instance.js';\nimport type {Tx} from './db.js';\nimport {db} from './db.js';\nimport {lockRunnerReservationAdvisoryKeysTx} from './reservation-locks.js';\nimport {terminalStates} from './runner-states.js';\nimport {pendingJobExecutions} from './schema/pending-job-executions.js';\nimport {provisionerCapabilitySnapshots} from './schema/provisioner-capability-snapshots.js';\nimport {provisionerTokens} from './schema/provisioner-tokens.js';\nimport {reservations} from './schema/reservations.js';\nimport {runnerActivationTokens} from './schema/runner-activation-tokens.js';\nimport {runnerControlSessions} from './schema/runner-control-sessions.js';\nimport {type providerRunnerLaunchKindEnum, providerRunners} from './schema/runner-instances.js';\nimport {runningJobExecutions} from './schema/running-job-executions.js';\n\nexport interface ReservationTemplate {\n templateKey: string;\n labels: string[];\n availableSlots: number;\n starting: number;\n running: number;\n}\n\nexport interface DemandStat {\n workspaceId?: string;\n labels: string[];\n queued: number;\n reserved: number;\n oldestQueuedAt: Date;\n}\n\nexport interface ReservationGrant {\n reservationId: string;\n workspaceId?: string;\n labels: string[];\n count: number;\n expiresAt: Date;\n}\n\nexport interface PollDemandAndReserveParams {\n workspaceId: string;\n provisionerId: string;\n maxReservations: number;\n ttlSeconds: number;\n /** Lifetime of the short reservation that gives rebound runners time to activate. */\n activationGraceSeconds?: number;\n templates: ReservationTemplate[];\n capabilityWindowSeconds?: number;\n}\n\nexport interface InstallationPollDemandAndReserveParams {\n provisionerId: string;\n maxReservations: number;\n ttlSeconds: number;\n /** Lifetime of the short reservation that gives rebound runners time to activate. */\n activationGraceSeconds?: number;\n templates: ReservationTemplate[];\n capabilityWindowSeconds: number;\n eligibleWorkspaceIds: ReadonlySet<string>;\n signal?: AbortSignal;\n onReservations?: (reservations: ReservationGrant[]) => void;\n}\n\ntype DemandScope = 'installation' | 'workspace';\n\ninterface IdleRunnerCandidate {\n id: string;\n launchKind: (typeof providerRunnerLaunchKindEnum.enumValues)[number];\n}\n\ninterface BindableRunnerParams {\n provisionerId: string;\n workspaceId: string;\n requiredLabels: string[];\n scope: DemandScope;\n}\n\ninterface IdleRunnerSelectionParams extends BindableRunnerParams {\n count: number;\n}\n\ntype PollDemandAndReserveLockedParams = PollDemandAndReserveParams & {\n scope: DemandScope;\n};\n\ninterface NormalizedTemplate {\n templateKey: string;\n labels: string[];\n remainingSlots: number;\n}\n\ninterface DemandRow {\n requiredLabels: string[];\n queued: number;\n oldestQueuedAt: Date;\n}\n\ninterface NewReservationUnits {\n labels: string[];\n count: number;\n}\n\ninterface PollDemandAndReserveResult {\n stats: DemandStat[];\n /** Only launch reservations are exposed to the provisioner. */\n reservations: ReservationGrant[];\n /** Internal allocation accounting for bound and launch rows together. */\n newlyReservedUnits: NewReservationUnits[];\n}\n\nexport async function pollDemandAndReserve(\n params: PollDemandAndReserveParams,\n): Promise<{stats: DemandStat[]; reservations: ReservationGrant[]}> {\n const result = await db().transaction(async (tx) => {\n return await pollDemandAndReserveTx(tx, params);\n });\n return {stats: result.stats, reservations: result.reservations};\n}\n\nexport async function pollDemandAndReserveTx(\n tx: Tx,\n params: PollDemandAndReserveParams,\n): Promise<PollDemandAndReserveResult> {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext(${params.workspaceId}))`);\n return await pollDemandAndReserveLockedTx(tx, {...params, scope: 'workspace'});\n}\n\nexport async function pollInstallationDemandAndReserve(\n params: InstallationPollDemandAndReserveParams,\n): Promise<{\n stats: DemandStat[];\n reservations: ReservationGrant[];\n newlyReservedCount?: number;\n}> {\n const candidateWorkspaceIds = await listInstallationDemandWorkspaceIds(\n params.eligibleWorkspaceIds,\n );\n const results: PollDemandAndReserveResult[] = [];\n let remainingMaxReservations = params.maxReservations;\n const remainingTemplates = params.templates.map((template) => ({\n ...template,\n labels: [...canonicalizeLabels(template.labels)],\n remainingSlots: template.availableSlots,\n }));\n for (const workspaceId of candidateWorkspaceIds) {\n if (params.signal?.aborted || remainingMaxReservations === 0) break;\n const result = await db().transaction(async (tx) => {\n const lockResult = await tx.execute<{locked: boolean}>(\n sql`select pg_try_advisory_xact_lock(hashtext(${workspaceId})) as locked`,\n );\n const locked = lockResult.rows[0];\n if (!locked?.locked) return {stats: [], reservations: [], newlyReservedUnits: []};\n return await pollDemandAndReserveLockedTx(tx, {\n workspaceId,\n provisionerId: params.provisionerId,\n maxReservations: remainingMaxReservations,\n ttlSeconds: params.ttlSeconds,\n ...(params.activationGraceSeconds !== undefined\n ? {activationGraceSeconds: params.activationGraceSeconds}\n : {}),\n templates: remainingTemplates.map((template) => ({\n ...template,\n availableSlots: template.remainingSlots,\n })),\n capabilityWindowSeconds: params.capabilityWindowSeconds,\n scope: 'installation',\n });\n });\n results.push(result);\n consumeInstallationTemplateSlots(remainingTemplates, result.reservations);\n params.onReservations?.(result.reservations);\n remainingMaxReservations -= result.newlyReservedUnits.reduce(\n (total, reservation) => total + reservation.count,\n 0,\n );\n }\n const newlyReservedCount = results.reduce(\n (total, result) =>\n total +\n result.newlyReservedUnits.reduce((subtotal, reservation) => subtotal + reservation.count, 0),\n 0,\n );\n return {\n stats: results.flatMap((result) => result.stats),\n reservations: results.flatMap((result) => result.reservations),\n ...(newlyReservedCount > 0 ? {newlyReservedCount} : {}),\n };\n}\n\nfunction consumeInstallationTemplateSlots(\n templates: NormalizedTemplate[],\n launchGrants: ReservationGrant[],\n): void {\n // Adopted runners are already included in the running count behind availableSlots.\n // Only units that still need a launch consume advertised template capacity.\n for (const reservation of launchGrants) {\n const satisfyingTemplates = templates\n .filter((template) => isSubset(reservation.labels, template.labels))\n .sort(\n (a, b) => a.labels.length - b.labels.length || a.templateKey.localeCompare(b.templateKey),\n );\n drawSlots(satisfyingTemplates, reservation.count);\n }\n}\n\nasync function pollDemandAndReserveLockedTx(\n tx: Tx,\n params: PollDemandAndReserveLockedParams,\n): Promise<PollDemandAndReserveResult> {\n let demandRows = (\n await tx\n .select({\n requiredLabels: pendingJobExecutions.requiredLabels,\n queued: sql<number>`count(*)::int`,\n oldestQueuedAt: sql<Date | string>`min(${pendingJobExecutions.createdAt})`,\n })\n .from(pendingJobExecutions)\n .where(eq(pendingJobExecutions.workspaceId, params.workspaceId))\n .groupBy(pendingJobExecutions.requiredLabels)\n ).map((row) => ({\n ...row,\n oldestQueuedAt: new Date(row.oldestQueuedAt),\n }));\n if (params.capabilityWindowSeconds !== undefined) {\n const capabilityLabels = await listActiveWorkspaceCapabilityLabelsTx(tx, {\n workspaceId: params.workspaceId,\n windowSeconds: params.capabilityWindowSeconds,\n });\n demandRows = demandRows.filter(\n (demand) => !capabilityLabels.some((labels) => isSubset(demand.requiredLabels, labels)),\n );\n }\n\n const activeReservationRows = await tx\n .select({\n requiredLabels: reservations.requiredLabels,\n reserved: sql<number>`coalesce(sum(${reservations.count}), 0)::int`,\n })\n .from(reservations)\n .where(\n and(eq(reservations.workspaceId, params.workspaceId), gt(reservations.expiresAt, sql`now()`)),\n )\n .groupBy(reservations.requiredLabels);\n\n const reservedByLabels = new Map(\n activeReservationRows.map((row) => [labelKey(row.requiredLabels), row.reserved]),\n );\n const activeProvisionerReservationRows = await listActiveProvisionerReservationRowsTx(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n });\n\n const templates = params.templates.map((template) => ({\n templateKey: template.templateKey,\n labels: [...canonicalizeLabels(template.labels)],\n remainingSlots: template.availableSlots,\n }));\n deductProvisionerReservations(templates, activeProvisionerReservationRows);\n const stats: DemandStat[] = [];\n const grants: ReservationGrant[] = [];\n const newlyReservedUnits: NewReservationUnits[] = [];\n let remainingMaxReservations = params.maxReservations;\n const workspaceIdField =\n params.capabilityWindowSeconds === undefined ? {} : {workspaceId: params.workspaceId};\n\n for (const demand of sortDemandRows(demandRows)) {\n const satisfyingTemplates = templates\n .filter((template) => isSubset(demand.requiredLabels, template.labels))\n .sort(\n (a, b) => a.labels.length - b.labels.length || a.templateKey.localeCompare(b.templateKey),\n );\n\n if (satisfyingTemplates.length === 0) continue;\n\n const reserved = reservedByLabels.get(labelKey(demand.requiredLabels)) ?? 0;\n const unreserved = Math.max(0, demand.queued - reserved);\n const capacity = satisfyingTemplates.reduce(\n (total, template) => total + template.remainingSlots,\n 0,\n );\n const grant = Math.min(unreserved, capacity, remainingMaxReservations);\n let reservedAfterGrant = reserved;\n\n if (grant > 0 && params.maxReservations > 0) {\n const idleRunners = await listIdleRunnerInstancesTx(tx, {\n provisionerId: params.provisionerId,\n requiredLabels: demand.requiredLabels,\n count: grant,\n workspaceId: params.workspaceId,\n scope: params.scope,\n });\n\n remainingMaxReservations -= grant;\n\n const boundCount = idleRunners.length;\n if (boundCount > 0) {\n const [boundReservation] = await tx\n .insert(reservations)\n .values({\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n requiredLabels: demand.requiredLabels,\n count: boundCount,\n kind: 'bound',\n expiresAt: sql`now() + (${params.activationGraceSeconds ?? params.ttlSeconds} || ' seconds')::interval`,\n })\n .returning({id: reservations.id});\n\n if (!boundReservation) throw new Error('Insert returned no rows');\n\n await bindIdleRunnerInstancesTx(tx, {\n provisionerId: params.provisionerId,\n reservationId: boundReservation.id,\n workspaceId: params.workspaceId,\n requiredLabels: demand.requiredLabels,\n scope: params.scope,\n idleRunners,\n });\n }\n\n const launchCount = grant - boundCount;\n drawSlots(satisfyingTemplates, launchCount);\n let launchReservation: {id: string; expiresAt: Date} | undefined;\n if (launchCount > 0) {\n const [inserted] = await tx\n .insert(reservations)\n .values({\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n requiredLabels: demand.requiredLabels,\n count: launchCount,\n kind: 'launch',\n expiresAt: sql`now() + (${params.ttlSeconds} || ' seconds')::interval`,\n })\n .returning({id: reservations.id, expiresAt: reservations.expiresAt});\n\n if (!inserted) throw new Error('Insert returned no rows');\n launchReservation = inserted;\n }\n\n newlyReservedUnits.push({labels: demand.requiredLabels, count: grant});\n reservedAfterGrant += grant;\n if (launchReservation) {\n grants.push({\n reservationId: launchReservation.id,\n ...workspaceIdField,\n labels: demand.requiredLabels,\n count: launchCount,\n expiresAt: launchReservation.expiresAt,\n });\n }\n }\n\n stats.push({\n ...workspaceIdField,\n labels: demand.requiredLabels,\n queued: demand.queued,\n reserved: reservedAfterGrant,\n oldestQueuedAt: demand.oldestQueuedAt,\n });\n }\n\n return {stats, reservations: grants, newlyReservedUnits};\n}\n\nasync function listActiveProvisionerReservationRowsTx(\n tx: Tx,\n params: {workspaceId: string; provisionerId: string},\n): Promise<Array<{requiredLabels: string[]; reserved: number}>> {\n const candidateRows = await tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n );\n const candidateIds = candidateRows.map((row) => row.id);\n if (candidateIds.length === 0) return [];\n\n // Assignment and provider-report transactions use this key before changing runner\n // links. Lock it before counting so an in-flight assignment cannot expose its unit twice.\n await lockRunnerReservationAdvisoryKeysTx(tx, {\n provisionerId: params.provisionerId,\n reservationIds: candidateIds,\n });\n\n const activeRows = await tx\n .select({\n id: reservations.id,\n requiredLabels: reservations.requiredLabels,\n count: reservations.count,\n })\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n )\n .orderBy(asc(reservations.id))\n .for('update');\n if (activeRows.length === 0) return [];\n\n const activeIds = activeRows.map((row) => row.id);\n const activeIdSet = new Set(activeIds);\n const usedRunnerRows = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n intendedReservationId: providerRunners.intendedReservationId,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.reservationReleasedAt),\n or(\n and(\n inArray(providerRunners.reservationId, activeIds),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n and(\n inArray(providerRunners.intendedReservationId, activeIds),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n ),\n ),\n );\n const usedByReservation = new Map<string, Set<string>>();\n for (const runner of usedRunnerRows) {\n if (runner.reservationId && activeIdSet.has(runner.reservationId)) {\n addUsedRunner(usedByReservation, runner.reservationId, runner.id);\n }\n if (runner.intendedReservationId && activeIdSet.has(runner.intendedReservationId)) {\n addUsedRunner(usedByReservation, runner.intendedReservationId, runner.id);\n }\n }\n\n return activeRows.flatMap((reservation) => {\n const used = usedByReservation.get(reservation.id)?.size ?? 0;\n const pending = Math.max(0, reservation.count - used);\n return pending > 0 ? [{requiredLabels: reservation.requiredLabels, reserved: pending}] : [];\n });\n}\n\nfunction addUsedRunner(\n usedByReservation: Map<string, Set<string>>,\n reservationId: string,\n runnerId: string,\n): void {\n const runnerIds = usedByReservation.get(reservationId);\n if (runnerIds) runnerIds.add(runnerId);\n else usedByReservation.set(reservationId, new Set([runnerId]));\n}\n\n// An expired or missing reservation is stale. A live reservation protects a runner that is\n// still booting or waiting for its activation grace period.\nfunction canBindRunner(tx: Tx, params: BindableRunnerParams) {\n return and(\n or(\n and(isNull(providerRunners.workspaceId), isNull(providerRunners.reservationId)),\n and(\n isNotNull(providerRunners.reservationId),\n params.scope === 'installation'\n ? undefined\n : or(\n isNull(providerRunners.workspaceId),\n eq(providerRunners.workspaceId, params.workspaceId),\n ),\n notExists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.id, providerRunners.reservationId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n ),\n ),\n ),\n ),\n or(\n isNull(providerRunners.intendedReservationId),\n notExists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.id, providerRunners.intendedReservationId),\n gt(reservations.expiresAt, sql`now()`),\n ),\n ),\n ),\n ),\n isNull(providerRunners.reservationReleasedAt),\n isNull(providerRunners.runnerSessionId),\n );\n}\n\nfunction isBindableRunner(tx: Tx, params: BindableRunnerParams) {\n return and(\n eq(providerRunners.provisionerId, params.provisionerId),\n canBindRunner(tx, params),\n isNotNull(providerRunners.providerRunnerId),\n eq(providerRunners.state, 'running'),\n arrayContains(providerRunners.labels, params.requiredLabels),\n exists(\n tx\n .select({id: runnerControlSessions.id})\n .from(runnerControlSessions)\n .where(\n and(\n eq(runnerControlSessions.runnerInstanceId, providerRunners.id),\n eq(runnerControlSessions.provisionerId, params.provisionerId),\n isNull(runnerControlSessions.closedAt),\n gt(runnerControlSessions.expiresAt, sql`now()`),\n ),\n ),\n ),\n );\n}\n\nasync function listIdleRunnerInstancesTx(\n tx: Tx,\n params: IdleRunnerSelectionParams & {count: number},\n): Promise<IdleRunnerCandidate[]> {\n const lockedRunners = await selectIdleRunnerInstancesTx(tx, params);\n if (lockedRunners.length === 0) return lockedRunners;\n\n // A SELECT ... FOR UPDATE can wake with a fresh target row but the original\n // statement snapshot for reservation subqueries. Re-check the full predicate\n // in a new statement while retaining the row locks from the first query.\n return await selectIdleRunnerInstancesTx(tx, {\n ...params,\n runnerIds: lockedRunners.map((runner) => runner.id),\n count: lockedRunners.length,\n });\n}\n\nasync function selectIdleRunnerInstancesTx(\n tx: Tx,\n params: IdleRunnerSelectionParams & {count: number; runnerIds?: string[]},\n): Promise<IdleRunnerCandidate[]> {\n if (params.runnerIds) {\n // The first pass retains the row locks. Recheck the full predicate in a fresh statement so\n // reservation subqueries see the state that was current when the lock was acquired.\n return await tx\n .select({id: providerRunners.id, launchKind: providerRunners.launchKind})\n .from(providerRunners)\n .where(and(inArray(providerRunners.id, params.runnerIds), isBindableRunner(tx, params)))\n .orderBy(asc(providerRunners.createdAt), asc(providerRunners.id))\n .limit(params.count);\n }\n\n // Select the oldest candidates first, but leave row locking to a second pass. The cleanup\n // path locks runner rows by id, so the locking pass must use that same order. A skipped row\n // rolls back only this nested savepoint and retries the bounded candidate scan, allowing the\n // next-oldest eligible runner to refill the grant without retaining a partial lock set.\n const retrySelection = Symbol('retry bindable runner selection');\n const idleRunners = await (async () => {\n while (true) {\n try {\n return await tx.transaction(async (lockTx) => {\n const candidateRunners = await lockTx\n .select({id: providerRunners.id, launchKind: providerRunners.launchKind})\n .from(providerRunners)\n .where(isBindableRunner(lockTx, params))\n .orderBy(asc(providerRunners.createdAt), asc(providerRunners.id))\n .limit(params.count);\n\n if (candidateRunners.length === 0) return candidateRunners;\n\n // PostgreSQL can acquire row locks before sorting a multi-row FOR UPDATE result. Lock\n // each selected candidate individually so both polling and cleanup use id order.\n const lockedRunners: typeof candidateRunners = [];\n for (const candidate of [...candidateRunners].sort(compareRunnerIds)) {\n const [runner] = await lockTx\n .select({id: providerRunners.id, launchKind: providerRunners.launchKind})\n .from(providerRunners)\n .where(and(eq(providerRunners.id, candidate.id), isBindableRunner(lockTx, params)))\n .for('update');\n if (runner) lockedRunners.push(runner);\n }\n\n if (lockedRunners.length !== candidateRunners.length) throw retrySelection;\n return lockedRunners;\n });\n } catch (error) {\n if (error !== retrySelection) throw error;\n }\n }\n })();\n\n return idleRunners;\n}\n\nasync function bindIdleRunnerInstancesTx(\n tx: Tx,\n params: {\n provisionerId: string;\n reservationId: string;\n workspaceId: string;\n requiredLabels: string[];\n scope: DemandScope;\n idleRunners: IdleRunnerCandidate[];\n },\n): Promise<void> {\n const idleRunnerIds = params.idleRunners.map((runner) => runner.id);\n\n await tx\n .update(runnerActivationTokens)\n .set({revokedAt: sql`now()`})\n .where(\n and(\n inArray(runnerActivationTokens.runnerInstanceId, idleRunnerIds),\n isNull(runnerActivationTokens.consumedAt),\n isNull(runnerActivationTokens.revokedAt),\n ),\n );\n\n // listIdleRunnerInstancesTx re-checks the full eligibility predicate in a fresh statement\n // after acquiring row locks. Those locks prevent the validated set from changing before this\n // update runs.\n const boundRunners = await tx\n .update(providerRunners)\n .set({\n workspaceId: params.workspaceId,\n reservationId: params.reservationId,\n intendedReservationId: null,\n assignedAt: sql`now()`,\n updatedAt: sql`now()`,\n })\n .where(and(inArray(providerRunners.id, idleRunnerIds), isBindableRunner(tx, params)))\n .returning({id: providerRunners.id, launchKind: providerRunners.launchKind});\n\n if (boundRunners.length !== params.idleRunners.length)\n throw new Error('Locked idle runner set changed before binding');\n\n const reboundCount = boundRunners.filter((runner) => runner.launchKind === 'demand').length;\n if (reboundCount > 0)\n recordProviderRunnerActivationOutcome({outcome: 'rebound', count: reboundCount});\n}\n\nasync function listInstallationDemandWorkspaceIds(eligibleWorkspaceIds: ReadonlySet<string>) {\n if (eligibleWorkspaceIds.size === 0) return [];\n const rows = await db()\n .select({\n workspaceId: pendingJobExecutions.workspaceId,\n oldestQueuedAt: sql<Date>`min(${pendingJobExecutions.createdAt})`,\n })\n .from(pendingJobExecutions)\n .where(inArray(pendingJobExecutions.workspaceId, [...eligibleWorkspaceIds]))\n .groupBy(pendingJobExecutions.workspaceId)\n .orderBy(\n asc(sql`min(${pendingJobExecutions.createdAt})`),\n asc(pendingJobExecutions.workspaceId),\n );\n return rows.map((row) => row.workspaceId);\n}\n\nexport async function listQueuedDemandWorkspaceIds(): Promise<string[]> {\n const rows = await db()\n .select({workspaceId: pendingJobExecutions.workspaceId})\n .from(pendingJobExecutions)\n .groupBy(pendingJobExecutions.workspaceId);\n return rows.map((row) => row.workspaceId);\n}\n\nasync function listActiveWorkspaceCapabilityLabelsTx(\n tx: Tx,\n params: {workspaceId: string; windowSeconds: number},\n): Promise<string[][]> {\n const rows = await tx\n .select({labels: provisionerCapabilitySnapshots.labels})\n .from(provisionerCapabilitySnapshots)\n .innerJoin(\n provisionerTokens,\n eq(provisionerTokens.id, provisionerCapabilitySnapshots.provisionerId),\n )\n .where(\n and(\n eq(provisionerCapabilitySnapshots.workspaceId, params.workspaceId),\n eq(provisionerTokens.workspaceId, params.workspaceId),\n eq(provisionerTokens.scope, 'workspace'),\n sql`${provisionerCapabilitySnapshots.advertisedAt} > now() - (${params.windowSeconds} || ' seconds')::interval`,\n sql`${provisionerTokens.revokedAt} is null`,\n sql`(${provisionerTokens.expiresAt} is null or ${provisionerTokens.expiresAt} > now())`,\n ),\n );\n return rows.map((row) => row.labels);\n}\n\nexport async function deleteExpiredReservations(params?: {limit?: number}): Promise<number> {\n return await db().transaction(async (tx) => {\n const expiredRows = await tx\n .select({id: reservations.id})\n .from(reservations)\n .where(lt(reservations.expiresAt, sql`now()`))\n .orderBy(asc(reservations.expiresAt))\n .limit(params?.limit ?? 1000);\n return await deleteReservationsWithCleanupTx(\n tx,\n expiredRows.map((reservation) => reservation.id),\n {expiredOnly: true},\n );\n });\n}\n\nexport async function deleteReservationsByIds(ids: string[]): Promise<number> {\n if (ids.length === 0) return 0;\n\n return await db().transaction(async (tx) => {\n return await deleteReservationsWithCleanupTx(tx, ids);\n });\n}\n\nasync function deleteReservationsWithCleanupTx(\n tx: Tx,\n ids: string[],\n params: {expiredOnly?: boolean} = {},\n): Promise<number> {\n if (ids.length === 0) return 0;\n\n const isAffectedRunner = () =>\n or(\n and(\n inArray(providerRunners.reservationId, ids),\n isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n inArray(providerRunners.intendedReservationId, ids),\n );\n const candidateRunners = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n intendedReservationId: providerRunners.intendedReservationId,\n runnerSessionId: providerRunners.runnerSessionId,\n reservationReleasedAt: providerRunners.reservationReleasedAt,\n })\n .from(providerRunners)\n .where(isAffectedRunner())\n .orderBy(asc(providerRunners.id));\n const affectedRunners: typeof candidateRunners = [];\n for (const candidate of [...candidateRunners].sort(compareRunnerIds)) {\n const [runner] = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n intendedReservationId: providerRunners.intendedReservationId,\n runnerSessionId: providerRunners.runnerSessionId,\n reservationReleasedAt: providerRunners.reservationReleasedAt,\n })\n .from(providerRunners)\n .where(and(eq(providerRunners.id, candidate.id), isAffectedRunner()))\n .for('update');\n if (runner) affectedRunners.push(runner);\n }\n const reservationRows = await tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n inArray(reservations.id, ids),\n params.expiredOnly ? lt(reservations.expiresAt, sql`now()`) : undefined,\n ),\n )\n .for('update');\n const reservationIds = reservationRows.map((reservation) => reservation.id);\n\n if (reservationIds.length === 0) return 0;\n\n const assignedRunnerIds = affectedRunners\n .filter(\n (runner) =>\n runner.reservationId &&\n reservationIds.includes(runner.reservationId) &&\n !runner.runnerSessionId &&\n !runner.reservationReleasedAt,\n )\n .map((runner) => runner.id);\n const intendedRunnerIds = affectedRunners\n .filter(\n (runner) =>\n runner.intendedReservationId && reservationIds.includes(runner.intendedReservationId),\n )\n .map((runner) => runner.id);\n if (assignedRunnerIds.length > 0) {\n await tx\n .update(runnerActivationTokens)\n .set({revokedAt: sql`now()`})\n .where(\n and(\n inArray(runnerActivationTokens.runnerInstanceId, assignedRunnerIds),\n isNull(runnerActivationTokens.consumedAt),\n isNull(runnerActivationTokens.revokedAt),\n ),\n );\n await tx\n .update(providerRunners)\n .set({\n workspaceId: null,\n reservationId: null,\n assignedAt: null,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(providerRunners.id, assignedRunnerIds),\n isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n );\n }\n if (intendedRunnerIds.length > 0) {\n await tx\n .update(providerRunners)\n .set({intendedReservationId: null, updatedAt: sql`now()`})\n .where(\n and(\n inArray(providerRunners.id, intendedRunnerIds),\n inArray(providerRunners.intendedReservationId, reservationIds),\n ),\n );\n }\n\n const deleted = await tx\n .delete(reservations)\n .where(inArray(reservations.id, reservationIds))\n .returning({id: reservations.id});\n\n return deleted.length;\n}\n\nexport async function releaseReservationUnits(\n tx: Tx,\n params: {\n workspaceId: string;\n provisionerId: string;\n releases: Array<{reservationId: string; count: number}>;\n },\n): Promise<number> {\n const releaseByReservationId = new Map<string, number>();\n for (const release of params.releases) {\n if (release.count <= 0) continue;\n releaseByReservationId.set(\n release.reservationId,\n (releaseByReservationId.get(release.reservationId) ?? 0) + release.count,\n );\n }\n const reservationIds = [...releaseByReservationId.keys()];\n if (reservationIds.length === 0) return 0;\n\n const releaseCount = sql<number>`CASE ${reservations.id}\n ${sql.join(\n [...releaseByReservationId].map(\n ([reservationId, count]) => sql`WHEN ${reservationId} THEN ${count}`,\n ),\n sql` `,\n )}\n ELSE 0\n END`;\n const scope = and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n inArray(reservations.id, reservationIds),\n gt(reservations.expiresAt, sql`now()`),\n );\n\n const decremented = await tx\n .update(reservations)\n .set({count: sql`${reservations.count} - ${releaseCount}`})\n .where(and(scope, gt(reservations.count, releaseCount)))\n .returning({id: reservations.id});\n const releasedFromDecremented = decremented.reduce(\n (total, row) => total + (releaseByReservationId.get(row.id) ?? 0),\n 0,\n );\n\n const decrementedIds = decremented.map((row) => row.id);\n const deleted = await tx\n .delete(reservations)\n .where(\n and(\n scope,\n sql`${reservations.count} <= ${releaseCount}`,\n decrementedIds.length > 0 ? notInArray(reservations.id, decrementedIds) : undefined,\n ),\n )\n .returning({count: reservations.count});\n const releasedFromDeleted = deleted.reduce((total, row) => total + row.count, 0);\n\n return releasedFromDeleted + releasedFromDecremented;\n}\n\nexport async function releaseTerminalRunnerInstanceReservationsByIds(\n tx: Tx,\n params: {\n workspaceId: string | null;\n provisionerId: string;\n providerRunnerIds?: string[];\n runnerInstanceIds?: string[];\n reportedAtByProviderRunnerId?: ReadonlyMap<string, Date>;\n requireUnlinkedSession?: boolean;\n /** Lock linked runners before rechecking terminal state for lease finalization. */\n requireTerminalState?: boolean;\n },\n): Promise<number> {\n if (\n (params.providerRunnerIds?.length ?? 0) === 0 &&\n (params.runnerInstanceIds?.length ?? 0) === 0\n )\n return 0;\n\n const reservationWorkspacePredicate =\n params.workspaceId === null\n ? sql``\n : sql`and ${eq(reservations.workspaceId, params.workspaceId)}`;\n const noRunningJobPredicate = notExists(\n tx\n .select({id: runningJobExecutions.id})\n .from(runningJobExecutions)\n .where(\n and(\n eq(runningJobExecutions.provisionerId, params.provisionerId),\n eq(runningJobExecutions.providerRunnerId, providerRunners.providerRunnerId),\n params.workspaceId === null\n ? undefined\n : eq(runningJobExecutions.workspaceId, params.workspaceId),\n ),\n ),\n );\n const reportFreshnessPredicate =\n params.reportedAtByProviderRunnerId && params.reportedAtByProviderRunnerId.size > 0\n ? or(\n ...[...params.reportedAtByProviderRunnerId].map(([providerRunnerId, reportedAt]) =>\n and(\n eq(providerRunners.providerRunnerId, providerRunnerId),\n lte(providerRunners.reportedAt, reportedAt),\n ),\n ),\n )\n : undefined;\n const runnerIdentityPredicate = or(\n params.providerRunnerIds && params.providerRunnerIds.length > 0\n ? inArray(providerRunners.providerRunnerId, params.providerRunnerIds)\n : undefined,\n params.runnerInstanceIds && params.runnerInstanceIds.length > 0\n ? inArray(providerRunners.id, params.runnerInstanceIds)\n : undefined,\n );\n\n // Assignment locks these keys before changing runner links. Acquire them before locking or\n // marking terminal runners so an assignment cannot consume a reservation concurrently with\n // this release.\n const reservationRowsToLock = await tx\n .select({\n reservationId: providerRunners.reservationId,\n intendedReservationId: providerRunners.intendedReservationId,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.provisionerId, params.provisionerId),\n runnerIdentityPredicate,\n params.requireTerminalState === false\n ? undefined\n : inArray(providerRunners.state, terminalStates),\n or(\n isNotNull(providerRunners.reservationId),\n isNotNull(providerRunners.intendedReservationId),\n ),\n isNull(providerRunners.reservationReleasedAt),\n ),\n );\n const reservationIdsToLock = [\n ...new Set(\n reservationRowsToLock.flatMap((row) =>\n [row.reservationId, row.intendedReservationId].filter(\n (reservationId): reservationId is string => reservationId !== null,\n ),\n ),\n ),\n ];\n await lockRunnerReservationAdvisoryKeysTx(tx, {\n provisionerId: params.provisionerId,\n reservationIds: reservationIdsToLock,\n });\n\n const rows = await tx\n .select({\n id: providerRunners.id,\n state: providerRunners.state,\n releaseReservationId: sql<string | null>`coalesce(\n (select ${reservations.id}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.intendedReservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate}),\n (select ${reservations.id}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.reservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate})\n )`,\n releaseReservationWorkspaceId: sql<string | null>`coalesce(\n (select ${reservations.workspaceId}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.intendedReservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate}),\n (select ${reservations.workspaceId}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.reservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate})\n )`,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.provisionerId, params.provisionerId),\n runnerIdentityPredicate,\n params.requireTerminalState === false\n ? undefined\n : inArray(providerRunners.state, terminalStates),\n or(\n isNotNull(providerRunners.reservationId),\n isNotNull(providerRunners.intendedReservationId),\n ),\n params.workspaceId === null\n ? undefined\n : or(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n or(\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.reservationId),\n ),\n ),\n ),\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.intendedReservationId),\n ),\n ),\n ),\n ),\n ),\n and(\n isNull(providerRunners.workspaceId),\n isNotNull(providerRunners.intendedReservationId),\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.intendedReservationId),\n ),\n ),\n ),\n ),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n noRunningJobPredicate,\n reportFreshnessPredicate,\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .for('update');\n\n if (rows.length === 0) return 0;\n\n // The lease-finalization path deliberately locks active rows too. If a terminal report is\n // concurrently projecting the runner state, PostgreSQL rechecks this row after the lock and\n // lets cleanup observe the committed terminal state without a cross-module advisory lock.\n const terminalRows =\n params.requireTerminalState === false\n ? rows.filter((row) => terminalStates.some((terminalState) => terminalState === row.state))\n : rows;\n if (terminalRows.length === 0) return 0;\n\n const updated = await tx\n .update(providerRunners)\n .set({\n intendedReservationId: null,\n reservationReleasedAt: sql`now()`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(\n providerRunners.id,\n terminalRows.map((row) => row.id),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n noRunningJobPredicate,\n reportFreshnessPredicate,\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .returning({id: providerRunners.id});\n\n const releasesByReservationId = new Map<\n string,\n {workspaceId: string; reservationId: string; count: number}\n >();\n const updatedIds = new Set(updated.map((row) => row.id));\n for (const row of terminalRows) {\n if (!updatedIds.has(row.id)) continue;\n if (!row.releaseReservationId || !row.releaseReservationWorkspaceId) continue;\n const key = `${row.releaseReservationWorkspaceId}:${row.releaseReservationId}`;\n const release = releasesByReservationId.get(key) ?? {\n workspaceId: row.releaseReservationWorkspaceId,\n reservationId: row.releaseReservationId,\n count: 0,\n };\n release.count += 1;\n releasesByReservationId.set(key, release);\n }\n\n if (releasesByReservationId.size === 0) return 0;\n\n const releasesByWorkspaceId = new Map<string, Array<{reservationId: string; count: number}>>();\n for (const release of releasesByReservationId.values()) {\n const releases = releasesByWorkspaceId.get(release.workspaceId) ?? [];\n releases.push({reservationId: release.reservationId, count: release.count});\n releasesByWorkspaceId.set(release.workspaceId, releases);\n }\n\n let released = 0;\n for (const [workspaceId, releases] of releasesByWorkspaceId) {\n released += await releaseReservationUnits(tx, {\n workspaceId,\n provisionerId: params.provisionerId,\n releases,\n });\n }\n return released;\n}\n\nfunction deductProvisionerReservations(\n templates: NormalizedTemplate[],\n activeReservations: {requiredLabels: string[]; reserved: number}[],\n): void {\n for (const reservation of sortReservationRows(activeReservations)) {\n const satisfyingTemplates = templates\n .filter((template) => isSubset(reservation.requiredLabels, template.labels))\n .sort(\n (a, b) => a.labels.length - b.labels.length || a.templateKey.localeCompare(b.templateKey),\n );\n drawSlots(satisfyingTemplates, reservation.reserved);\n }\n}\n\nfunction compareRunnerIds(left: {id: string}, right: {id: string}): number {\n return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;\n}\n\nfunction sortDemandRows(rows: DemandRow[]): DemandRow[] {\n return [...rows].sort((a, b) => {\n const specificity = b.requiredLabels.length - a.requiredLabels.length;\n if (specificity !== 0) return specificity;\n return a.oldestQueuedAt.getTime() - b.oldestQueuedAt.getTime();\n });\n}\n\nfunction sortReservationRows<T extends {requiredLabels: string[]}>(rows: T[]): T[] {\n return [...rows].sort((a, b) => {\n const specificity = b.requiredLabels.length - a.requiredLabels.length;\n if (specificity !== 0) return specificity;\n return labelKey(a.requiredLabels).localeCompare(labelKey(b.requiredLabels));\n });\n}\n\nfunction isSubset(requiredLabels: string[], availableLabels: string[]): boolean {\n return requiredLabels.every((label) => availableLabels.includes(label));\n}\n\nfunction drawSlots(templates: NormalizedTemplate[], count: number): void {\n let remaining = count;\n for (const template of templates) {\n if (remaining === 0) return;\n const used = Math.min(template.remainingSlots, remaining);\n template.remainingSlots -= used;\n remaining -= used;\n }\n}\n\nfunction labelKey(labels: string[]): string {\n return JSON.stringify(labels);\n}\n"],"names":["canonicalizeLabels","and","arrayContains","asc","eq","exists","gt","inArray","isNotNull","isNull","lt","lte","notExists","notInArray","or","sql","recordProviderRunnerActivationOutcome","db","lockRunnerReservationAdvisoryKeysTx","terminalStates","pendingJobExecutions","provisionerCapabilitySnapshots","provisionerTokens","reservations","runnerActivationTokens","runnerControlSessions","providerRunners","runningJobExecutions","pollDemandAndReserve","params","result","transaction","tx","pollDemandAndReserveTx","stats","execute","workspaceId","pollDemandAndReserveLockedTx","scope","pollInstallationDemandAndReserve","candidateWorkspaceIds","listInstallationDemandWorkspaceIds","eligibleWorkspaceIds","results","remainingMaxReservations","maxReservations","remainingTemplates","templates","map","template","labels","remainingSlots","availableSlots","signal","aborted","lockResult","locked","rows","newlyReservedUnits","provisionerId","ttlSeconds","activationGraceSeconds","undefined","capabilityWindowSeconds","push","consumeInstallationTemplateSlots","onReservations","reduce","total","reservation","count","newlyReservedCount","subtotal","flatMap","launchGrants","satisfyingTemplates","filter","isSubset","sort","a","b","length","templateKey","localeCompare","drawSlots","demandRows","select","requiredLabels","queued","oldestQueuedAt","createdAt","from","where","groupBy","row","Date","capabilityLabels","listActiveWorkspaceCapabilityLabelsTx","windowSeconds","demand","some","activeReservationRows","reserved","expiresAt","reservedByLabels","Map","labelKey","activeProvisionerReservationRows","listActiveProvisionerReservationRowsTx","deductProvisionerReservations","grants","workspaceIdField","sortDemandRows","get","unreserved","Math","max","capacity","grant","min","reservedAfterGrant","idleRunners","listIdleRunnerInstancesTx","boundCount","boundReservation","insert","values","kind","returning","id","Error","bindIdleRunnerInstancesTx","reservationId","launchCount","launchReservation","inserted","candidateRows","candidateIds","reservationIds","activeRows","orderBy","for","activeIds","activeIdSet","Set","usedRunnerRows","intendedReservationId","reservationReleasedAt","state","usedByReservation","runner","has","addUsedRunner","used","size","pending","runnerId","runnerIds","add","set","canBindRunner","runnerSessionId","isBindableRunner","providerRunnerId","runnerInstanceId","closedAt","lockedRunners","selectIdleRunnerInstancesTx","launchKind","limit","retrySelection","Symbol","lockTx","candidateRunners","candidate","compareRunnerIds","error","idleRunnerIds","update","revokedAt","consumedAt","boundRunners","assignedAt","updatedAt","reboundCount","outcome","listQueuedDemandWorkspaceIds","innerJoin","advertisedAt","deleteExpiredReservations","expiredRows","deleteReservationsWithCleanupTx","expiredOnly","deleteReservationsByIds","ids","isAffectedRunner","affectedRunners","reservationRows","assignedRunnerIds","includes","intendedRunnerIds","deleted","delete","releaseReservationUnits","releaseByReservationId","release","releases","keys","releaseCount","join","decremented","releasedFromDecremented","decrementedIds","releasedFromDeleted","releaseTerminalRunnerInstanceReservationsByIds","providerRunnerIds","runnerInstanceIds","reservationWorkspacePredicate","noRunningJobPredicate","reportFreshnessPredicate","reportedAtByProviderRunnerId","reportedAt","runnerIdentityPredicate","reservationRowsToLock","requireTerminalState","reservationIdsToLock","releaseReservationId","releaseReservationWorkspaceId","requireUnlinkedSession","terminalRows","terminalState","updated","releasesByReservationId","updatedIds","key","releasesByWorkspaceId","released","activeReservations","sortReservationRows","left","right","specificity","getTime","availableLabels","every","label","remaining","JSON","stringify"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"runner-assignments.d.ts","sourceRoot":"","sources":["../../src/db/runner-assignments.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,mCAAmC,EACxC,KAAK,uBAAuB,EAE7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,SAAS,CAAC;AAQhC,gGAAgG;AAChG,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOpB;AAED,UAAU,6BAA6B;IACrC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,0BAA0B,EAAE,mCAAmC,EAAE,CAAC;CACnE;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,uBAAuB,CAAC;CAClC,GACA,OAAO,CAAC,6BAA6B,CAAC,CAqLxC;AAED,MAAM,MAAM,sCAAsC,GAC9C,uBAAuB,GACvB,2BAA2B,GAC3B,qBAAqB,GACrB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,mCAAmC;IAClD,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,wBAAwB,EAAE,GAAG,CAC3B,MAAM,EACN;QAAC,MAAM,EAAE,sCAAsC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAChE,CAAC;CACH;AAED,wBAAsB,mCAAmC,CACvD,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;CAC7D,EACD,OAAO,GAAE;IAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAM,GAC1C,OAAO,CAAC,mCAAmC,CAAC,CAmI9C"}
1
+ {"version":3,"file":"runner-assignments.d.ts","sourceRoot":"","sources":["../../src/db/runner-assignments.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,mCAAmC,EACxC,KAAK,uBAAuB,EAE7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,SAAS,CAAC;AAQhC,gGAAgG;AAChG,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOpB;AAED,UAAU,6BAA6B;IACrC,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,0BAA0B,EAAE,mCAAmC,EAAE,CAAC;CACnE;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,EAAE,uBAAuB,CAAC;CAClC,GACA,OAAO,CAAC,6BAA6B,CAAC,CAsLxC;AAED,MAAM,MAAM,sCAAsC,GAC9C,uBAAuB,GACvB,2BAA2B,GAC3B,qBAAqB,GACrB,oBAAoB,CAAC;AAEzB,MAAM,WAAW,mCAAmC;IAClD,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,wBAAwB,EAAE,GAAG,CAC3B,MAAM,EACN;QAAC,MAAM,EAAE,sCAAsC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAChE,CAAC;CACH;AAED,wBAAsB,mCAAmC,CACvD,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,SAAS;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;CAC7D,EACD,OAAO,GAAE;IAAC,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAAM,GAC1C,OAAO,CAAC,mCAAmC,CAAC,CAiI9C"}
@@ -73,7 +73,9 @@ export async function assignRunnerInstancesTx(tx, params) {
73
73
  const newRunnerIds = newRunners.map((runner)=>runner.id);
74
74
  const assignedCount = await tx.select({
75
75
  count: sql`count(*)::int`
76
- }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), notInArray(providerRunners.id, newRunnerIds), or(and(eq(providerRunners.reservationId, reservation.id), isNull(providerRunners.reservationReleasedAt)), and(eq(providerRunners.intendedReservationId, reservation.id), isNull(providerRunners.reservationReleasedAt), notInArray(providerRunners.state, [
76
+ }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), notInArray(providerRunners.id, newRunnerIds), or(and(eq(providerRunners.reservationId, reservation.id), isNull(providerRunners.reservationReleasedAt), notInArray(providerRunners.state, [
77
+ ...terminalStates
78
+ ])), and(eq(providerRunners.intendedReservationId, reservation.id), isNull(providerRunners.reservationReleasedAt), notInArray(providerRunners.state, [
77
79
  ...terminalStates
78
80
  ])))));
79
81
  if ((assignedCount[0]?.count ?? 0) + newRunners.length > reservation.count) throw new RunnerInstanceNotAssignableError(newRunners[0]?.id ?? '', 'capacity-exhausted');
@@ -157,9 +159,10 @@ export async function validateRunnerReservationCapacityTx(tx, params, options =
157
159
  const usedRunnerRows = await tx.select({
158
160
  id: providerRunners.id,
159
161
  reservationId: providerRunners.reservationId,
160
- intendedReservationId: providerRunners.intendedReservationId,
161
- state: providerRunners.state
162
- }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), isNull(providerRunners.reservationReleasedAt), or(inArray(providerRunners.reservationId, reservationIds), and(inArray(providerRunners.intendedReservationId, reservationIds), notInArray(providerRunners.state, [
162
+ intendedReservationId: providerRunners.intendedReservationId
163
+ }).from(providerRunners).where(and(eq(providerRunners.provisionerId, params.provisionerId), isNull(providerRunners.reservationReleasedAt), or(and(inArray(providerRunners.reservationId, reservationIds), notInArray(providerRunners.state, [
164
+ ...terminalStates
165
+ ])), and(inArray(providerRunners.intendedReservationId, reservationIds), notInArray(providerRunners.state, [
163
166
  ...terminalStates
164
167
  ])))));
165
168
  for (const runner of usedRunnerRows){
@@ -168,7 +171,7 @@ export async function validateRunnerReservationCapacityTx(tx, params, options =
168
171
  usedRunnerIds.add(runner.id);
169
172
  usedRunnerIdsByReservation.set(runner.reservationId, usedRunnerIds);
170
173
  }
171
- if (runner.intendedReservationId && requestedReservationIds.has(runner.intendedReservationId) && !terminalStates.includes(runner.state)) {
174
+ if (runner.intendedReservationId && requestedReservationIds.has(runner.intendedReservationId)) {
172
175
  const usedRunnerIds = usedRunnerIdsByReservation.get(runner.intendedReservationId) ?? new Set();
173
176
  usedRunnerIds.add(runner.id);
174
177
  usedRunnerIdsByReservation.set(runner.intendedReservationId, usedRunnerIds);