@shipfox/api-runners 12.7.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +12 -0
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/job-executions.d.ts +8 -24
- package/dist/db/job-executions.d.ts.map +1 -1
- package/dist/db/job-executions.js +62 -81
- package/dist/db/job-executions.js.map +1 -1
- package/dist/db/reservations.d.ts.map +1 -1
- package/dist/db/reservations.js +6 -4
- package/dist/db/reservations.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/presentation/index.d.ts +2 -1
- package/dist/presentation/index.d.ts.map +1 -1
- package/dist/presentation/index.js +2 -1
- package/dist/presentation/index.js.map +1 -1
- package/dist/presentation/inter-module.d.ts +0 -1
- package/dist/presentation/inter-module.d.ts.map +1 -1
- package/dist/presentation/inter-module.js +2 -25
- package/dist/presentation/inter-module.js.map +1 -1
- package/dist/presentation/subscribers/on-workflows-job-execution-queued.d.ts +3 -0
- package/dist/presentation/subscribers/on-workflows-job-execution-queued.d.ts.map +1 -0
- package/dist/presentation/subscribers/on-workflows-job-execution-queued.js +21 -0
- package/dist/presentation/subscribers/on-workflows-job-execution-queued.js.map +1 -0
- package/dist/presentation/subscribers/on-workflows-job-execution-terminated.d.ts +3 -0
- package/dist/presentation/subscribers/on-workflows-job-execution-terminated.d.ts.map +1 -0
- package/dist/presentation/subscribers/{on-workflows-job-execution-timed-out.js → on-workflows-job-execution-terminated.js} +5 -4
- package/dist/presentation/subscribers/on-workflows-job-execution-terminated.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/db/index.ts +0 -2
- package/src/db/job-executions.test.ts +105 -335
- package/src/db/job-executions.ts +70 -91
- package/src/db/reservations.ts +6 -3
- package/src/db/runner-instances.test.ts +100 -0
- package/src/index.test.ts +1 -0
- package/src/index.ts +8 -7
- package/src/presentation/index.ts +2 -1
- package/src/presentation/inter-module.ts +2 -40
- package/src/presentation/subscribers/on-workflows-job-execution-queued.test.ts +57 -0
- package/src/presentation/subscribers/on-workflows-job-execution-queued.ts +26 -0
- package/src/presentation/subscribers/on-workflows-job-execution-terminated.test.ts +142 -0
- package/src/presentation/subscribers/{on-workflows-job-execution-timed-out.ts → on-workflows-job-execution-terminated.ts} +5 -4
- package/test/factories/pending-job.ts +3 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/presentation/subscribers/on-workflows-job-execution-timed-out.d.ts +0 -3
- package/dist/presentation/subscribers/on-workflows-job-execution-timed-out.d.ts.map +0 -1
- package/dist/presentation/subscribers/on-workflows-job-execution-timed-out.js.map +0 -1
- package/src/presentation/inter-module.test.ts +0 -15
- package/src/presentation/subscribers/on-workflows-job-execution-timed-out.test.ts +0 -163
|
@@ -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 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
|
+
{"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 // Cancellation keeps the lease row so the provisioner can observe its terminate intent.\n // Once the runner is terminal, only an uncancelled lease should block reservation release.\n const noUncancelledRunningJobPredicate = 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 isNull(runningJobExecutions.cancellationRequestedAt),\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 noUncancelledRunningJobPredicate,\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 noUncancelledRunningJobPredicate,\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","noUncancelledRunningJobPredicate","cancellationRequestedAt","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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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AuthInterModuleClient } from '@shipfox/api-auth-dto/inter-module';
|
|
|
2
2
|
import { type ShipfoxModule } from '@shipfox/node-module';
|
|
3
3
|
import type { CreateRunnersModuleOptions } from '#installation-provisioning.js';
|
|
4
4
|
export { type EffectiveRunnerToolCapabilitiesResult, getEffectiveRunnerToolCapabilities, unadvertisedRunnerTools, } from '#core/runner-tool-capabilities.js';
|
|
5
|
-
export {
|
|
5
|
+
export { getWorkspaceJobCounts, isJobLeaseActive, } from '#db/index.js';
|
|
6
6
|
export type { CreateRunnersModuleOptions, InstallationProvisioningPolicy, } from '#installation-provisioning.js';
|
|
7
7
|
export declare function createRunnersModule({ auth, ...options }: CreateRunnersModuleOptions & {
|
|
8
8
|
auth: AuthInterModuleClient;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;AAQ9E,OAAO,EAAC,KAAK,aAAa,EAAoB,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;AAgB9E,OAAO,EACL,KAAK,qCAAqC,EAC1C,kCAAkC,EAClC,uBAAuB,GACxB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,0BAA0B,EAC1B,8BAA8B,GAC/B,MAAM,+BAA+B,CAAC;AAOvC,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,GAAG,OAAO,EACX,EAAE,0BAA0B,GAAG;IAAC,IAAI,EAAE,qBAAqB,CAAA;CAAC,GAAG,aAAa,CA8B5E"}
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,11 @@ import { dirname, resolve } from 'node:path';
|
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
3
|
import { administrationActionEventSchemas } from '@shipfox/api-common-dto';
|
|
4
4
|
import { runnersEventSchemas } from '@shipfox/api-runners-dto';
|
|
5
|
-
import {
|
|
5
|
+
import { WORKFLOWS_JOB_EXECUTION_QUEUED, WORKFLOWS_JOB_EXECUTION_TERMINATED } from '@shipfox/api-workflows-dto';
|
|
6
6
|
import { subscriberFactory } from '@shipfox/node-module';
|
|
7
7
|
import { db, migrationsPath, runnersOutbox } from '#db/index.js';
|
|
8
8
|
import { registerRunnersServiceMetrics } from '#metrics/index.js';
|
|
9
|
-
import { createProvisionerTokenAuthMethod, createRunnerControlSessionAuthMethod, createRunnerRegistrationTokenAuthMethod, createRunnerRoutes,
|
|
9
|
+
import { createProvisionerTokenAuthMethod, createRunnerControlSessionAuthMethod, createRunnerRegistrationTokenAuthMethod, createRunnerRoutes, onWorkflowsJobExecutionQueued, onWorkflowsJobExecutionTerminated } from '#presentation/index.js';
|
|
10
10
|
import { createRunnersInterModulePresentation } from '#presentation/inter-module.js';
|
|
11
11
|
import { createRunnersMaintenanceActivities } from '#temporal/activities/index.js';
|
|
12
12
|
import { RUNNERS_MAINTENANCE_TASK_QUEUE } from '#temporal/constants.js';
|
|
@@ -15,7 +15,7 @@ const runnersPublisherEventSchemas = {
|
|
|
15
15
|
...administrationActionEventSchemas
|
|
16
16
|
};
|
|
17
17
|
export { getEffectiveRunnerToolCapabilities, unadvertisedRunnerTools } from '#core/runner-tool-capabilities.js';
|
|
18
|
-
export {
|
|
18
|
+
export { getWorkspaceJobCounts, isJobLeaseActive } from '#db/index.js';
|
|
19
19
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
20
20
|
const workflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');
|
|
21
21
|
const subscriber = subscriberFactory();
|
|
@@ -43,7 +43,8 @@ export function createRunnersModule({ auth, ...options }) {
|
|
|
43
43
|
}
|
|
44
44
|
],
|
|
45
45
|
subscribers: [
|
|
46
|
-
subscriber(
|
|
46
|
+
subscriber(WORKFLOWS_JOB_EXECUTION_QUEUED, onWorkflowsJobExecutionQueued),
|
|
47
|
+
subscriber(WORKFLOWS_JOB_EXECUTION_TERMINATED, onWorkflowsJobExecutionTerminated)
|
|
47
48
|
],
|
|
48
49
|
workers: [
|
|
49
50
|
{
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport type {AuthInterModuleClient} from '@shipfox/api-auth-dto/inter-module';\nimport {administrationActionEventSchemas} from '@shipfox/api-common-dto';\nimport {runnersEventSchemas} from '@shipfox/api-runners-dto';\nimport {\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {dirname, resolve} from 'node:path';\nimport {fileURLToPath} from 'node:url';\nimport type {AuthInterModuleClient} from '@shipfox/api-auth-dto/inter-module';\nimport {administrationActionEventSchemas} from '@shipfox/api-common-dto';\nimport {runnersEventSchemas} from '@shipfox/api-runners-dto';\nimport {\n WORKFLOWS_JOB_EXECUTION_QUEUED,\n WORKFLOWS_JOB_EXECUTION_TERMINATED,\n type WorkflowsEventMapDto,\n} from '@shipfox/api-workflows-dto';\nimport {type ShipfoxModule, subscriberFactory} from '@shipfox/node-module';\nimport {db, migrationsPath, runnersOutbox} from '#db/index.js';\nimport type {CreateRunnersModuleOptions} from '#installation-provisioning.js';\nimport {registerRunnersServiceMetrics} from '#metrics/index.js';\nimport {\n createProvisionerTokenAuthMethod,\n createRunnerControlSessionAuthMethod,\n createRunnerRegistrationTokenAuthMethod,\n createRunnerRoutes,\n onWorkflowsJobExecutionQueued,\n onWorkflowsJobExecutionTerminated,\n} from '#presentation/index.js';\nimport {createRunnersInterModulePresentation} from '#presentation/inter-module.js';\nimport {createRunnersMaintenanceActivities} from '#temporal/activities/index.js';\nimport {RUNNERS_MAINTENANCE_TASK_QUEUE} from '#temporal/constants.js';\n\nconst runnersPublisherEventSchemas = {...runnersEventSchemas, ...administrationActionEventSchemas};\n\nexport {\n type EffectiveRunnerToolCapabilitiesResult,\n getEffectiveRunnerToolCapabilities,\n unadvertisedRunnerTools,\n} from '#core/runner-tool-capabilities.js';\nexport {\n getWorkspaceJobCounts,\n isJobLeaseActive,\n} from '#db/index.js';\nexport type {\n CreateRunnersModuleOptions,\n InstallationProvisioningPolicy,\n} from '#installation-provisioning.js';\n\nconst packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst workflowsPath = resolve(packageRoot, 'dist/temporal/workflows/index.js');\n\nconst subscriber = subscriberFactory<WorkflowsEventMapDto>();\n\nexport function createRunnersModule({\n auth,\n ...options\n}: CreateRunnersModuleOptions & {auth: AuthInterModuleClient}): ShipfoxModule {\n return {\n name: 'runners',\n database: {db, migrationsPath, databaseNamespace: 'runners'},\n auth: [\n createRunnerRegistrationTokenAuthMethod(),\n createRunnerControlSessionAuthMethod(),\n createProvisionerTokenAuthMethod(),\n ],\n routes: createRunnerRoutes(auth, options),\n metrics: registerRunnersServiceMetrics,\n publishers: [\n {name: 'runners', table: runnersOutbox, db, eventSchemas: runnersPublisherEventSchemas},\n ],\n subscribers: [\n subscriber(WORKFLOWS_JOB_EXECUTION_QUEUED, onWorkflowsJobExecutionQueued),\n subscriber(WORKFLOWS_JOB_EXECUTION_TERMINATED, onWorkflowsJobExecutionTerminated),\n ],\n workers: [\n {\n taskQueue: RUNNERS_MAINTENANCE_TASK_QUEUE,\n workflowsPath,\n activities: createRunnersMaintenanceActivities,\n workflows: [\n {name: 'stuckJobDetector', id: 'stuck-job-detector', cronSchedule: '* * * * *'},\n ],\n },\n ],\n interModulePresentations: [createRunnersInterModulePresentation()],\n };\n}\n"],"names":["dirname","resolve","fileURLToPath","administrationActionEventSchemas","runnersEventSchemas","WORKFLOWS_JOB_EXECUTION_QUEUED","WORKFLOWS_JOB_EXECUTION_TERMINATED","subscriberFactory","db","migrationsPath","runnersOutbox","registerRunnersServiceMetrics","createProvisionerTokenAuthMethod","createRunnerControlSessionAuthMethod","createRunnerRegistrationTokenAuthMethod","createRunnerRoutes","onWorkflowsJobExecutionQueued","onWorkflowsJobExecutionTerminated","createRunnersInterModulePresentation","createRunnersMaintenanceActivities","RUNNERS_MAINTENANCE_TASK_QUEUE","runnersPublisherEventSchemas","getEffectiveRunnerToolCapabilities","unadvertisedRunnerTools","getWorkspaceJobCounts","isJobLeaseActive","packageRoot","url","workflowsPath","subscriber","createRunnersModule","auth","options","name","database","databaseNamespace","routes","metrics","publishers","table","eventSchemas","subscribers","workers","taskQueue","activities","workflows","id","cronSchedule","interModulePresentations"],"mappings":"AAAA,SAAQA,OAAO,EAAEC,OAAO,QAAO,YAAY;AAC3C,SAAQC,aAAa,QAAO,WAAW;AAEvC,SAAQC,gCAAgC,QAAO,0BAA0B;AACzE,SAAQC,mBAAmB,QAAO,2BAA2B;AAC7D,SACEC,8BAA8B,EAC9BC,kCAAkC,QAE7B,6BAA6B;AACpC,SAA4BC,iBAAiB,QAAO,uBAAuB;AAC3E,SAAQC,EAAE,EAAEC,cAAc,EAAEC,aAAa,QAAO,eAAe;AAE/D,SAAQC,6BAA6B,QAAO,oBAAoB;AAChE,SACEC,gCAAgC,EAChCC,oCAAoC,EACpCC,uCAAuC,EACvCC,kBAAkB,EAClBC,6BAA6B,EAC7BC,iCAAiC,QAC5B,yBAAyB;AAChC,SAAQC,oCAAoC,QAAO,gCAAgC;AACnF,SAAQC,kCAAkC,QAAO,gCAAgC;AACjF,SAAQC,8BAA8B,QAAO,yBAAyB;AAEtE,MAAMC,+BAA+B;IAAC,GAAGjB,mBAAmB;IAAE,GAAGD,gCAAgC;AAAA;AAEjG,SAEEmB,kCAAkC,EAClCC,uBAAuB,QAClB,oCAAoC;AAC3C,SACEC,qBAAqB,EACrBC,gBAAgB,QACX,eAAe;AAMtB,MAAMC,cAAczB,QAAQD,QAAQE,cAAc,YAAYyB,GAAG,IAAI;AACrE,MAAMC,gBAAgB3B,QAAQyB,aAAa;AAE3C,MAAMG,aAAatB;AAEnB,OAAO,SAASuB,oBAAoB,EAClCC,IAAI,EACJ,GAAGC,SACwD;IAC3D,OAAO;QACLC,MAAM;QACNC,UAAU;YAAC1B;YAAIC;YAAgB0B,mBAAmB;QAAS;QAC3DJ,MAAM;YACJjB;YACAD;YACAD;SACD;QACDwB,QAAQrB,mBAAmBgB,MAAMC;QACjCK,SAAS1B;QACT2B,YAAY;YACV;gBAACL,MAAM;gBAAWM,OAAO7B;gBAAeF;gBAAIgC,cAAcnB;YAA4B;SACvF;QACDoB,aAAa;YACXZ,WAAWxB,gCAAgCW;YAC3Ca,WAAWvB,oCAAoCW;SAChD;QACDyB,SAAS;YACP;gBACEC,WAAWvB;gBACXQ;gBACAgB,YAAYzB;gBACZ0B,WAAW;oBACT;wBAACZ,MAAM;wBAAoBa,IAAI;wBAAsBC,cAAc;oBAAW;iBAC/E;YACH;SACD;QACDC,0BAA0B;YAAC9B;SAAuC;IACpE;AACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { createProvisionerTokenAuthMethod, createRunnerControlSessionAuthMethod, createRunnerRegistrationTokenAuthMethod, } from './auth/index.js';
|
|
2
2
|
export { createRunnerRoutes, createRunnerRoutes as routes } from './routes/index.js';
|
|
3
|
-
export {
|
|
3
|
+
export { onWorkflowsJobExecutionQueued } from './subscribers/on-workflows-job-execution-queued.js';
|
|
4
|
+
export { onWorkflowsJobExecutionTerminated } from './subscribers/on-workflows-job-execution-terminated.js';
|
|
4
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,oCAAoC,EACpC,uCAAuC,GACxC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,kBAAkB,EAAE,kBAAkB,IAAI,MAAM,EAAC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAC
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/presentation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,oCAAoC,EACpC,uCAAuC,GACxC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAC,kBAAkB,EAAE,kBAAkB,IAAI,MAAM,EAAC,MAAM,mBAAmB,CAAC;AACnF,OAAO,EAAC,6BAA6B,EAAC,MAAM,oDAAoD,CAAC;AACjG,OAAO,EAAC,iCAAiC,EAAC,MAAM,wDAAwD,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createProvisionerTokenAuthMethod, createRunnerControlSessionAuthMethod, createRunnerRegistrationTokenAuthMethod } from './auth/index.js';
|
|
2
2
|
export { createRunnerRoutes, createRunnerRoutes as routes } from './routes/index.js';
|
|
3
|
-
export {
|
|
3
|
+
export { onWorkflowsJobExecutionQueued } from './subscribers/on-workflows-job-execution-queued.js';
|
|
4
|
+
export { onWorkflowsJobExecutionTerminated } from './subscribers/on-workflows-job-execution-terminated.js';
|
|
4
5
|
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/presentation/index.ts"],"sourcesContent":["export {\n createProvisionerTokenAuthMethod,\n createRunnerControlSessionAuthMethod,\n createRunnerRegistrationTokenAuthMethod,\n} from './auth/index.js';\nexport {createRunnerRoutes, createRunnerRoutes as routes} from './routes/index.js';\nexport {
|
|
1
|
+
{"version":3,"sources":["../../src/presentation/index.ts"],"sourcesContent":["export {\n createProvisionerTokenAuthMethod,\n createRunnerControlSessionAuthMethod,\n createRunnerRegistrationTokenAuthMethod,\n} from './auth/index.js';\nexport {createRunnerRoutes, createRunnerRoutes as routes} from './routes/index.js';\nexport {onWorkflowsJobExecutionQueued} from './subscribers/on-workflows-job-execution-queued.js';\nexport {onWorkflowsJobExecutionTerminated} from './subscribers/on-workflows-job-execution-terminated.js';\n"],"names":["createProvisionerTokenAuthMethod","createRunnerControlSessionAuthMethod","createRunnerRegistrationTokenAuthMethod","createRunnerRoutes","routes","onWorkflowsJobExecutionQueued","onWorkflowsJobExecutionTerminated"],"mappings":"AAAA,SACEA,gCAAgC,EAChCC,oCAAoC,EACpCC,uCAAuC,QAClC,kBAAkB;AACzB,SAAQC,kBAAkB,EAAEA,sBAAsBC,MAAM,QAAO,oBAAoB;AACnF,SAAQC,6BAA6B,QAAO,qDAAqD;AACjG,SAAQC,iCAAiC,QAAO,yDAAyD"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { runnersInterModuleContract } from '@shipfox/api-runners-dto/inter-module';
|
|
2
2
|
import { type InterModulePresentation } from '@shipfox/inter-module';
|
|
3
3
|
export declare function createRunnersInterModulePresentation(): InterModulePresentation<typeof runnersInterModuleContract>;
|
|
4
|
-
export declare function toEnqueueJobExecutionKnownError(error: unknown): unknown;
|
|
5
4
|
//# sourceMappingURL=inter-module.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inter-module.d.ts","sourceRoot":"","sources":["../../src/presentation/inter-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,0BAA0B,EAAC,MAAM,uCAAuC,CAAC;AACjF,OAAO,
|
|
1
|
+
{"version":3,"file":"inter-module.d.ts","sourceRoot":"","sources":["../../src/presentation/inter-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,0BAA0B,EAAC,MAAM,uCAAuC,CAAC;AACjF,OAAO,EAAgC,KAAK,uBAAuB,EAAC,MAAM,uBAAuB,CAAC;AAIlG,wBAAgB,oCAAoC,IAAI,uBAAuB,CAC7E,OAAO,0BAA0B,CAClC,CAWA"}
|
|
@@ -1,26 +1,9 @@
|
|
|
1
1
|
import { runnersInterModuleContract } from '@shipfox/api-runners-dto/inter-module';
|
|
2
|
-
import {
|
|
3
|
-
import { EmptyRequiredLabelsError } from '#core/errors.js';
|
|
2
|
+
import { defineInterModulePresentation } from '@shipfox/inter-module';
|
|
4
3
|
import { getEffectiveRunnerToolCapabilities } from '#core/runner-tool-capabilities.js';
|
|
5
|
-
import {
|
|
4
|
+
import { getWorkspaceJobCounts, isJobLeaseActive } from '#db/job-executions.js';
|
|
6
5
|
export function createRunnersInterModulePresentation() {
|
|
7
6
|
return defineInterModulePresentation(runnersInterModuleContract, {
|
|
8
|
-
enqueueJobExecution: async (input)=>{
|
|
9
|
-
try {
|
|
10
|
-
await enqueueJobExecution(input);
|
|
11
|
-
return {};
|
|
12
|
-
} catch (error) {
|
|
13
|
-
throw toEnqueueJobExecutionKnownError(error);
|
|
14
|
-
}
|
|
15
|
-
},
|
|
16
|
-
releaseJobExecution: async (input)=>{
|
|
17
|
-
await releaseJobExecution(input);
|
|
18
|
-
return {};
|
|
19
|
-
},
|
|
20
|
-
cancelJobs: async (input)=>{
|
|
21
|
-
await cancelRunnerJobs(input);
|
|
22
|
-
return {};
|
|
23
|
-
},
|
|
24
7
|
getLeaseState: async (input)=>({
|
|
25
8
|
active: await isJobLeaseActive(input)
|
|
26
9
|
}),
|
|
@@ -38,11 +21,5 @@ export function createRunnersInterModulePresentation() {
|
|
|
38
21
|
})
|
|
39
22
|
});
|
|
40
23
|
}
|
|
41
|
-
export function toEnqueueJobExecutionKnownError(error) {
|
|
42
|
-
if (error instanceof EmptyRequiredLabelsError) {
|
|
43
|
-
return createInterModuleKnownError(runnersInterModuleContract.methods.enqueueJobExecution, 'empty-required-labels', {});
|
|
44
|
-
}
|
|
45
|
-
return error;
|
|
46
|
-
}
|
|
47
24
|
|
|
48
25
|
//# sourceMappingURL=inter-module.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {runnersInterModuleContract} from '@shipfox/api-runners-dto/inter-module';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../src/presentation/inter-module.ts"],"sourcesContent":["import {runnersInterModuleContract} from '@shipfox/api-runners-dto/inter-module';\nimport {defineInterModulePresentation, type InterModulePresentation} from '@shipfox/inter-module';\nimport {getEffectiveRunnerToolCapabilities} from '#core/runner-tool-capabilities.js';\nimport {getWorkspaceJobCounts, isJobLeaseActive} from '#db/job-executions.js';\n\nexport function createRunnersInterModulePresentation(): InterModulePresentation<\n typeof runnersInterModuleContract\n> {\n return defineInterModulePresentation(runnersInterModuleContract, {\n getLeaseState: async (input) => ({active: await isJobLeaseActive(input)}),\n getEffectiveRunnerToolCapabilities: async (input) => {\n const result = await getEffectiveRunnerToolCapabilities(input);\n return {capabilities: result.capabilities, reportFresh: result.reportFresh};\n },\n getWorkspaceJobCounts: async ({workspaceIds}) => ({\n counts: await getWorkspaceJobCounts({workspaceIds}),\n }),\n });\n}\n"],"names":["runnersInterModuleContract","defineInterModulePresentation","getEffectiveRunnerToolCapabilities","getWorkspaceJobCounts","isJobLeaseActive","createRunnersInterModulePresentation","getLeaseState","input","active","result","capabilities","reportFresh","workspaceIds","counts"],"mappings":"AAAA,SAAQA,0BAA0B,QAAO,wCAAwC;AACjF,SAAQC,6BAA6B,QAAqC,wBAAwB;AAClG,SAAQC,kCAAkC,QAAO,oCAAoC;AACrF,SAAQC,qBAAqB,EAAEC,gBAAgB,QAAO,wBAAwB;AAE9E,OAAO,SAASC;IAGd,OAAOJ,8BAA8BD,4BAA4B;QAC/DM,eAAe,OAAOC,QAAW,CAAA;gBAACC,QAAQ,MAAMJ,iBAAiBG;YAAM,CAAA;QACvEL,oCAAoC,OAAOK;YACzC,MAAME,SAAS,MAAMP,mCAAmCK;YACxD,OAAO;gBAACG,cAAcD,OAAOC,YAAY;gBAAEC,aAAaF,OAAOE,WAAW;YAAA;QAC5E;QACAR,uBAAuB,OAAO,EAACS,YAAY,EAAC,GAAM,CAAA;gBAChDC,QAAQ,MAAMV,sBAAsB;oBAACS;gBAAY;YACnD,CAAA;IACF;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-workflows-job-execution-queued.d.ts","sourceRoot":"","sources":["../../../src/presentation/subscribers/on-workflows-job-execution-queued.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mCAAmC,EAAC,MAAM,4BAA4B,CAAC;AAIpF,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,mCAAmC,GAC3C,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { logger } from '@shipfox/node-opentelemetry';
|
|
2
|
+
import { enqueueJobExecution } from '#db/job-executions.js';
|
|
3
|
+
export async function onWorkflowsJobExecutionQueued(payload) {
|
|
4
|
+
logger().info({
|
|
5
|
+
jobId: payload.jobId,
|
|
6
|
+
jobExecutionId: payload.jobExecutionId,
|
|
7
|
+
workflowRunAttemptId: payload.workflowRunAttemptId
|
|
8
|
+
}, 'Queueing runner job execution from workflow fact');
|
|
9
|
+
await enqueueJobExecution({
|
|
10
|
+
workspaceId: payload.workspaceId,
|
|
11
|
+
workflowRunId: payload.workflowRunId,
|
|
12
|
+
workflowRunAttemptId: payload.workflowRunAttemptId,
|
|
13
|
+
jobId: payload.jobId,
|
|
14
|
+
jobExecutionId: payload.jobExecutionId,
|
|
15
|
+
projectId: payload.projectId,
|
|
16
|
+
requiredLabels: payload.requiredLabels,
|
|
17
|
+
queuedAt: new Date(payload.queuedAt)
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=on-workflows-job-execution-queued.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/subscribers/on-workflows-job-execution-queued.ts"],"sourcesContent":["import type {WorkflowsJobExecutionQueuedEventDto} from '@shipfox/api-workflows-dto';\nimport {logger} from '@shipfox/node-opentelemetry';\nimport {enqueueJobExecution} from '#db/job-executions.js';\n\nexport async function onWorkflowsJobExecutionQueued(\n payload: WorkflowsJobExecutionQueuedEventDto,\n): Promise<void> {\n logger().info(\n {\n jobId: payload.jobId,\n jobExecutionId: payload.jobExecutionId,\n workflowRunAttemptId: payload.workflowRunAttemptId,\n },\n 'Queueing runner job execution from workflow fact',\n );\n await enqueueJobExecution({\n workspaceId: payload.workspaceId,\n workflowRunId: payload.workflowRunId,\n workflowRunAttemptId: payload.workflowRunAttemptId,\n jobId: payload.jobId,\n jobExecutionId: payload.jobExecutionId,\n projectId: payload.projectId,\n requiredLabels: payload.requiredLabels,\n queuedAt: new Date(payload.queuedAt),\n });\n}\n"],"names":["logger","enqueueJobExecution","onWorkflowsJobExecutionQueued","payload","info","jobId","jobExecutionId","workflowRunAttemptId","workspaceId","workflowRunId","projectId","requiredLabels","queuedAt","Date"],"mappings":"AACA,SAAQA,MAAM,QAAO,8BAA8B;AACnD,SAAQC,mBAAmB,QAAO,wBAAwB;AAE1D,OAAO,eAAeC,8BACpBC,OAA4C;IAE5CH,SAASI,IAAI,CACX;QACEC,OAAOF,QAAQE,KAAK;QACpBC,gBAAgBH,QAAQG,cAAc;QACtCC,sBAAsBJ,QAAQI,oBAAoB;IACpD,GACA;IAEF,MAAMN,oBAAoB;QACxBO,aAAaL,QAAQK,WAAW;QAChCC,eAAeN,QAAQM,aAAa;QACpCF,sBAAsBJ,QAAQI,oBAAoB;QAClDF,OAAOF,QAAQE,KAAK;QACpBC,gBAAgBH,QAAQG,cAAc;QACtCI,WAAWP,QAAQO,SAAS;QAC5BC,gBAAgBR,QAAQQ,cAAc;QACtCC,UAAU,IAAIC,KAAKV,QAAQS,QAAQ;IACrC;AACF"}
|