@shipfox/api-runners 6.0.0 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +19 -0
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/core/entities/runner-instance.d.ts +1 -0
- package/dist/core/entities/runner-instance.d.ts.map +1 -1
- package/dist/core/entities/runner-instance.js.map +1 -1
- package/dist/core/errors.d.ts +6 -6
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +8 -8
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +2 -4
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/runner-assignments.d.ts +6 -0
- package/dist/core/runner-assignments.d.ts.map +1 -0
- package/dist/core/runner-assignments.js +6 -0
- package/dist/core/runner-assignments.js.map +1 -0
- package/dist/core/runner-instances.d.ts +2 -9
- package/dist/core/runner-instances.d.ts.map +1 -1
- package/dist/core/runner-instances.js +3 -6
- package/dist/core/runner-instances.js.map +1 -1
- package/dist/db/db.d.ts +34 -218
- package/dist/db/db.d.ts.map +1 -1
- package/dist/db/db.js +0 -2
- package/dist/db/db.js.map +1 -1
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +2 -2
- package/dist/db/index.js.map +1 -1
- package/dist/db/runner-assignments.d.ts +7 -0
- package/dist/db/runner-assignments.d.ts.map +1 -0
- package/dist/db/runner-assignments.js +55 -0
- package/dist/db/runner-assignments.js.map +1 -0
- package/dist/db/runner-instances.d.ts +2 -9
- package/dist/db/runner-instances.d.ts.map +1 -1
- package/dist/db/runner-instances.js +2 -16
- package/dist/db/runner-instances.js.map +1 -1
- package/dist/db/schema/runner-instances.d.ts +17 -0
- package/dist/db/schema/runner-instances.d.ts.map +1 -1
- package/dist/db/schema/runner-instances.js +5 -1
- package/dist/db/schema/runner-instances.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/presentation/dto/index.d.ts +0 -1
- package/dist/presentation/dto/index.d.ts.map +1 -1
- package/dist/presentation/dto/index.js +0 -1
- package/dist/presentation/dto/index.js.map +1 -1
- package/dist/presentation/routes/assign-runner-instances.d.ts +2 -0
- package/dist/presentation/routes/assign-runner-instances.d.ts.map +1 -0
- package/dist/presentation/routes/assign-runner-instances.js +40 -0
- package/dist/presentation/routes/assign-runner-instances.js.map +1 -0
- package/dist/presentation/routes/index.d.ts.map +1 -1
- package/dist/presentation/routes/index.js +4 -8
- package/dist/presentation/routes/index.js.map +1 -1
- package/dist/presentation/routes/runner-enrollment.d.ts +1 -0
- package/dist/presentation/routes/runner-enrollment.d.ts.map +1 -1
- package/dist/presentation/routes/runner-enrollment.js +27 -0
- package/dist/presentation/routes/runner-enrollment.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0000_initial.sql +1 -12
- package/drizzle/meta/0000_snapshot.json +6 -97
- package/package.json +10 -10
- package/src/config.ts +1 -1
- package/src/core/entities/runner-instance.ts +1 -0
- package/src/core/errors.ts +8 -8
- package/src/core/index.ts +2 -9
- package/src/core/runner-assignments.ts +9 -0
- package/src/core/runner-instances.ts +4 -13
- package/src/db/db.ts +0 -2
- package/src/db/index.ts +2 -3
- package/src/db/runner-assignments.test.ts +163 -0
- package/src/db/runner-assignments.ts +115 -0
- package/src/db/runner-instances.test.ts +36 -23
- package/src/db/runner-instances.ts +3 -23
- package/src/db/schema/runner-instances.ts +3 -1
- package/src/index.ts +0 -9
- package/src/presentation/dto/index.ts +0 -4
- package/src/presentation/routes/assign-runner-instances.ts +49 -0
- package/src/presentation/routes/index.ts +4 -7
- package/src/presentation/routes/runner-enrollment.test.ts +60 -0
- package/src/presentation/routes/runner-enrollment.ts +22 -0
- package/test/globalSetup.ts +0 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/core/capacity-assignments.d.ts +0 -7
- package/dist/core/capacity-assignments.d.ts.map +0 -1
- package/dist/core/capacity-assignments.js +0 -6
- package/dist/core/capacity-assignments.js.map +0 -1
- package/dist/core/entities/capacity-assignment.d.ts +0 -9
- package/dist/core/entities/capacity-assignment.d.ts.map +0 -1
- package/dist/core/entities/capacity-assignment.js +0 -3
- package/dist/core/entities/capacity-assignment.js.map +0 -1
- package/dist/db/capacity-assignments.d.ts +0 -7
- package/dist/db/capacity-assignments.d.ts.map +0 -1
- package/dist/db/capacity-assignments.js +0 -72
- package/dist/db/capacity-assignments.js.map +0 -1
- package/dist/db/schema/capacity-assignments.d.ts +0 -113
- package/dist/db/schema/capacity-assignments.d.ts.map +0 -1
- package/dist/db/schema/capacity-assignments.js +0 -29
- package/dist/db/schema/capacity-assignments.js.map +0 -1
- package/dist/presentation/dto/mint-registration-tokens.d.ts +0 -7
- package/dist/presentation/dto/mint-registration-tokens.d.ts.map +0 -1
- package/dist/presentation/dto/mint-registration-tokens.js +0 -19
- package/dist/presentation/dto/mint-registration-tokens.js.map +0 -1
- package/dist/presentation/routes/assign-capacity.d.ts +0 -2
- package/dist/presentation/routes/assign-capacity.d.ts.map +0 -1
- package/dist/presentation/routes/assign-capacity.js +0 -44
- package/dist/presentation/routes/assign-capacity.js.map +0 -1
- package/dist/presentation/routes/mint-registration-tokens.d.ts +0 -2
- package/dist/presentation/routes/mint-registration-tokens.d.ts.map +0 -1
- package/dist/presentation/routes/mint-registration-tokens.js +0 -74
- package/dist/presentation/routes/mint-registration-tokens.js.map +0 -1
- package/dist/presentation/routes/planned-capacity.d.ts +0 -3
- package/dist/presentation/routes/planned-capacity.d.ts.map +0 -1
- package/dist/presentation/routes/planned-capacity.js +0 -54
- package/dist/presentation/routes/planned-capacity.js.map +0 -1
- package/src/core/capacity-assignments.ts +0 -10
- package/src/core/entities/capacity-assignment.ts +0 -8
- package/src/db/capacity-assignments.test.ts +0 -159
- package/src/db/capacity-assignments.ts +0 -116
- package/src/db/schema/capacity-assignments.ts +0 -34
- package/src/presentation/dto/mint-registration-tokens.ts +0 -28
- package/src/presentation/routes/assign-capacity.ts +0 -48
- package/src/presentation/routes/mint-registration-tokens.test.ts +0 -453
- package/src/presentation/routes/mint-registration-tokens.ts +0 -80
- package/src/presentation/routes/planned-capacity.ts +0 -49
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/db/runner-instances.ts"],"sourcesContent":["import {logger} from '@shipfox/node-opentelemetry';\nimport {canonicalizeLabels} from '@shipfox/runner-labels';\nimport {\n and,\n asc,\n desc,\n eq,\n exists,\n gt,\n inArray,\n isNotNull,\n isNull,\n lt,\n notExists,\n notInArray,\n or,\n type SQL,\n sql,\n} from 'drizzle-orm';\nimport {alias} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance, RunnerInstanceState} from '#core/entities/runner-instance.js';\nimport type {Tx} from './db.js';\nimport {db} from './db.js';\nimport {\n listRunningJobExecutionsByRunnerInstanceTx,\n type RunnerInstanceBoundJobExecution,\n} from './job-executions.js';\nimport {releaseReservationUnits} from './reservations.js';\nimport {ephemeralRegistrationTokens} from './schema/ephemeral-registration-tokens.js';\nimport {provisionerTokens} from './schema/provisioner-tokens.js';\nimport {providerRunners, toRunnerInstance} from './schema/runner-instances.js';\nimport {runnerSessions} from './schema/runner-sessions.js';\nimport {runningJobExecutions} from './schema/running-job-executions.js';\n\nexport const terminalStates = [\n 'stopped',\n 'failed',\n 'terminated',\n] as const satisfies readonly RunnerInstanceState[];\nexport const activeStates = [\n 'starting',\n 'running',\n 'stopping',\n] as const satisfies readonly RunnerInstanceState[];\nexport const divergenceCountStates = ['starting', 'running'] as const satisfies readonly Extract<\n RunnerInstanceState,\n 'starting' | 'running'\n>[];\n\nexport type RunnerInstanceTerminateIntentReason = 'job-cancelled';\n\nexport interface RunnerInstanceTerminateIntent {\n providerRunnerId: string;\n reason: RunnerInstanceTerminateIntentReason;\n}\n\nexport interface ActiveRunnerInstanceTemplateCount {\n templateKey: string;\n state: (typeof divergenceCountStates)[number];\n count: number;\n}\n\nexport interface RunnerInstanceReportEvent {\n providerRunnerId: string;\n reservationId: string | null;\n templateKey: string | null;\n labels: string[];\n state: RunnerInstanceState;\n reason: string | null;\n runnerSessionId: string | null;\n providerKind: string | null;\n reportedAt: Date;\n}\n\nexport interface ReportRunnerInstancesParams {\n workspaceId: string | null;\n provisionerId: string;\n events: RunnerInstanceReportEvent[];\n}\n\nexport interface ReconcileRunnerInstancesParams {\n workspaceId: string | null;\n provisionerId: string;\n observedRunnerInstanceIds: string[];\n terminateGraceSeconds: number;\n}\n\nexport interface ReconcileRunnerInstancesDbResult {\n observedRows: RunnerInstance[];\n boundJobExecutionsByRunnerInstanceId: Map<string, RunnerInstanceBoundJobExecution>;\n absentIds: string[];\n reservationsReleased: number;\n}\n\nexport interface ReapStaleRunnerInstancesResult {\n reaped: number;\n reservationsReleased: number;\n}\n\nexport async function createPlannedProvisionedCapacity(params: {\n provisionerId: string;\n providerKind: string | null;\n templateKey: string | null;\n}): Promise<{capacityId: string}> {\n const [row] = await db()\n .insert(providerRunners)\n .values({\n provisionerId: params.provisionerId,\n providerKind: params.providerKind,\n templateKey: params.templateKey,\n state: 'starting',\n labels: [],\n reportedAt: new Date(),\n })\n .returning({capacityId: providerRunners.id});\n if (!row) throw new Error('Planned capacity insert returned no row');\n return row;\n}\n\nexport async function attachProviderRunnerId(params: {\n capacityId: string;\n provisionerId: string;\n providerRunnerId: string;\n}): Promise<boolean> {\n const updated = await db()\n .update(providerRunners)\n .set({providerRunnerId: params.providerRunnerId, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, params.capacityId),\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.providerRunnerId),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({id: providerRunners.id});\n return updated.length === 1;\n}\n\ninterface RunnerInstanceReportRow extends RunnerInstanceReportEvent {\n startedAt: Date | null;\n stoppingAt: Date | null;\n stoppedAt: Date | null;\n failedAt: Date | null;\n terminatedAt: Date | null;\n}\n\ntype RunnerInstanceMilestoneColumn =\n | typeof providerRunners.startedAt\n | typeof providerRunners.stoppingAt\n | typeof providerRunners.stoppedAt\n | typeof providerRunners.failedAt\n | typeof providerRunners.terminatedAt;\n\nexport async function reportRunnerInstances(params: ReportRunnerInstancesParams): Promise<{\n accepted: number;\n reservationsReleased: number;\n terminateIntentsHonored: RunnerInstanceTerminateIntent[];\n}> {\n if (params.events.length === 0)\n return {accepted: 0, reservationsReleased: 0, terminateIntentsHonored: []};\n\n return await db().transaction(async (tx) => {\n const receivedAt = new Date();\n const aggregatedEvents = aggregateEvents(params.events, receivedAt);\n const hasTerminalEvent = aggregatedEvents.some((event) => isTerminalState(event.state));\n\n if (hasTerminalEvent) {\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${params.workspaceId ?? params.provisionerId}))`,\n );\n }\n\n const events = await hydrateRunnerSessionIdsFromConsumedTokens(tx, params, aggregatedEvents);\n const terminateIntentsHonored = await listTerminateIntentsHonoredByTerminatedReportsTx(\n tx,\n params,\n events,\n );\n\n const values = events.map((event) => ({\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerId: event.providerRunnerId,\n reservationId: event.reservationId,\n templateKey: event.templateKey,\n labels: [...canonicalizeLabels(event.labels)],\n state: event.state,\n reason: event.reason,\n runnerSessionId: event.runnerSessionId,\n providerKind: event.providerKind,\n reportedAt: event.reportedAt > receivedAt ? receivedAt : event.reportedAt,\n startedAt: event.startedAt,\n stoppingAt: event.stoppingAt,\n stoppedAt: event.stoppedAt,\n failedAt: event.failedAt,\n terminatedAt: event.terminatedAt,\n }));\n\n await tx\n .insert(providerRunners)\n .values(values)\n .onConflictDoUpdate({\n target: [providerRunners.provisionerId, providerRunners.providerRunnerId],\n targetWhere: isNotNull(providerRunners.providerRunnerId),\n set: {\n reservationId: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(excluded.reservation_id, ${providerRunners.reservationId}) ELSE ${providerRunners.reservationId} END`,\n templateKey: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(excluded.template_key, ${providerRunners.templateKey}) ELSE ${providerRunners.templateKey} END`,\n labels: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.labels ELSE ${providerRunners.labels} END`,\n state: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.state ELSE ${providerRunners.state} END`,\n reason: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.reason ELSE ${providerRunners.reason} END`,\n runnerSessionId: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(${providerRunners.runnerSessionId}, excluded.runner_session_id) ELSE ${providerRunners.runnerSessionId} END`,\n providerKind: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(excluded.provider_kind, ${providerRunners.providerKind}) ELSE ${providerRunners.providerKind} END`,\n reportedAt: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.reported_at ELSE ${providerRunners.reportedAt} END`,\n startedAt: firstObservedAt(providerRunners.startedAt, sql`excluded.started_at`),\n stoppingAt: firstObservedAt(providerRunners.stoppingAt, sql`excluded.stopping_at`),\n stoppedAt: firstObservedAt(providerRunners.stoppedAt, sql`excluded.stopped_at`),\n failedAt: firstObservedAt(providerRunners.failedAt, sql`excluded.failed_at`),\n terminatedAt: firstObservedAt(providerRunners.terminatedAt, sql`excluded.terminated_at`),\n updatedAt: sql`now()`,\n },\n setWhere: sql`\n ${providerRunnerProjectionUpdateCondition()}\n OR ${providerRunnerMilestoneUpdateCondition()}\n `,\n });\n\n const reservationsReleased = hasTerminalEvent\n ? await releaseTerminalRunnerInstanceReservations(tx, params, events)\n : 0;\n\n return {accepted: events.length, reservationsReleased, terminateIntentsHonored};\n });\n}\n\nexport async function listActiveRunnerInstanceCountsByTemplateTx(\n tx: Tx,\n params: {workspaceId: string; provisionerId: string},\n): Promise<ActiveRunnerInstanceTemplateCount[]> {\n const rows = await tx\n .select({\n templateKey: providerRunners.templateKey,\n state: providerRunners.state,\n count: sql<number>`count(*)::int`,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.state, divergenceCountStates),\n isNotNull(providerRunners.templateKey),\n ),\n )\n .groupBy(providerRunners.templateKey, providerRunners.state);\n\n return rows.flatMap((row) =>\n row.templateKey && isDivergenceCountState(row.state)\n ? [{templateKey: row.templateKey, state: row.state, count: row.count}]\n : [],\n );\n}\n\nexport async function listActiveRunnerInstances(params: {\n workspaceId: string;\n windowSeconds: number;\n limit?: number;\n}): Promise<RunnerInstance[]> {\n const rows = await db()\n .select()\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n inArray(providerRunners.state, activeStates),\n sql`${providerRunners.updatedAt} > now() - (${params.windowSeconds} || ' seconds')::interval`,\n ),\n )\n .orderBy(desc(providerRunners.updatedAt), desc(providerRunners.id))\n .limit(params.limit ?? 1000);\n\n return rows.map(toRunnerInstance);\n}\n\nexport async function listProvisionerTerminateIntents(params: {\n workspaceId: string;\n provisionerId: string;\n limit: number;\n}): Promise<string[]> {\n return await db().transaction(async (tx) => {\n const rows = await listProvisionerTerminateIntentRowsTx(tx, params);\n return rows.map((row) => row.providerRunnerId);\n });\n}\n\nexport async function listProvisionerTerminateIntentRowsTx(\n tx: Tx,\n params: {\n workspaceId: string;\n provisionerId: string;\n limit: number;\n },\n): Promise<RunnerInstanceTerminateIntent[]> {\n const rows = await provisionerTerminateIntentsQuery(tx, params)\n .orderBy(asc(providerRunners.providerRunnerId))\n .limit(params.limit + 1);\n\n const truncated = rows.length > params.limit;\n const returnedRows = truncated ? rows.slice(0, params.limit) : rows;\n if (truncated) {\n logger().warn(\n {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n limit: params.limit,\n returnedCount: returnedRows.length,\n },\n 'provisioner terminate intents truncated by poll-demand limit',\n );\n }\n\n return returnedRows.flatMap((row) =>\n row.providerRunnerId ? [{...row, providerRunnerId: row.providerRunnerId}] : [],\n );\n}\n\nfunction provisionerTerminateIntentsQuery(\n tx: Tx,\n params: {workspaceId: string; provisionerId: string; providerRunnerIds?: string[]},\n) {\n const newerRunningJobExecutions = alias(runningJobExecutions, 'newer_running_jobs');\n\n return tx\n .select({\n providerRunnerId: providerRunners.providerRunnerId,\n reason: sql<RunnerInstanceTerminateIntentReason>`'job-cancelled'`,\n })\n .from(runningJobExecutions)\n .innerJoin(\n providerRunners,\n and(\n eq(providerRunners.workspaceId, runningJobExecutions.workspaceId),\n eq(providerRunners.provisionerId, runningJobExecutions.provisionerId),\n eq(providerRunners.providerRunnerId, runningJobExecutions.providerRunnerId),\n ),\n )\n .where(\n and(\n eq(runningJobExecutions.workspaceId, params.workspaceId),\n eq(runningJobExecutions.provisionerId, params.provisionerId),\n isNotNull(providerRunners.providerRunnerId),\n isNotNull(runningJobExecutions.cancellationRequestedAt),\n inArray(providerRunners.state, activeStates),\n params.providerRunnerIds && params.providerRunnerIds.length > 0\n ? inArray(providerRunners.providerRunnerId, params.providerRunnerIds)\n : undefined,\n notExists(\n tx\n .select({id: newerRunningJobExecutions.id})\n .from(newerRunningJobExecutions)\n .where(\n and(\n eq(newerRunningJobExecutions.workspaceId, runningJobExecutions.workspaceId),\n eq(newerRunningJobExecutions.provisionerId, runningJobExecutions.provisionerId),\n eq(\n newerRunningJobExecutions.providerRunnerId,\n runningJobExecutions.providerRunnerId,\n ),\n or(\n gt(newerRunningJobExecutions.startedAt, runningJobExecutions.startedAt),\n and(\n eq(newerRunningJobExecutions.startedAt, runningJobExecutions.startedAt),\n gt(\n newerRunningJobExecutions.jobExecutionId,\n runningJobExecutions.jobExecutionId,\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n )\n .groupBy(providerRunners.providerRunnerId);\n}\n\nasync function listTerminateIntentsHonoredByTerminatedReportsTx(\n tx: Tx,\n params: ReportRunnerInstancesParams,\n events: RunnerInstanceReportEvent[],\n): Promise<RunnerInstanceTerminateIntent[]> {\n if (!params.workspaceId) return [];\n const terminatedRunnerInstanceIds = [\n ...new Set(\n events.filter((event) => event.state === 'terminated').map((event) => event.providerRunnerId),\n ),\n ];\n if (terminatedRunnerInstanceIds.length === 0) return [];\n\n const rows = await provisionerTerminateIntentsQuery(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: terminatedRunnerInstanceIds,\n }).orderBy(asc(providerRunners.providerRunnerId));\n return rows.flatMap((row) =>\n row.providerRunnerId ? [{...row, providerRunnerId: row.providerRunnerId}] : [],\n );\n}\n\nexport async function reconcileRunnerInstances(\n params: ReconcileRunnerInstancesParams,\n): Promise<ReconcileRunnerInstancesDbResult> {\n const observedRunnerInstanceIds = [...new Set(params.observedRunnerInstanceIds)];\n\n return await db().transaction(async (tx) => {\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${params.workspaceId ?? params.provisionerId}))`,\n );\n\n let absentIds: string[] = [];\n let reservationsReleased = 0;\n if (observedRunnerInstanceIds.length > 0) {\n const staleAbsentRows = await tx\n .select({\n id: providerRunners.id,\n providerRunnerId: providerRunners.providerRunnerId,\n })\n .from(providerRunners)\n .where(\n and(\n params.workspaceId\n ? eq(providerRunners.workspaceId, params.workspaceId)\n : isNull(providerRunners.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.state, activeStates),\n lt(\n providerRunners.reportedAt,\n sql`now() - (${params.terminateGraceSeconds} || ' seconds')::interval`,\n ),\n notInArray(providerRunners.providerRunnerId, observedRunnerInstanceIds),\n ),\n );\n\n if (staleAbsentRows.length > 0) {\n const updated = await tx\n .update(providerRunners)\n .set({\n state: 'terminated',\n terminatedAt: sql`coalesce(${providerRunners.terminatedAt}, now())`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(\n providerRunners.id,\n staleAbsentRows.map((row) => row.id),\n ),\n inArray(providerRunners.state, activeStates),\n lt(\n providerRunners.reportedAt,\n sql`now() - (${params.terminateGraceSeconds} || ' seconds')::interval`,\n ),\n ),\n )\n .returning({providerRunnerId: providerRunners.providerRunnerId});\n\n absentIds = updated.flatMap((row) => (row.providerRunnerId ? [row.providerRunnerId] : []));\n if (params.workspaceId) {\n reservationsReleased = await releaseTerminalRunnerInstanceReservationsByIds(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: absentIds,\n });\n }\n }\n }\n\n const observedRows =\n observedRunnerInstanceIds.length === 0\n ? []\n : (\n await tx\n .select()\n .from(providerRunners)\n .where(\n and(\n params.workspaceId\n ? eq(providerRunners.workspaceId, params.workspaceId)\n : isNull(providerRunners.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.providerRunnerId, observedRunnerInstanceIds),\n ),\n )\n ).map(toRunnerInstance);\n\n const boundJobExecutions = params.workspaceId\n ? await listRunningJobExecutionsByRunnerInstanceTx(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: observedRunnerInstanceIds,\n })\n : [];\n\n return {\n observedRows,\n boundJobExecutionsByRunnerInstanceId: new Map(\n boundJobExecutions.map((jobExecution) => [jobExecution.providerRunnerId, jobExecution]),\n ),\n absentIds,\n reservationsReleased,\n };\n });\n}\n\nexport async function reapStaleRunnerInstances(params: {\n thresholdSeconds: number;\n limit: number;\n}): Promise<ReapStaleRunnerInstancesResult> {\n const cutoff = staleRunnerInstanceCutoff(params.thresholdSeconds);\n\n return await db().transaction(async (tx) => {\n const candidateRows = await tx\n .select({\n id: providerRunners.id,\n workspaceId: providerRunners.workspaceId,\n provisionerId: providerRunners.provisionerId,\n providerRunnerId: providerRunners.providerRunnerId,\n })\n .from(providerRunners)\n .where(staleRunnerInstanceWhere(tx, cutoff))\n .orderBy(asc(providerRunners.updatedAt), asc(providerRunners.id))\n .limit(params.limit);\n\n if (candidateRows.length === 0) return {reaped: 0, reservationsReleased: 0};\n\n const workspaceIds = [\n ...new Set(candidateRows.flatMap((row) => (row.workspaceId ? [row.workspaceId] : []))),\n ].sort();\n for (const workspaceId of workspaceIds) {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext(${workspaceId}))`);\n }\n\n const updatedRows = await tx\n .update(providerRunners)\n .set({\n state: 'failed',\n reason: 'stale-provisioner',\n failedAt: sql`coalesce(${providerRunners.failedAt}, now())`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(\n providerRunners.id,\n candidateRows.map((row) => row.id),\n ),\n staleRunnerInstanceWhere(tx, cutoff),\n ),\n )\n .returning({\n workspaceId: providerRunners.workspaceId,\n provisionerId: providerRunners.provisionerId,\n providerRunnerId: providerRunners.providerRunnerId,\n });\n\n let reservationsReleased = 0;\n for (const group of groupRunnerInstanceIds(updatedRows)) {\n reservationsReleased += await releaseTerminalRunnerInstanceReservationsByIds(tx, {\n workspaceId: group.workspaceId,\n provisionerId: group.provisionerId,\n providerRunnerIds: group.providerRunnerIds,\n requireUnlinkedSession: false,\n });\n }\n\n return {reaped: updatedRows.length, reservationsReleased};\n });\n}\n\nasync function releaseTerminalRunnerInstanceReservations(\n tx: Tx,\n params: ReportRunnerInstancesParams,\n events: RunnerInstanceReportEvent[],\n): Promise<number> {\n const terminalEvents = events.filter((event) => isTerminalState(event.state));\n if (terminalEvents.length === 0 || !params.workspaceId) return 0;\n\n return await releaseTerminalRunnerInstanceReservationsByIds(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: terminalEvents.map((event) => event.providerRunnerId),\n });\n}\n\nasync function releaseTerminalRunnerInstanceReservationsByIds(\n tx: Tx,\n params: {\n workspaceId: string;\n provisionerId: string;\n providerRunnerIds: string[];\n requireUnlinkedSession?: boolean;\n },\n): Promise<number> {\n if (params.providerRunnerIds.length === 0) return 0;\n\n const rows = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.providerRunnerId, params.providerRunnerIds),\n inArray(providerRunners.state, terminalStates),\n isNotNull(providerRunners.reservationId),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n );\n\n if (rows.length === 0) return 0;\n\n const updated = await tx\n .update(providerRunners)\n .set({reservationReleasedAt: sql`now()`, updatedAt: sql`now()`})\n .where(\n and(\n inArray(\n providerRunners.id,\n rows.map((row) => row.id),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .returning({reservationId: providerRunners.reservationId});\n\n const releasesByReservationId = new Map<string, number>();\n for (const row of updated) {\n if (!row.reservationId) continue;\n releasesByReservationId.set(\n row.reservationId,\n (releasesByReservationId.get(row.reservationId) ?? 0) + 1,\n );\n }\n\n if (releasesByReservationId.size === 0) return 0;\n\n return await releaseReservationUnits(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n releases: [...releasesByReservationId].map(([reservationId, count]) => ({\n reservationId,\n count,\n })),\n });\n}\n\nfunction staleRunnerInstanceCutoff(thresholdSeconds: number): SQL {\n return sql`now() - (${thresholdSeconds} || ' seconds')::interval`;\n}\n\nfunction staleRunnerInstanceWhere(tx: Tx, cutoff: SQL): SQL<boolean> {\n return and(\n inArray(providerRunners.state, activeStates),\n lt(providerRunners.reportedAt, cutoff),\n lt(providerRunners.updatedAt, cutoff),\n exists(\n tx\n .select({id: provisionerTokens.id})\n .from(provisionerTokens)\n .where(\n and(\n eq(provisionerTokens.id, providerRunners.provisionerId),\n or(isNull(provisionerTokens.lastSeenAt), lt(provisionerTokens.lastSeenAt, cutoff)),\n ),\n ),\n ),\n notExists(\n tx\n .select({id: runningJobExecutions.id})\n .from(runningJobExecutions)\n .where(\n and(\n eq(runningJobExecutions.workspaceId, providerRunners.workspaceId),\n eq(runningJobExecutions.provisionerId, providerRunners.provisionerId),\n eq(runningJobExecutions.providerRunnerId, providerRunners.providerRunnerId),\n ),\n ),\n ),\n notExists(\n tx\n .select({id: runnerSessions.id})\n .from(runnerSessions)\n .where(\n and(\n eq(runnerSessions.workspaceId, providerRunners.workspaceId),\n eq(runnerSessions.provisionerId, providerRunners.provisionerId),\n eq(runnerSessions.providerRunnerId, providerRunners.providerRunnerId),\n sql`${runnerSessions.updatedAt} >= ${cutoff}`,\n ),\n ),\n ),\n ) as SQL<boolean>;\n}\n\nfunction groupRunnerInstanceIds(\n rows: Array<{\n workspaceId: string | null;\n provisionerId: string;\n providerRunnerId: string | null;\n }>,\n): Array<{workspaceId: string; provisionerId: string; providerRunnerIds: string[]}> {\n const groups = new Map<\n string,\n {workspaceId: string; provisionerId: string; providerRunnerIds: string[]}\n >();\n for (const row of rows) {\n if (!row.workspaceId || !row.providerRunnerId) continue;\n const key = `${row.workspaceId}:${row.provisionerId}`;\n const group = groups.get(key) ?? {\n workspaceId: row.workspaceId,\n provisionerId: row.provisionerId,\n providerRunnerIds: [],\n };\n group.providerRunnerIds.push(row.providerRunnerId);\n groups.set(key, group);\n }\n return [...groups.values()];\n}\n\nasync function hydrateRunnerSessionIdsFromConsumedTokens(\n tx: Tx,\n params: ReportRunnerInstancesParams,\n events: RunnerInstanceReportRow[],\n): Promise<RunnerInstanceReportRow[]> {\n if (!params.workspaceId) return events;\n const providerRunnerIds = [...new Set(events.map((event) => event.providerRunnerId))];\n if (providerRunnerIds.length === 0) return events;\n\n const tokenRows = await tx\n .select({\n providerRunnerId: ephemeralRegistrationTokens.providerRunnerId,\n consumedSessionId: ephemeralRegistrationTokens.consumedSessionId,\n })\n .from(ephemeralRegistrationTokens)\n .where(\n and(\n eq(ephemeralRegistrationTokens.workspaceId, params.workspaceId),\n eq(ephemeralRegistrationTokens.provisionerId, params.provisionerId),\n inArray(ephemeralRegistrationTokens.providerRunnerId, providerRunnerIds),\n isNotNull(ephemeralRegistrationTokens.consumedSessionId),\n ),\n )\n .orderBy(\n desc(ephemeralRegistrationTokens.consumedAt),\n desc(ephemeralRegistrationTokens.createdAt),\n );\n\n const consumedSessionIdsByRunnerInstanceId = new Map<string, string>();\n for (const row of tokenRows) {\n if (!row.consumedSessionId) continue;\n if (consumedSessionIdsByRunnerInstanceId.has(row.providerRunnerId)) continue;\n consumedSessionIdsByRunnerInstanceId.set(row.providerRunnerId, row.consumedSessionId);\n }\n\n if (consumedSessionIdsByRunnerInstanceId.size === 0) return events;\n\n return events.map((event) => {\n const consumedSessionId = consumedSessionIdsByRunnerInstanceId.get(event.providerRunnerId);\n if (!consumedSessionId || event.runnerSessionId === consumedSessionId) return event;\n return {...event, runnerSessionId: consumedSessionId};\n });\n}\n\nfunction aggregateEvents(\n events: RunnerInstanceReportEvent[],\n receivedAt: Date,\n): RunnerInstanceReportRow[] {\n const byRunnerInstanceId = new Map<string, RunnerInstanceReportRow>();\n for (const rawEvent of events) {\n const event = toRunnerInstanceReportRow(rawEvent, receivedAt);\n const existing = byRunnerInstanceId.get(event.providerRunnerId);\n if (existing) mergeMilestones(existing, event);\n if (!existing || compareRunnerInstanceReportEvents(event, existing) > 0) {\n byRunnerInstanceId.set(\n event.providerRunnerId,\n existing ? mergeProjectionMetadata(event, existing) : event,\n );\n }\n }\n return [...byRunnerInstanceId.values()];\n}\n\nfunction toRunnerInstanceReportRow(\n event: RunnerInstanceReportEvent,\n receivedAt: Date,\n): RunnerInstanceReportRow {\n const reportedAt = event.reportedAt > receivedAt ? receivedAt : event.reportedAt;\n return {\n ...event,\n reportedAt,\n startedAt: event.state === 'running' ? reportedAt : null,\n stoppingAt: event.state === 'stopping' ? reportedAt : null,\n stoppedAt: event.state === 'stopped' ? reportedAt : null,\n failedAt: event.state === 'failed' ? reportedAt : null,\n terminatedAt: event.state === 'terminated' ? reportedAt : null,\n };\n}\n\nfunction mergeMilestones(target: RunnerInstanceReportRow, source: RunnerInstanceReportRow) {\n target.startedAt = earliestDate(target.startedAt, source.startedAt);\n target.stoppingAt = earliestDate(target.stoppingAt, source.stoppingAt);\n target.stoppedAt = earliestDate(target.stoppedAt, source.stoppedAt);\n target.failedAt = earliestDate(target.failedAt, source.failedAt);\n target.terminatedAt = earliestDate(target.terminatedAt, source.terminatedAt);\n}\n\nfunction mergeProjectionMetadata(\n event: RunnerInstanceReportRow,\n existing: RunnerInstanceReportRow,\n): RunnerInstanceReportRow {\n return {\n ...event,\n reservationId: event.reservationId ?? existing.reservationId,\n templateKey: event.templateKey ?? existing.templateKey,\n runnerSessionId: event.runnerSessionId ?? existing.runnerSessionId,\n providerKind: event.providerKind ?? existing.providerKind,\n ...pickMilestones(existing),\n };\n}\n\nfunction pickMilestones(event: RunnerInstanceReportRow) {\n return {\n startedAt: event.startedAt,\n stoppingAt: event.stoppingAt,\n stoppedAt: event.stoppedAt,\n failedAt: event.failedAt,\n terminatedAt: event.terminatedAt,\n };\n}\n\nfunction earliestDate(a: Date | null, b: Date | null): Date | null {\n if (!a) return b;\n if (!b) return a;\n return a < b ? a : b;\n}\n\nfunction compareRunnerInstanceReportEvents(\n a: RunnerInstanceReportEvent,\n b: RunnerInstanceReportEvent,\n): number {\n const timeDelta = a.reportedAt.getTime() - b.reportedAt.getTime();\n const rankDelta = getRunnerInstanceStateRank(a.state) - getRunnerInstanceStateRank(b.state);\n if (rankDelta !== 0) return rankDelta;\n return timeDelta;\n}\n\nfunction getRunnerInstanceStateRank(state: RunnerInstanceState): number {\n switch (state) {\n case 'starting':\n return 1;\n case 'running':\n return 2;\n case 'stopping':\n return 3;\n case 'stopped':\n return 4;\n case 'failed':\n return 5;\n case 'terminated':\n return 6;\n }\n}\n\nfunction providerRunnerStateRank(state: SQL | typeof providerRunners.state): SQL<number> {\n return sql<number>`\n CASE ${state}\n WHEN 'starting' THEN 1\n WHEN 'running' THEN 2\n WHEN 'stopping' THEN 3\n WHEN 'stopped' THEN 4\n WHEN 'failed' THEN 5\n WHEN 'terminated' THEN 6\n ELSE 0\n END\n `;\n}\n\nfunction providerRunnerProjectionUpdateCondition(): SQL<boolean> {\n return sql<boolean>`\n ${providerRunnerStateRank(sql`excluded.state`)} > ${providerRunnerStateRank(providerRunners.state)}\n OR (\n ${providerRunnerStateRank(sql`excluded.state`)} = ${providerRunnerStateRank(providerRunners.state)}\n AND excluded.reported_at >= ${providerRunners.reportedAt}\n )\n `;\n}\n\nfunction providerRunnerMilestoneUpdateCondition(): SQL<boolean> {\n return sql<boolean>`\n ${milestoneNeedsUpdate(providerRunners.startedAt, sql`excluded.started_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.stoppingAt, sql`excluded.stopping_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.stoppedAt, sql`excluded.stopped_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.failedAt, sql`excluded.failed_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.terminatedAt, sql`excluded.terminated_at`)}\n `;\n}\n\nfunction milestoneNeedsUpdate(\n current: SQL | RunnerInstanceMilestoneColumn,\n incoming: SQL,\n): SQL<boolean> {\n return sql<boolean>`${incoming} IS NOT NULL AND (${current} IS NULL OR ${incoming} < ${current})`;\n}\n\nfunction firstObservedAt(current: SQL | RunnerInstanceMilestoneColumn, incoming: SQL) {\n return sql`\n CASE\n WHEN ${incoming} IS NULL THEN ${current}\n WHEN ${current} IS NULL THEN ${incoming}\n ELSE least(${current}, ${incoming})\n END\n `;\n}\n\nexport function isTerminalState(state: RunnerInstanceState): boolean {\n return terminalStates.includes(state as (typeof terminalStates)[number]);\n}\n\nfunction isDivergenceCountState(\n state: RunnerInstanceState,\n): state is (typeof divergenceCountStates)[number] {\n return divergenceCountStates.includes(state as (typeof divergenceCountStates)[number]);\n}\n"],"names":["logger","canonicalizeLabels","and","asc","desc","eq","exists","gt","inArray","isNotNull","isNull","lt","notExists","notInArray","or","sql","alias","db","listRunningJobExecutionsByRunnerInstanceTx","releaseReservationUnits","ephemeralRegistrationTokens","provisionerTokens","providerRunners","toRunnerInstance","runnerSessions","runningJobExecutions","terminalStates","activeStates","divergenceCountStates","createPlannedProvisionedCapacity","params","row","insert","values","provisionerId","providerKind","templateKey","state","labels","reportedAt","Date","returning","capacityId","id","Error","attachProviderRunnerId","updated","update","set","providerRunnerId","updatedAt","where","length","reportRunnerInstances","events","accepted","reservationsReleased","terminateIntentsHonored","transaction","tx","receivedAt","aggregatedEvents","aggregateEvents","hasTerminalEvent","some","event","isTerminalState","execute","workspaceId","hydrateRunnerSessionIdsFromConsumedTokens","listTerminateIntentsHonoredByTerminatedReportsTx","map","reservationId","reason","runnerSessionId","startedAt","stoppingAt","stoppedAt","failedAt","terminatedAt","onConflictDoUpdate","target","targetWhere","providerRunnerProjectionUpdateCondition","firstObservedAt","setWhere","providerRunnerMilestoneUpdateCondition","releaseTerminalRunnerInstanceReservations","listActiveRunnerInstanceCountsByTemplateTx","rows","select","count","from","groupBy","flatMap","isDivergenceCountState","listActiveRunnerInstances","windowSeconds","orderBy","limit","listProvisionerTerminateIntents","listProvisionerTerminateIntentRowsTx","provisionerTerminateIntentsQuery","truncated","returnedRows","slice","warn","returnedCount","newerRunningJobExecutions","innerJoin","cancellationRequestedAt","providerRunnerIds","undefined","jobExecutionId","terminatedRunnerInstanceIds","Set","filter","reconcileRunnerInstances","observedRunnerInstanceIds","absentIds","staleAbsentRows","terminateGraceSeconds","releaseTerminalRunnerInstanceReservationsByIds","observedRows","boundJobExecutions","boundJobExecutionsByRunnerInstanceId","Map","jobExecution","reapStaleRunnerInstances","cutoff","staleRunnerInstanceCutoff","thresholdSeconds","candidateRows","staleRunnerInstanceWhere","reaped","workspaceIds","sort","updatedRows","group","groupRunnerInstanceIds","requireUnlinkedSession","terminalEvents","reservationReleasedAt","releasesByReservationId","get","size","releases","lastSeenAt","groups","key","push","tokenRows","consumedSessionId","consumedAt","createdAt","consumedSessionIdsByRunnerInstanceId","has","byRunnerInstanceId","rawEvent","toRunnerInstanceReportRow","existing","mergeMilestones","compareRunnerInstanceReportEvents","mergeProjectionMetadata","source","earliestDate","pickMilestones","a","b","timeDelta","getTime","rankDelta","getRunnerInstanceStateRank","providerRunnerStateRank","milestoneNeedsUpdate","current","incoming","includes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/db/runner-instances.ts"],"sourcesContent":["import {logger} from '@shipfox/node-opentelemetry';\nimport {canonicalizeLabels} from '@shipfox/runner-labels';\nimport {\n and,\n asc,\n desc,\n eq,\n exists,\n gt,\n inArray,\n isNotNull,\n isNull,\n lt,\n notExists,\n notInArray,\n or,\n type SQL,\n sql,\n} from 'drizzle-orm';\nimport {alias} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance, RunnerInstanceState} from '#core/entities/runner-instance.js';\nimport type {Tx} from './db.js';\nimport {db} from './db.js';\nimport {\n listRunningJobExecutionsByRunnerInstanceTx,\n type RunnerInstanceBoundJobExecution,\n} from './job-executions.js';\nimport {releaseReservationUnits} from './reservations.js';\nimport {ephemeralRegistrationTokens} from './schema/ephemeral-registration-tokens.js';\nimport {provisionerTokens} from './schema/provisioner-tokens.js';\nimport {providerRunners, toRunnerInstance} from './schema/runner-instances.js';\nimport {runnerSessions} from './schema/runner-sessions.js';\nimport {runningJobExecutions} from './schema/running-job-executions.js';\n\nexport const terminalStates = [\n 'stopped',\n 'failed',\n 'terminated',\n] as const satisfies readonly RunnerInstanceState[];\nexport const activeStates = [\n 'starting',\n 'running',\n 'stopping',\n] as const satisfies readonly RunnerInstanceState[];\nexport const divergenceCountStates = ['starting', 'running'] as const satisfies readonly Extract<\n RunnerInstanceState,\n 'starting' | 'running'\n>[];\n\nexport type RunnerInstanceTerminateIntentReason = 'job-cancelled';\n\nexport interface RunnerInstanceTerminateIntent {\n providerRunnerId: string;\n reason: RunnerInstanceTerminateIntentReason;\n}\n\nexport interface ActiveRunnerInstanceTemplateCount {\n templateKey: string;\n state: (typeof divergenceCountStates)[number];\n count: number;\n}\n\nexport interface RunnerInstanceReportEvent {\n providerRunnerId: string;\n reservationId: string | null;\n templateKey: string | null;\n labels: string[];\n state: RunnerInstanceState;\n reason: string | null;\n runnerSessionId: string | null;\n providerKind: string | null;\n reportedAt: Date;\n}\n\nexport interface ReportRunnerInstancesParams {\n workspaceId: string | null;\n provisionerId: string;\n events: RunnerInstanceReportEvent[];\n}\n\nexport interface ReconcileRunnerInstancesParams {\n workspaceId: string | null;\n provisionerId: string;\n observedRunnerInstanceIds: string[];\n terminateGraceSeconds: number;\n}\n\nexport interface ReconcileRunnerInstancesDbResult {\n observedRows: RunnerInstance[];\n boundJobExecutionsByRunnerInstanceId: Map<string, RunnerInstanceBoundJobExecution>;\n absentIds: string[];\n reservationsReleased: number;\n}\n\nexport interface ReapStaleRunnerInstancesResult {\n reaped: number;\n reservationsReleased: number;\n}\n\nexport async function attachRunnerInstanceProviderId(params: {\n runnerInstanceId: string;\n provisionerId: string;\n providerRunnerId: string;\n}): Promise<boolean> {\n const updated = await db()\n .update(providerRunners)\n .set({providerRunnerId: params.providerRunnerId, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, params.runnerInstanceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n isNull(providerRunners.providerRunnerId),\n notInArray(providerRunners.state, [...terminalStates]),\n ),\n )\n .returning({id: providerRunners.id});\n return updated.length === 1;\n}\n\ninterface RunnerInstanceReportRow extends RunnerInstanceReportEvent {\n startedAt: Date | null;\n stoppingAt: Date | null;\n stoppedAt: Date | null;\n failedAt: Date | null;\n terminatedAt: Date | null;\n}\n\ntype RunnerInstanceMilestoneColumn =\n | typeof providerRunners.startedAt\n | typeof providerRunners.stoppingAt\n | typeof providerRunners.stoppedAt\n | typeof providerRunners.failedAt\n | typeof providerRunners.terminatedAt;\n\nexport async function reportRunnerInstances(params: ReportRunnerInstancesParams): Promise<{\n accepted: number;\n reservationsReleased: number;\n terminateIntentsHonored: RunnerInstanceTerminateIntent[];\n}> {\n if (params.events.length === 0)\n return {accepted: 0, reservationsReleased: 0, terminateIntentsHonored: []};\n\n return await db().transaction(async (tx) => {\n const receivedAt = new Date();\n const aggregatedEvents = aggregateEvents(params.events, receivedAt);\n const hasTerminalEvent = aggregatedEvents.some((event) => isTerminalState(event.state));\n\n if (hasTerminalEvent) {\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${params.workspaceId ?? params.provisionerId}))`,\n );\n }\n\n const events = await hydrateRunnerSessionIdsFromConsumedTokens(tx, params, aggregatedEvents);\n const terminateIntentsHonored = await listTerminateIntentsHonoredByTerminatedReportsTx(\n tx,\n params,\n events,\n );\n\n const values = events.map((event) => ({\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerId: event.providerRunnerId,\n reservationId: event.reservationId,\n templateKey: event.templateKey,\n labels: [...canonicalizeLabels(event.labels)],\n state: event.state,\n reason: event.reason,\n runnerSessionId: event.runnerSessionId,\n providerKind: event.providerKind,\n reportedAt: event.reportedAt > receivedAt ? receivedAt : event.reportedAt,\n startedAt: event.startedAt,\n stoppingAt: event.stoppingAt,\n stoppedAt: event.stoppedAt,\n failedAt: event.failedAt,\n terminatedAt: event.terminatedAt,\n }));\n\n await tx\n .insert(providerRunners)\n .values(values)\n .onConflictDoUpdate({\n target: [providerRunners.provisionerId, providerRunners.providerRunnerId],\n targetWhere: isNotNull(providerRunners.providerRunnerId),\n set: {\n reservationId: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(excluded.reservation_id, ${providerRunners.reservationId}) ELSE ${providerRunners.reservationId} END`,\n templateKey: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(excluded.template_key, ${providerRunners.templateKey}) ELSE ${providerRunners.templateKey} END`,\n labels: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.labels ELSE ${providerRunners.labels} END`,\n state: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.state ELSE ${providerRunners.state} END`,\n reason: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.reason ELSE ${providerRunners.reason} END`,\n runnerSessionId: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(${providerRunners.runnerSessionId}, excluded.runner_session_id) ELSE ${providerRunners.runnerSessionId} END`,\n providerKind: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN coalesce(excluded.provider_kind, ${providerRunners.providerKind}) ELSE ${providerRunners.providerKind} END`,\n reportedAt: sql`CASE WHEN ${providerRunnerProjectionUpdateCondition()} THEN excluded.reported_at ELSE ${providerRunners.reportedAt} END`,\n startedAt: firstObservedAt(providerRunners.startedAt, sql`excluded.started_at`),\n stoppingAt: firstObservedAt(providerRunners.stoppingAt, sql`excluded.stopping_at`),\n stoppedAt: firstObservedAt(providerRunners.stoppedAt, sql`excluded.stopped_at`),\n failedAt: firstObservedAt(providerRunners.failedAt, sql`excluded.failed_at`),\n terminatedAt: firstObservedAt(providerRunners.terminatedAt, sql`excluded.terminated_at`),\n updatedAt: sql`now()`,\n },\n setWhere: sql`\n ${providerRunnerProjectionUpdateCondition()}\n OR ${providerRunnerMilestoneUpdateCondition()}\n `,\n });\n\n const reservationsReleased = hasTerminalEvent\n ? await releaseTerminalRunnerInstanceReservations(tx, params, events)\n : 0;\n\n return {accepted: events.length, reservationsReleased, terminateIntentsHonored};\n });\n}\n\nexport async function listActiveRunnerInstanceCountsByTemplateTx(\n tx: Tx,\n params: {workspaceId: string; provisionerId: string},\n): Promise<ActiveRunnerInstanceTemplateCount[]> {\n const rows = await tx\n .select({\n templateKey: providerRunners.templateKey,\n state: providerRunners.state,\n count: sql<number>`count(*)::int`,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.state, divergenceCountStates),\n isNotNull(providerRunners.templateKey),\n ),\n )\n .groupBy(providerRunners.templateKey, providerRunners.state);\n\n return rows.flatMap((row) =>\n row.templateKey && isDivergenceCountState(row.state)\n ? [{templateKey: row.templateKey, state: row.state, count: row.count}]\n : [],\n );\n}\n\nexport async function listActiveRunnerInstances(params: {\n workspaceId: string;\n windowSeconds: number;\n limit?: number;\n}): Promise<RunnerInstance[]> {\n const rows = await db()\n .select()\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n inArray(providerRunners.state, activeStates),\n sql`${providerRunners.updatedAt} > now() - (${params.windowSeconds} || ' seconds')::interval`,\n ),\n )\n .orderBy(desc(providerRunners.updatedAt), desc(providerRunners.id))\n .limit(params.limit ?? 1000);\n\n return rows.map(toRunnerInstance);\n}\n\nexport async function listProvisionerTerminateIntents(params: {\n workspaceId: string;\n provisionerId: string;\n limit: number;\n}): Promise<string[]> {\n return await db().transaction(async (tx) => {\n const rows = await listProvisionerTerminateIntentRowsTx(tx, params);\n return rows.map((row) => row.providerRunnerId);\n });\n}\n\nexport async function listProvisionerTerminateIntentRowsTx(\n tx: Tx,\n params: {\n workspaceId: string;\n provisionerId: string;\n limit: number;\n },\n): Promise<RunnerInstanceTerminateIntent[]> {\n const rows = await provisionerTerminateIntentsQuery(tx, params)\n .orderBy(asc(providerRunners.providerRunnerId))\n .limit(params.limit + 1);\n\n const truncated = rows.length > params.limit;\n const returnedRows = truncated ? rows.slice(0, params.limit) : rows;\n if (truncated) {\n logger().warn(\n {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n limit: params.limit,\n returnedCount: returnedRows.length,\n },\n 'provisioner terminate intents truncated by poll-demand limit',\n );\n }\n\n return returnedRows.flatMap((row) =>\n row.providerRunnerId ? [{...row, providerRunnerId: row.providerRunnerId}] : [],\n );\n}\n\nfunction provisionerTerminateIntentsQuery(\n tx: Tx,\n params: {workspaceId: string; provisionerId: string; providerRunnerIds?: string[]},\n) {\n const newerRunningJobExecutions = alias(runningJobExecutions, 'newer_running_jobs');\n\n return tx\n .select({\n providerRunnerId: providerRunners.providerRunnerId,\n reason: sql<RunnerInstanceTerminateIntentReason>`'job-cancelled'`,\n })\n .from(runningJobExecutions)\n .innerJoin(\n providerRunners,\n and(\n eq(providerRunners.workspaceId, runningJobExecutions.workspaceId),\n eq(providerRunners.provisionerId, runningJobExecutions.provisionerId),\n eq(providerRunners.providerRunnerId, runningJobExecutions.providerRunnerId),\n ),\n )\n .where(\n and(\n eq(runningJobExecutions.workspaceId, params.workspaceId),\n eq(runningJobExecutions.provisionerId, params.provisionerId),\n isNotNull(providerRunners.providerRunnerId),\n isNotNull(runningJobExecutions.cancellationRequestedAt),\n inArray(providerRunners.state, activeStates),\n params.providerRunnerIds && params.providerRunnerIds.length > 0\n ? inArray(providerRunners.providerRunnerId, params.providerRunnerIds)\n : undefined,\n notExists(\n tx\n .select({id: newerRunningJobExecutions.id})\n .from(newerRunningJobExecutions)\n .where(\n and(\n eq(newerRunningJobExecutions.workspaceId, runningJobExecutions.workspaceId),\n eq(newerRunningJobExecutions.provisionerId, runningJobExecutions.provisionerId),\n eq(\n newerRunningJobExecutions.providerRunnerId,\n runningJobExecutions.providerRunnerId,\n ),\n or(\n gt(newerRunningJobExecutions.startedAt, runningJobExecutions.startedAt),\n and(\n eq(newerRunningJobExecutions.startedAt, runningJobExecutions.startedAt),\n gt(\n newerRunningJobExecutions.jobExecutionId,\n runningJobExecutions.jobExecutionId,\n ),\n ),\n ),\n ),\n ),\n ),\n ),\n )\n .groupBy(providerRunners.providerRunnerId);\n}\n\nasync function listTerminateIntentsHonoredByTerminatedReportsTx(\n tx: Tx,\n params: ReportRunnerInstancesParams,\n events: RunnerInstanceReportEvent[],\n): Promise<RunnerInstanceTerminateIntent[]> {\n if (!params.workspaceId) return [];\n const terminatedRunnerInstanceIds = [\n ...new Set(\n events.filter((event) => event.state === 'terminated').map((event) => event.providerRunnerId),\n ),\n ];\n if (terminatedRunnerInstanceIds.length === 0) return [];\n\n const rows = await provisionerTerminateIntentsQuery(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: terminatedRunnerInstanceIds,\n }).orderBy(asc(providerRunners.providerRunnerId));\n return rows.flatMap((row) =>\n row.providerRunnerId ? [{...row, providerRunnerId: row.providerRunnerId}] : [],\n );\n}\n\nexport async function reconcileRunnerInstances(\n params: ReconcileRunnerInstancesParams,\n): Promise<ReconcileRunnerInstancesDbResult> {\n const observedRunnerInstanceIds = [...new Set(params.observedRunnerInstanceIds)];\n\n return await db().transaction(async (tx) => {\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${params.workspaceId ?? params.provisionerId}))`,\n );\n\n let absentIds: string[] = [];\n let reservationsReleased = 0;\n if (observedRunnerInstanceIds.length > 0) {\n const staleAbsentRows = await tx\n .select({\n id: providerRunners.id,\n providerRunnerId: providerRunners.providerRunnerId,\n })\n .from(providerRunners)\n .where(\n and(\n params.workspaceId\n ? eq(providerRunners.workspaceId, params.workspaceId)\n : isNull(providerRunners.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.state, activeStates),\n lt(\n providerRunners.reportedAt,\n sql`now() - (${params.terminateGraceSeconds} || ' seconds')::interval`,\n ),\n notInArray(providerRunners.providerRunnerId, observedRunnerInstanceIds),\n ),\n );\n\n if (staleAbsentRows.length > 0) {\n const updated = await tx\n .update(providerRunners)\n .set({\n state: 'terminated',\n terminatedAt: sql`coalesce(${providerRunners.terminatedAt}, now())`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(\n providerRunners.id,\n staleAbsentRows.map((row) => row.id),\n ),\n inArray(providerRunners.state, activeStates),\n lt(\n providerRunners.reportedAt,\n sql`now() - (${params.terminateGraceSeconds} || ' seconds')::interval`,\n ),\n ),\n )\n .returning({providerRunnerId: providerRunners.providerRunnerId});\n\n absentIds = updated.flatMap((row) => (row.providerRunnerId ? [row.providerRunnerId] : []));\n if (params.workspaceId) {\n reservationsReleased = await releaseTerminalRunnerInstanceReservationsByIds(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: absentIds,\n });\n }\n }\n }\n\n const observedRows =\n observedRunnerInstanceIds.length === 0\n ? []\n : (\n await tx\n .select()\n .from(providerRunners)\n .where(\n and(\n params.workspaceId\n ? eq(providerRunners.workspaceId, params.workspaceId)\n : isNull(providerRunners.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.providerRunnerId, observedRunnerInstanceIds),\n ),\n )\n ).map(toRunnerInstance);\n\n const boundJobExecutions = params.workspaceId\n ? await listRunningJobExecutionsByRunnerInstanceTx(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: observedRunnerInstanceIds,\n })\n : [];\n\n return {\n observedRows,\n boundJobExecutionsByRunnerInstanceId: new Map(\n boundJobExecutions.map((jobExecution) => [jobExecution.providerRunnerId, jobExecution]),\n ),\n absentIds,\n reservationsReleased,\n };\n });\n}\n\nexport async function reapStaleRunnerInstances(params: {\n thresholdSeconds: number;\n limit: number;\n}): Promise<ReapStaleRunnerInstancesResult> {\n const cutoff = staleRunnerInstanceCutoff(params.thresholdSeconds);\n\n return await db().transaction(async (tx) => {\n const candidateRows = await tx\n .select({\n id: providerRunners.id,\n workspaceId: providerRunners.workspaceId,\n provisionerId: providerRunners.provisionerId,\n providerRunnerId: providerRunners.providerRunnerId,\n })\n .from(providerRunners)\n .where(staleRunnerInstanceWhere(tx, cutoff))\n .orderBy(asc(providerRunners.updatedAt), asc(providerRunners.id))\n .limit(params.limit);\n\n if (candidateRows.length === 0) return {reaped: 0, reservationsReleased: 0};\n\n const workspaceIds = [\n ...new Set(candidateRows.flatMap((row) => (row.workspaceId ? [row.workspaceId] : []))),\n ].sort();\n for (const workspaceId of workspaceIds) {\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext(${workspaceId}))`);\n }\n\n const updatedRows = await tx\n .update(providerRunners)\n .set({\n state: 'failed',\n reason: 'stale-provisioner',\n failedAt: sql`coalesce(${providerRunners.failedAt}, now())`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(\n providerRunners.id,\n candidateRows.map((row) => row.id),\n ),\n staleRunnerInstanceWhere(tx, cutoff),\n ),\n )\n .returning({\n workspaceId: providerRunners.workspaceId,\n provisionerId: providerRunners.provisionerId,\n providerRunnerId: providerRunners.providerRunnerId,\n });\n\n let reservationsReleased = 0;\n for (const group of groupRunnerInstanceIds(updatedRows)) {\n reservationsReleased += await releaseTerminalRunnerInstanceReservationsByIds(tx, {\n workspaceId: group.workspaceId,\n provisionerId: group.provisionerId,\n providerRunnerIds: group.providerRunnerIds,\n requireUnlinkedSession: false,\n });\n }\n\n return {reaped: updatedRows.length, reservationsReleased};\n });\n}\n\nasync function releaseTerminalRunnerInstanceReservations(\n tx: Tx,\n params: ReportRunnerInstancesParams,\n events: RunnerInstanceReportEvent[],\n): Promise<number> {\n const terminalEvents = events.filter((event) => isTerminalState(event.state));\n if (terminalEvents.length === 0 || !params.workspaceId) return 0;\n\n return await releaseTerminalRunnerInstanceReservationsByIds(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n providerRunnerIds: terminalEvents.map((event) => event.providerRunnerId),\n });\n}\n\nasync function releaseTerminalRunnerInstanceReservationsByIds(\n tx: Tx,\n params: {\n workspaceId: string;\n provisionerId: string;\n providerRunnerIds: string[];\n requireUnlinkedSession?: boolean;\n },\n): Promise<number> {\n if (params.providerRunnerIds.length === 0) return 0;\n\n const rows = await tx\n .select({\n id: providerRunners.id,\n reservationId: providerRunners.reservationId,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.providerRunnerId, params.providerRunnerIds),\n inArray(providerRunners.state, terminalStates),\n isNotNull(providerRunners.reservationId),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n );\n\n if (rows.length === 0) return 0;\n\n const updated = await tx\n .update(providerRunners)\n .set({reservationReleasedAt: sql`now()`, updatedAt: sql`now()`})\n .where(\n and(\n inArray(\n providerRunners.id,\n rows.map((row) => row.id),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .returning({reservationId: providerRunners.reservationId});\n\n const releasesByReservationId = new Map<string, number>();\n for (const row of updated) {\n if (!row.reservationId) continue;\n releasesByReservationId.set(\n row.reservationId,\n (releasesByReservationId.get(row.reservationId) ?? 0) + 1,\n );\n }\n\n if (releasesByReservationId.size === 0) return 0;\n\n return await releaseReservationUnits(tx, {\n workspaceId: params.workspaceId,\n provisionerId: params.provisionerId,\n releases: [...releasesByReservationId].map(([reservationId, count]) => ({\n reservationId,\n count,\n })),\n });\n}\n\nfunction staleRunnerInstanceCutoff(thresholdSeconds: number): SQL {\n return sql`now() - (${thresholdSeconds} || ' seconds')::interval`;\n}\n\nfunction staleRunnerInstanceWhere(tx: Tx, cutoff: SQL): SQL<boolean> {\n return and(\n inArray(providerRunners.state, activeStates),\n lt(providerRunners.reportedAt, cutoff),\n lt(providerRunners.updatedAt, cutoff),\n exists(\n tx\n .select({id: provisionerTokens.id})\n .from(provisionerTokens)\n .where(\n and(\n eq(provisionerTokens.id, providerRunners.provisionerId),\n or(isNull(provisionerTokens.lastSeenAt), lt(provisionerTokens.lastSeenAt, cutoff)),\n ),\n ),\n ),\n notExists(\n tx\n .select({id: runningJobExecutions.id})\n .from(runningJobExecutions)\n .where(\n and(\n eq(runningJobExecutions.workspaceId, providerRunners.workspaceId),\n eq(runningJobExecutions.provisionerId, providerRunners.provisionerId),\n eq(runningJobExecutions.providerRunnerId, providerRunners.providerRunnerId),\n ),\n ),\n ),\n notExists(\n tx\n .select({id: runnerSessions.id})\n .from(runnerSessions)\n .where(\n and(\n eq(runnerSessions.workspaceId, providerRunners.workspaceId),\n eq(runnerSessions.provisionerId, providerRunners.provisionerId),\n eq(runnerSessions.providerRunnerId, providerRunners.providerRunnerId),\n sql`${runnerSessions.updatedAt} >= ${cutoff}`,\n ),\n ),\n ),\n ) as SQL<boolean>;\n}\n\nfunction groupRunnerInstanceIds(\n rows: Array<{\n workspaceId: string | null;\n provisionerId: string;\n providerRunnerId: string | null;\n }>,\n): Array<{workspaceId: string; provisionerId: string; providerRunnerIds: string[]}> {\n const groups = new Map<\n string,\n {workspaceId: string; provisionerId: string; providerRunnerIds: string[]}\n >();\n for (const row of rows) {\n if (!row.workspaceId || !row.providerRunnerId) continue;\n const key = `${row.workspaceId}:${row.provisionerId}`;\n const group = groups.get(key) ?? {\n workspaceId: row.workspaceId,\n provisionerId: row.provisionerId,\n providerRunnerIds: [],\n };\n group.providerRunnerIds.push(row.providerRunnerId);\n groups.set(key, group);\n }\n return [...groups.values()];\n}\n\nasync function hydrateRunnerSessionIdsFromConsumedTokens(\n tx: Tx,\n params: ReportRunnerInstancesParams,\n events: RunnerInstanceReportRow[],\n): Promise<RunnerInstanceReportRow[]> {\n if (!params.workspaceId) return events;\n const providerRunnerIds = [...new Set(events.map((event) => event.providerRunnerId))];\n if (providerRunnerIds.length === 0) return events;\n\n const tokenRows = await tx\n .select({\n providerRunnerId: ephemeralRegistrationTokens.providerRunnerId,\n consumedSessionId: ephemeralRegistrationTokens.consumedSessionId,\n })\n .from(ephemeralRegistrationTokens)\n .where(\n and(\n eq(ephemeralRegistrationTokens.workspaceId, params.workspaceId),\n eq(ephemeralRegistrationTokens.provisionerId, params.provisionerId),\n inArray(ephemeralRegistrationTokens.providerRunnerId, providerRunnerIds),\n isNotNull(ephemeralRegistrationTokens.consumedSessionId),\n ),\n )\n .orderBy(\n desc(ephemeralRegistrationTokens.consumedAt),\n desc(ephemeralRegistrationTokens.createdAt),\n );\n\n const consumedSessionIdsByRunnerInstanceId = new Map<string, string>();\n for (const row of tokenRows) {\n if (!row.consumedSessionId) continue;\n if (consumedSessionIdsByRunnerInstanceId.has(row.providerRunnerId)) continue;\n consumedSessionIdsByRunnerInstanceId.set(row.providerRunnerId, row.consumedSessionId);\n }\n\n if (consumedSessionIdsByRunnerInstanceId.size === 0) return events;\n\n return events.map((event) => {\n const consumedSessionId = consumedSessionIdsByRunnerInstanceId.get(event.providerRunnerId);\n if (!consumedSessionId || event.runnerSessionId === consumedSessionId) return event;\n return {...event, runnerSessionId: consumedSessionId};\n });\n}\n\nfunction aggregateEvents(\n events: RunnerInstanceReportEvent[],\n receivedAt: Date,\n): RunnerInstanceReportRow[] {\n const byRunnerInstanceId = new Map<string, RunnerInstanceReportRow>();\n for (const rawEvent of events) {\n const event = toRunnerInstanceReportRow(rawEvent, receivedAt);\n const existing = byRunnerInstanceId.get(event.providerRunnerId);\n if (existing) mergeMilestones(existing, event);\n if (!existing || compareRunnerInstanceReportEvents(event, existing) > 0) {\n byRunnerInstanceId.set(\n event.providerRunnerId,\n existing ? mergeProjectionMetadata(event, existing) : event,\n );\n }\n }\n return [...byRunnerInstanceId.values()];\n}\n\nfunction toRunnerInstanceReportRow(\n event: RunnerInstanceReportEvent,\n receivedAt: Date,\n): RunnerInstanceReportRow {\n const reportedAt = event.reportedAt > receivedAt ? receivedAt : event.reportedAt;\n return {\n ...event,\n reportedAt,\n startedAt: event.state === 'running' ? reportedAt : null,\n stoppingAt: event.state === 'stopping' ? reportedAt : null,\n stoppedAt: event.state === 'stopped' ? reportedAt : null,\n failedAt: event.state === 'failed' ? reportedAt : null,\n terminatedAt: event.state === 'terminated' ? reportedAt : null,\n };\n}\n\nfunction mergeMilestones(target: RunnerInstanceReportRow, source: RunnerInstanceReportRow) {\n target.startedAt = earliestDate(target.startedAt, source.startedAt);\n target.stoppingAt = earliestDate(target.stoppingAt, source.stoppingAt);\n target.stoppedAt = earliestDate(target.stoppedAt, source.stoppedAt);\n target.failedAt = earliestDate(target.failedAt, source.failedAt);\n target.terminatedAt = earliestDate(target.terminatedAt, source.terminatedAt);\n}\n\nfunction mergeProjectionMetadata(\n event: RunnerInstanceReportRow,\n existing: RunnerInstanceReportRow,\n): RunnerInstanceReportRow {\n return {\n ...event,\n reservationId: event.reservationId ?? existing.reservationId,\n templateKey: event.templateKey ?? existing.templateKey,\n runnerSessionId: event.runnerSessionId ?? existing.runnerSessionId,\n providerKind: event.providerKind ?? existing.providerKind,\n ...pickMilestones(existing),\n };\n}\n\nfunction pickMilestones(event: RunnerInstanceReportRow) {\n return {\n startedAt: event.startedAt,\n stoppingAt: event.stoppingAt,\n stoppedAt: event.stoppedAt,\n failedAt: event.failedAt,\n terminatedAt: event.terminatedAt,\n };\n}\n\nfunction earliestDate(a: Date | null, b: Date | null): Date | null {\n if (!a) return b;\n if (!b) return a;\n return a < b ? a : b;\n}\n\nfunction compareRunnerInstanceReportEvents(\n a: RunnerInstanceReportEvent,\n b: RunnerInstanceReportEvent,\n): number {\n const timeDelta = a.reportedAt.getTime() - b.reportedAt.getTime();\n const rankDelta = getRunnerInstanceStateRank(a.state) - getRunnerInstanceStateRank(b.state);\n if (rankDelta !== 0) return rankDelta;\n return timeDelta;\n}\n\nfunction getRunnerInstanceStateRank(state: RunnerInstanceState): number {\n switch (state) {\n case 'starting':\n return 1;\n case 'running':\n return 2;\n case 'stopping':\n return 3;\n case 'stopped':\n return 4;\n case 'failed':\n return 5;\n case 'terminated':\n return 6;\n }\n}\n\nfunction providerRunnerStateRank(state: SQL | typeof providerRunners.state): SQL<number> {\n return sql<number>`\n CASE ${state}\n WHEN 'starting' THEN 1\n WHEN 'running' THEN 2\n WHEN 'stopping' THEN 3\n WHEN 'stopped' THEN 4\n WHEN 'failed' THEN 5\n WHEN 'terminated' THEN 6\n ELSE 0\n END\n `;\n}\n\nfunction providerRunnerProjectionUpdateCondition(): SQL<boolean> {\n return sql<boolean>`\n ${providerRunnerStateRank(sql`excluded.state`)} > ${providerRunnerStateRank(providerRunners.state)}\n OR (\n ${providerRunnerStateRank(sql`excluded.state`)} = ${providerRunnerStateRank(providerRunners.state)}\n AND excluded.reported_at >= ${providerRunners.reportedAt}\n )\n `;\n}\n\nfunction providerRunnerMilestoneUpdateCondition(): SQL<boolean> {\n return sql<boolean>`\n ${milestoneNeedsUpdate(providerRunners.startedAt, sql`excluded.started_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.stoppingAt, sql`excluded.stopping_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.stoppedAt, sql`excluded.stopped_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.failedAt, sql`excluded.failed_at`)}\n OR ${milestoneNeedsUpdate(providerRunners.terminatedAt, sql`excluded.terminated_at`)}\n `;\n}\n\nfunction milestoneNeedsUpdate(\n current: SQL | RunnerInstanceMilestoneColumn,\n incoming: SQL,\n): SQL<boolean> {\n return sql<boolean>`${incoming} IS NOT NULL AND (${current} IS NULL OR ${incoming} < ${current})`;\n}\n\nfunction firstObservedAt(current: SQL | RunnerInstanceMilestoneColumn, incoming: SQL) {\n return sql`\n CASE\n WHEN ${incoming} IS NULL THEN ${current}\n WHEN ${current} IS NULL THEN ${incoming}\n ELSE least(${current}, ${incoming})\n END\n `;\n}\n\nexport function isTerminalState(state: RunnerInstanceState): boolean {\n return terminalStates.includes(state as (typeof terminalStates)[number]);\n}\n\nfunction isDivergenceCountState(\n state: RunnerInstanceState,\n): state is (typeof divergenceCountStates)[number] {\n return divergenceCountStates.includes(state as (typeof divergenceCountStates)[number]);\n}\n"],"names":["logger","canonicalizeLabels","and","asc","desc","eq","exists","gt","inArray","isNotNull","isNull","lt","notExists","notInArray","or","sql","alias","db","listRunningJobExecutionsByRunnerInstanceTx","releaseReservationUnits","ephemeralRegistrationTokens","provisionerTokens","providerRunners","toRunnerInstance","runnerSessions","runningJobExecutions","terminalStates","activeStates","divergenceCountStates","attachRunnerInstanceProviderId","params","updated","update","set","providerRunnerId","updatedAt","where","id","runnerInstanceId","provisionerId","state","returning","length","reportRunnerInstances","events","accepted","reservationsReleased","terminateIntentsHonored","transaction","tx","receivedAt","Date","aggregatedEvents","aggregateEvents","hasTerminalEvent","some","event","isTerminalState","execute","workspaceId","hydrateRunnerSessionIdsFromConsumedTokens","listTerminateIntentsHonoredByTerminatedReportsTx","values","map","reservationId","templateKey","labels","reason","runnerSessionId","providerKind","reportedAt","startedAt","stoppingAt","stoppedAt","failedAt","terminatedAt","insert","onConflictDoUpdate","target","targetWhere","providerRunnerProjectionUpdateCondition","firstObservedAt","setWhere","providerRunnerMilestoneUpdateCondition","releaseTerminalRunnerInstanceReservations","listActiveRunnerInstanceCountsByTemplateTx","rows","select","count","from","groupBy","flatMap","row","isDivergenceCountState","listActiveRunnerInstances","windowSeconds","orderBy","limit","listProvisionerTerminateIntents","listProvisionerTerminateIntentRowsTx","provisionerTerminateIntentsQuery","truncated","returnedRows","slice","warn","returnedCount","newerRunningJobExecutions","innerJoin","cancellationRequestedAt","providerRunnerIds","undefined","jobExecutionId","terminatedRunnerInstanceIds","Set","filter","reconcileRunnerInstances","observedRunnerInstanceIds","absentIds","staleAbsentRows","terminateGraceSeconds","releaseTerminalRunnerInstanceReservationsByIds","observedRows","boundJobExecutions","boundJobExecutionsByRunnerInstanceId","Map","jobExecution","reapStaleRunnerInstances","cutoff","staleRunnerInstanceCutoff","thresholdSeconds","candidateRows","staleRunnerInstanceWhere","reaped","workspaceIds","sort","updatedRows","group","groupRunnerInstanceIds","requireUnlinkedSession","terminalEvents","reservationReleasedAt","releasesByReservationId","get","size","releases","lastSeenAt","groups","key","push","tokenRows","consumedSessionId","consumedAt","createdAt","consumedSessionIdsByRunnerInstanceId","has","byRunnerInstanceId","rawEvent","toRunnerInstanceReportRow","existing","mergeMilestones","compareRunnerInstanceReportEvents","mergeProjectionMetadata","source","earliestDate","pickMilestones","a","b","timeDelta","getTime","rankDelta","getRunnerInstanceStateRank","providerRunnerStateRank","milestoneNeedsUpdate","current","incoming","includes"],"mappings":"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"}
|
|
@@ -89,6 +89,23 @@ export declare const providerRunners: import("drizzle-orm/pg-core").PgTableWithC
|
|
|
89
89
|
identity: undefined;
|
|
90
90
|
generated: undefined;
|
|
91
91
|
}, {}, {}>;
|
|
92
|
+
assignedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
93
|
+
name: "assigned_at";
|
|
94
|
+
tableName: "runner_instances";
|
|
95
|
+
dataType: "date";
|
|
96
|
+
columnType: "PgTimestamp";
|
|
97
|
+
data: Date;
|
|
98
|
+
driverParam: string;
|
|
99
|
+
notNull: false;
|
|
100
|
+
hasDefault: false;
|
|
101
|
+
isPrimaryKey: false;
|
|
102
|
+
isAutoincrement: false;
|
|
103
|
+
hasRuntimeDefault: false;
|
|
104
|
+
enumValues: undefined;
|
|
105
|
+
baseColumn: never;
|
|
106
|
+
identity: undefined;
|
|
107
|
+
generated: undefined;
|
|
108
|
+
}, {}, {}>;
|
|
92
109
|
templateKey: import("drizzle-orm/pg-core").PgColumn<{
|
|
93
110
|
name: "template_key";
|
|
94
111
|
tableName: "runner_instances";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../../src/db/schema/runner-instances.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAGtE,eAAO,MAAM,uBAAuB,8GAOlC,CAAC;AAEH,eAAO,MAAM,eAAe
|
|
1
|
+
{"version":3,"file":"runner-instances.d.ts","sourceRoot":"","sources":["../../../src/db/schema/runner-instances.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,mCAAmC,CAAC;AAGtE,eAAO,MAAM,uBAAuB,8GAOlC,CAAC;AAEH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2C3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AACnE,MAAM,MAAM,sBAAsB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AAEzE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,cAAc,CAyBtE"}
|
|
@@ -18,6 +18,9 @@ export const providerRunners = pgTable('runner_instances', {
|
|
|
18
18
|
provisionerId: uuid('provisioner_id').notNull(),
|
|
19
19
|
providerRunnerId: text('provider_runner_id'),
|
|
20
20
|
reservationId: uuid('reservation_id'),
|
|
21
|
+
assignedAt: timestamp('assigned_at', {
|
|
22
|
+
withTimezone: true
|
|
23
|
+
}),
|
|
21
24
|
templateKey: text('template_key'),
|
|
22
25
|
labels: text('labels').array().notNull().default([]),
|
|
23
26
|
state: providerRunnerStateEnum('state').notNull(),
|
|
@@ -60,13 +63,14 @@ export const providerRunners = pgTable('runner_instances', {
|
|
|
60
63
|
index('runners_runner_instances_active_template_counts_idx').on(table.provisionerId, table.state, table.templateKey).where(sql`"state" in ('starting', 'running') and "template_key" is not null`)
|
|
61
64
|
]);
|
|
62
65
|
export function toRunnerInstance(row) {
|
|
63
|
-
if (!row.providerRunnerId) throw new Error('
|
|
66
|
+
if (!row.providerRunnerId) throw new Error('Runner instance has no provider runner identity');
|
|
64
67
|
return {
|
|
65
68
|
id: row.id,
|
|
66
69
|
workspaceId: row.workspaceId,
|
|
67
70
|
provisionerId: row.provisionerId,
|
|
68
71
|
providerRunnerId: row.providerRunnerId,
|
|
69
72
|
reservationId: row.reservationId,
|
|
73
|
+
assignedAt: row.assignedAt,
|
|
70
74
|
templateKey: row.templateKey,
|
|
71
75
|
labels: row.labels,
|
|
72
76
|
state: row.state,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db/schema/runner-instances.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {sql} from 'drizzle-orm';\nimport {index, jsonb, pgEnum, text, timestamp, uniqueIndex, uuid} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance} from '#core/entities/runner-instance.js';\nimport {pgTable} from './common.js';\n\nexport const providerRunnerStateEnum = pgEnum('runners_provider_runner_state', [\n 'starting',\n 'running',\n 'stopping',\n 'stopped',\n 'failed',\n 'terminated',\n]);\n\nexport const providerRunners = pgTable(\n 'runner_instances',\n {\n id: uuidv7PrimaryKey(),\n // Kept during the protocol migration for legacy workspace capacity. New capacity is owned\n // only by its provisioner and has no workspace assignment.\n workspaceId: uuid('workspace_id'),\n provisionerId: uuid('provisioner_id').notNull(),\n providerRunnerId: text('provider_runner_id'),\n reservationId: uuid('reservation_id'),\n templateKey: text('template_key'),\n labels: text('labels').array().notNull().default([]),\n state: providerRunnerStateEnum('state').notNull(),\n reason: text('reason'),\n runnerSessionId: uuid('runner_session_id'),\n providerKind: text('provider_kind'),\n protocolVersion: text('protocol_version'),\n capabilities: jsonb('capabilities').$type<RunnerToolCapabilitiesDto | null>(),\n reportedAt: timestamp('reported_at', {withTimezone: true}).notNull(),\n startedAt: timestamp('started_at', {withTimezone: true}),\n stoppingAt: timestamp('stopping_at', {withTimezone: true}),\n stoppedAt: timestamp('stopped_at', {withTimezone: true}),\n failedAt: timestamp('failed_at', {withTimezone: true}),\n terminatedAt: timestamp('terminated_at', {withTimezone: true}),\n reservationReleasedAt: timestamp('reservation_released_at', {withTimezone: true}),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('runners_runner_instances_provisioner_runner_unique')\n .on(table.provisionerId, table.providerRunnerId)\n .where(sql`${table.providerRunnerId} is not null`),\n index('runners_runner_instances_workspace_state_updated_idx').on(table.state, table.updatedAt),\n index('runners_runner_instances_stale_reaper_idx').on(\n table.state,\n table.updatedAt,\n table.reportedAt,\n ),\n index('runners_runner_instances_active_template_counts_idx')\n .on(table.provisionerId, table.state, table.templateKey)\n .where(sql`\"state\" in ('starting', 'running') and \"template_key\" is not null`),\n ],\n);\n\nexport type RunnerInstanceDb = typeof providerRunners.$inferSelect;\nexport type RunnerInstanceInsertDb = typeof providerRunners.$inferInsert;\n\nexport function toRunnerInstance(row: RunnerInstanceDb): RunnerInstance {\n if (!row.providerRunnerId) throw new Error('
|
|
1
|
+
{"version":3,"sources":["../../../src/db/schema/runner-instances.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {uuidv7PrimaryKey} from '@shipfox/node-drizzle';\nimport {sql} from 'drizzle-orm';\nimport {index, jsonb, pgEnum, text, timestamp, uniqueIndex, uuid} from 'drizzle-orm/pg-core';\nimport type {RunnerInstance} from '#core/entities/runner-instance.js';\nimport {pgTable} from './common.js';\n\nexport const providerRunnerStateEnum = pgEnum('runners_provider_runner_state', [\n 'starting',\n 'running',\n 'stopping',\n 'stopped',\n 'failed',\n 'terminated',\n]);\n\nexport const providerRunners = pgTable(\n 'runner_instances',\n {\n id: uuidv7PrimaryKey(),\n // Kept during the protocol migration for legacy workspace capacity. New capacity is owned\n // only by its provisioner and has no workspace assignment.\n workspaceId: uuid('workspace_id'),\n provisionerId: uuid('provisioner_id').notNull(),\n providerRunnerId: text('provider_runner_id'),\n reservationId: uuid('reservation_id'),\n assignedAt: timestamp('assigned_at', {withTimezone: true}),\n templateKey: text('template_key'),\n labels: text('labels').array().notNull().default([]),\n state: providerRunnerStateEnum('state').notNull(),\n reason: text('reason'),\n runnerSessionId: uuid('runner_session_id'),\n providerKind: text('provider_kind'),\n protocolVersion: text('protocol_version'),\n capabilities: jsonb('capabilities').$type<RunnerToolCapabilitiesDto | null>(),\n reportedAt: timestamp('reported_at', {withTimezone: true}).notNull(),\n startedAt: timestamp('started_at', {withTimezone: true}),\n stoppingAt: timestamp('stopping_at', {withTimezone: true}),\n stoppedAt: timestamp('stopped_at', {withTimezone: true}),\n failedAt: timestamp('failed_at', {withTimezone: true}),\n terminatedAt: timestamp('terminated_at', {withTimezone: true}),\n reservationReleasedAt: timestamp('reservation_released_at', {withTimezone: true}),\n createdAt: timestamp('created_at', {withTimezone: true}).notNull().defaultNow(),\n updatedAt: timestamp('updated_at', {withTimezone: true}).notNull().defaultNow(),\n },\n (table) => [\n uniqueIndex('runners_runner_instances_provisioner_runner_unique')\n .on(table.provisionerId, table.providerRunnerId)\n .where(sql`${table.providerRunnerId} is not null`),\n index('runners_runner_instances_workspace_state_updated_idx').on(table.state, table.updatedAt),\n index('runners_runner_instances_stale_reaper_idx').on(\n table.state,\n table.updatedAt,\n table.reportedAt,\n ),\n index('runners_runner_instances_active_template_counts_idx')\n .on(table.provisionerId, table.state, table.templateKey)\n .where(sql`\"state\" in ('starting', 'running') and \"template_key\" is not null`),\n ],\n);\n\nexport type RunnerInstanceDb = typeof providerRunners.$inferSelect;\nexport type RunnerInstanceInsertDb = typeof providerRunners.$inferInsert;\n\nexport function toRunnerInstance(row: RunnerInstanceDb): RunnerInstance {\n if (!row.providerRunnerId) throw new Error('Runner instance has no provider runner identity');\n return {\n id: row.id,\n workspaceId: row.workspaceId,\n provisionerId: row.provisionerId,\n providerRunnerId: row.providerRunnerId,\n reservationId: row.reservationId,\n assignedAt: row.assignedAt,\n templateKey: row.templateKey,\n labels: row.labels,\n state: row.state,\n reason: row.reason,\n runnerSessionId: row.runnerSessionId,\n providerKind: row.providerKind,\n reportedAt: row.reportedAt,\n startedAt: row.startedAt,\n stoppingAt: row.stoppingAt,\n stoppedAt: row.stoppedAt,\n failedAt: row.failedAt,\n terminatedAt: row.terminatedAt,\n reservationReleasedAt: row.reservationReleasedAt,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n"],"names":["uuidv7PrimaryKey","sql","index","jsonb","pgEnum","text","timestamp","uniqueIndex","uuid","pgTable","providerRunnerStateEnum","providerRunners","id","workspaceId","provisionerId","notNull","providerRunnerId","reservationId","assignedAt","withTimezone","templateKey","labels","array","default","state","reason","runnerSessionId","providerKind","protocolVersion","capabilities","$type","reportedAt","startedAt","stoppingAt","stoppedAt","failedAt","terminatedAt","reservationReleasedAt","createdAt","defaultNow","updatedAt","table","on","where","toRunnerInstance","row","Error"],"mappings":"AACA,SAAQA,gBAAgB,QAAO,wBAAwB;AACvD,SAAQC,GAAG,QAAO,cAAc;AAChC,SAAQC,KAAK,EAAEC,KAAK,EAAEC,MAAM,EAAEC,IAAI,EAAEC,SAAS,EAAEC,WAAW,EAAEC,IAAI,QAAO,sBAAsB;AAE7F,SAAQC,OAAO,QAAO,cAAc;AAEpC,OAAO,MAAMC,0BAA0BN,OAAO,iCAAiC;IAC7E;IACA;IACA;IACA;IACA;IACA;CACD,EAAE;AAEH,OAAO,MAAMO,kBAAkBF,QAC7B,oBACA;IACEG,IAAIZ;IACJ,0FAA0F;IAC1F,2DAA2D;IAC3Da,aAAaL,KAAK;IAClBM,eAAeN,KAAK,kBAAkBO,OAAO;IAC7CC,kBAAkBX,KAAK;IACvBY,eAAeT,KAAK;IACpBU,YAAYZ,UAAU,eAAe;QAACa,cAAc;IAAI;IACxDC,aAAaf,KAAK;IAClBgB,QAAQhB,KAAK,UAAUiB,KAAK,GAAGP,OAAO,GAAGQ,OAAO,CAAC,EAAE;IACnDC,OAAOd,wBAAwB,SAASK,OAAO;IAC/CU,QAAQpB,KAAK;IACbqB,iBAAiBlB,KAAK;IACtBmB,cAActB,KAAK;IACnBuB,iBAAiBvB,KAAK;IACtBwB,cAAc1B,MAAM,gBAAgB2B,KAAK;IACzCC,YAAYzB,UAAU,eAAe;QAACa,cAAc;IAAI,GAAGJ,OAAO;IAClEiB,WAAW1B,UAAU,cAAc;QAACa,cAAc;IAAI;IACtDc,YAAY3B,UAAU,eAAe;QAACa,cAAc;IAAI;IACxDe,WAAW5B,UAAU,cAAc;QAACa,cAAc;IAAI;IACtDgB,UAAU7B,UAAU,aAAa;QAACa,cAAc;IAAI;IACpDiB,cAAc9B,UAAU,iBAAiB;QAACa,cAAc;IAAI;IAC5DkB,uBAAuB/B,UAAU,2BAA2B;QAACa,cAAc;IAAI;IAC/EmB,WAAWhC,UAAU,cAAc;QAACa,cAAc;IAAI,GAAGJ,OAAO,GAAGwB,UAAU;IAC7EC,WAAWlC,UAAU,cAAc;QAACa,cAAc;IAAI,GAAGJ,OAAO,GAAGwB,UAAU;AAC/E,GACA,CAACE,QAAU;QACTlC,YAAY,sDACTmC,EAAE,CAACD,MAAM3B,aAAa,EAAE2B,MAAMzB,gBAAgB,EAC9C2B,KAAK,CAAC1C,GAAG,CAAC,EAAEwC,MAAMzB,gBAAgB,CAAC,YAAY,CAAC;QACnDd,MAAM,wDAAwDwC,EAAE,CAACD,MAAMjB,KAAK,EAAEiB,MAAMD,SAAS;QAC7FtC,MAAM,6CAA6CwC,EAAE,CACnDD,MAAMjB,KAAK,EACXiB,MAAMD,SAAS,EACfC,MAAMV,UAAU;QAElB7B,MAAM,uDACHwC,EAAE,CAACD,MAAM3B,aAAa,EAAE2B,MAAMjB,KAAK,EAAEiB,MAAMrB,WAAW,EACtDuB,KAAK,CAAC1C,GAAG,CAAC,iEAAiE,CAAC;KAChF,EACD;AAKF,OAAO,SAAS2C,iBAAiBC,GAAqB;IACpD,IAAI,CAACA,IAAI7B,gBAAgB,EAAE,MAAM,IAAI8B,MAAM;IAC3C,OAAO;QACLlC,IAAIiC,IAAIjC,EAAE;QACVC,aAAagC,IAAIhC,WAAW;QAC5BC,eAAe+B,IAAI/B,aAAa;QAChCE,kBAAkB6B,IAAI7B,gBAAgB;QACtCC,eAAe4B,IAAI5B,aAAa;QAChCC,YAAY2B,IAAI3B,UAAU;QAC1BE,aAAayB,IAAIzB,WAAW;QAC5BC,QAAQwB,IAAIxB,MAAM;QAClBG,OAAOqB,IAAIrB,KAAK;QAChBC,QAAQoB,IAAIpB,MAAM;QAClBC,iBAAiBmB,IAAInB,eAAe;QACpCC,cAAckB,IAAIlB,YAAY;QAC9BI,YAAYc,IAAId,UAAU;QAC1BC,WAAWa,IAAIb,SAAS;QACxBC,YAAYY,IAAIZ,UAAU;QAC1BC,WAAWW,IAAIX,SAAS;QACxBC,UAAUU,IAAIV,QAAQ;QACtBC,cAAcS,IAAIT,YAAY;QAC9BC,uBAAuBQ,IAAIR,qBAAqB;QAChDC,WAAWO,IAAIP,SAAS;QACxBE,WAAWK,IAAIL,SAAS;IAC1B;AACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
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
|
-
export { type MintEphemeralRegistrationTokenParams, type MintEphemeralRegistrationTokenResult, type MintEphemeralRegistrationTokensBatchParams, type MintEphemeralRegistrationTokensBatchResult, type MintEphemeralRegistrationTokensBatchRunnerInstance, mintEphemeralRegistrationToken, mintEphemeralRegistrationTokensBatch, } from '#core/ephemeral-registration-tokens.js';
|
|
5
4
|
export { type EffectiveRunnerToolCapabilitiesResult, getEffectiveRunnerToolCapabilities, unadvertisedRunnerTools, } from '#core/runner-tool-capabilities.js';
|
|
6
5
|
export { cancelRunnerJobs, type EnqueueJobExecutionParams, enqueueJobExecution, isJobLeaseActive, releaseJobExecution, } from '#db/index.js';
|
|
7
6
|
export type { CreateRunnersModuleOptions, InstallationProvisioningPolicy, } from '#installation-provisioning.js';
|
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;AAM9E,OAAO,EAAC,KAAK,aAAa,EAAoB,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;AAa9E,OAAO,EACL,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;AAM9E,OAAO,EAAC,KAAK,aAAa,EAAoB,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;AAa9E,OAAO,EACL,KAAK,qCAAqC,EAC1C,kCAAkC,EAClC,uBAAuB,GACxB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,gBAAgB,EAChB,KAAK,yBAAyB,EAC9B,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,GACpB,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,CAyB5E"}
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,6 @@ import { createProvisionerTokenAuthMethod, createRunnerControlSessionAuthMethod,
|
|
|
9
9
|
import { createRunnersInterModulePresentation } from '#presentation/inter-module.js';
|
|
10
10
|
import { createRunnersMaintenanceActivities } from '#temporal/activities/index.js';
|
|
11
11
|
import { RUNNERS_MAINTENANCE_TASK_QUEUE } from '#temporal/constants.js';
|
|
12
|
-
export { mintEphemeralRegistrationToken, mintEphemeralRegistrationTokensBatch } from '#core/ephemeral-registration-tokens.js';
|
|
13
12
|
export { getEffectiveRunnerToolCapabilities, unadvertisedRunnerTools } from '#core/runner-tool-capabilities.js';
|
|
14
13
|
export { cancelRunnerJobs, enqueueJobExecution, isJobLeaseActive, releaseJobExecution } from '#db/index.js';
|
|
15
14
|
const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
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 {runnersEventSchemas} from '@shipfox/api-runners-dto';\nimport {\n WORKFLOWS_JOB_EXECUTION_TIMED_OUT,\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 onWorkflowsJobExecutionTimedOut,\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\nexport {\n type
|
|
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 {runnersEventSchemas} from '@shipfox/api-runners-dto';\nimport {\n WORKFLOWS_JOB_EXECUTION_TIMED_OUT,\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 onWorkflowsJobExecutionTimedOut,\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\nexport {\n type EffectiveRunnerToolCapabilitiesResult,\n getEffectiveRunnerToolCapabilities,\n unadvertisedRunnerTools,\n} from '#core/runner-tool-capabilities.js';\nexport {\n cancelRunnerJobs,\n type EnqueueJobExecutionParams,\n enqueueJobExecution,\n isJobLeaseActive,\n releaseJobExecution,\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},\n auth: [\n createRunnerRegistrationTokenAuthMethod(),\n createRunnerControlSessionAuthMethod(),\n createProvisionerTokenAuthMethod(),\n ],\n routes: createRunnerRoutes(auth, options),\n metrics: registerRunnersServiceMetrics,\n publishers: [{name: 'runners', table: runnersOutbox, db, eventSchemas: runnersEventSchemas}],\n subscribers: [subscriber(WORKFLOWS_JOB_EXECUTION_TIMED_OUT, onWorkflowsJobExecutionTimedOut)],\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","runnersEventSchemas","WORKFLOWS_JOB_EXECUTION_TIMED_OUT","subscriberFactory","db","migrationsPath","runnersOutbox","registerRunnersServiceMetrics","createProvisionerTokenAuthMethod","createRunnerControlSessionAuthMethod","createRunnerRegistrationTokenAuthMethod","createRunnerRoutes","onWorkflowsJobExecutionTimedOut","createRunnersInterModulePresentation","createRunnersMaintenanceActivities","RUNNERS_MAINTENANCE_TASK_QUEUE","getEffectiveRunnerToolCapabilities","unadvertisedRunnerTools","cancelRunnerJobs","enqueueJobExecution","isJobLeaseActive","releaseJobExecution","packageRoot","url","workflowsPath","subscriber","createRunnersModule","auth","options","name","database","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,mBAAmB,QAAO,2BAA2B;AAC7D,SACEC,iCAAiC,QAE5B,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,+BAA+B,QAC1B,yBAAyB;AAChC,SAAQC,oCAAoC,QAAO,gCAAgC;AACnF,SAAQC,kCAAkC,QAAO,gCAAgC;AACjF,SAAQC,8BAA8B,QAAO,yBAAyB;AAEtE,SAEEC,kCAAkC,EAClCC,uBAAuB,QAClB,oCAAoC;AAC3C,SACEC,gBAAgB,EAEhBC,mBAAmB,EACnBC,gBAAgB,EAChBC,mBAAmB,QACd,eAAe;AAMtB,MAAMC,cAAcvB,QAAQD,QAAQE,cAAc,YAAYuB,GAAG,IAAI;AACrE,MAAMC,gBAAgBzB,QAAQuB,aAAa;AAE3C,MAAMG,aAAatB;AAEnB,OAAO,SAASuB,oBAAoB,EAClCC,IAAI,EACJ,GAAGC,SACwD;IAC3D,OAAO;QACLC,MAAM;QACNC,UAAU;YAAC1B;YAAIC;QAAc;QAC7BsB,MAAM;YACJjB;YACAD;YACAD;SACD;QACDuB,QAAQpB,mBAAmBgB,MAAMC;QACjCI,SAASzB;QACT0B,YAAY;YAAC;gBAACJ,MAAM;gBAAWK,OAAO5B;gBAAeF;gBAAI+B,cAAclC;YAAmB;SAAE;QAC5FmC,aAAa;YAACX,WAAWvB,mCAAmCU;SAAiC;QAC7FyB,SAAS;YACP;gBACEC,WAAWvB;gBACXS;gBACAe,YAAYzB;gBACZ0B,WAAW;oBACT;wBAACX,MAAM;wBAAoBY,IAAI;wBAAsBC,cAAc;oBAAW;iBAC/E;YACH;SACD;QACDC,0BAA0B;YAAC9B;SAAuC;IACpE;AACF"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { toActiveProvisionerDto } from './active-provisioner.js';
|
|
2
2
|
export { toManualRegistrationTokenDto } from './manual-registration-token.js';
|
|
3
|
-
export { toMintRegistrationTokensResponseDto, toMintRegistrationTokensRunnerInstances, } from './mint-registration-tokens.js';
|
|
4
3
|
export { toPollDemandResponseDto } from './poll-demand.js';
|
|
5
4
|
export { toProvisionerTokenDto } from './provisioner-token.js';
|
|
6
5
|
export { toActiveRunnersResponseDto, toReconcileRunnerInstancesResponseDto, toReportRunnerInstancesResponseDto, } from './runner-instances.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAC,4BAA4B,EAAC,MAAM,gCAAgC,CAAC;AAC5E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/dto/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,sBAAsB,EAAC,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAC,4BAA4B,EAAC,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAC,uBAAuB,EAAC,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAC,qBAAqB,EAAC,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,0BAA0B,EAC1B,qCAAqC,EACrC,kCAAkC,GACnC,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { toActiveProvisionerDto } from './active-provisioner.js';
|
|
2
2
|
export { toManualRegistrationTokenDto } from './manual-registration-token.js';
|
|
3
|
-
export { toMintRegistrationTokensResponseDto, toMintRegistrationTokensRunnerInstances } from './mint-registration-tokens.js';
|
|
4
3
|
export { toPollDemandResponseDto } from './poll-demand.js';
|
|
5
4
|
export { toProvisionerTokenDto } from './provisioner-token.js';
|
|
6
5
|
export { toActiveRunnersResponseDto, toReconcileRunnerInstancesResponseDto, toReportRunnerInstancesResponseDto } from './runner-instances.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/presentation/dto/index.ts"],"sourcesContent":["export {toActiveProvisionerDto} from './active-provisioner.js';\nexport {toManualRegistrationTokenDto} from './manual-registration-token.js';\nexport {
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/dto/index.ts"],"sourcesContent":["export {toActiveProvisionerDto} from './active-provisioner.js';\nexport {toManualRegistrationTokenDto} from './manual-registration-token.js';\nexport {toPollDemandResponseDto} from './poll-demand.js';\nexport {toProvisionerTokenDto} from './provisioner-token.js';\nexport {\n toActiveRunnersResponseDto,\n toReconcileRunnerInstancesResponseDto,\n toReportRunnerInstancesResponseDto,\n} from './runner-instances.js';\n"],"names":["toActiveProvisionerDto","toManualRegistrationTokenDto","toPollDemandResponseDto","toProvisionerTokenDto","toActiveRunnersResponseDto","toReconcileRunnerInstancesResponseDto","toReportRunnerInstancesResponseDto"],"mappings":"AAAA,SAAQA,sBAAsB,QAAO,0BAA0B;AAC/D,SAAQC,4BAA4B,QAAO,iCAAiC;AAC5E,SAAQC,uBAAuB,QAAO,mBAAmB;AACzD,SAAQC,qBAAqB,QAAO,yBAAyB;AAC7D,SACEC,0BAA0B,EAC1BC,qCAAqC,EACrCC,kCAAkC,QAC7B,wBAAwB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assign-runner-instances.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/assign-runner-instances.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,0BAA0B,iDAkCrC,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { requireProvisionerContext } from '@shipfox/api-auth-context';
|
|
2
|
+
import { assignRunnerInstancesBodySchema, assignRunnerInstancesResponseSchema } from '@shipfox/api-runners-dto';
|
|
3
|
+
import { ClientError, defineRoute } from '@shipfox/node-fastify';
|
|
4
|
+
import { ReservationExpiredError, ReservationNotFoundError, RunnerInstanceAlreadyAssignedError, RunnerInstanceNotAssignableError } from '#core/errors.js';
|
|
5
|
+
import { assignRunnerInstances } from '#core/runner-assignments.js';
|
|
6
|
+
export const assignRunnerInstancesRoute = defineRoute({
|
|
7
|
+
method: 'POST',
|
|
8
|
+
path: '/runner-instances/assignments',
|
|
9
|
+
description: 'Assign enrolled runner instances to an owned demand reservation',
|
|
10
|
+
schema: {
|
|
11
|
+
body: assignRunnerInstancesBodySchema,
|
|
12
|
+
response: {
|
|
13
|
+
200: assignRunnerInstancesResponseSchema
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
errorHandler: (error)=>{
|
|
17
|
+
if (error instanceof ReservationNotFoundError) throw new ClientError('Reservation not found', 'reservation-not-found', {
|
|
18
|
+
status: 404
|
|
19
|
+
});
|
|
20
|
+
if (error instanceof ReservationExpiredError) throw new ClientError('Reservation has expired', 'reservation-expired', {
|
|
21
|
+
status: 409
|
|
22
|
+
});
|
|
23
|
+
if (error instanceof RunnerInstanceAlreadyAssignedError || error instanceof RunnerInstanceNotAssignableError) throw new ClientError('Runner instance cannot be assigned', 'runner-instance-not-assignable', {
|
|
24
|
+
status: 409
|
|
25
|
+
});
|
|
26
|
+
throw error;
|
|
27
|
+
},
|
|
28
|
+
handler: async (request)=>{
|
|
29
|
+
const { provisionerTokenId } = requireProvisionerContext(request);
|
|
30
|
+
return {
|
|
31
|
+
runner_instance_ids: await assignRunnerInstances({
|
|
32
|
+
provisionerId: provisionerTokenId,
|
|
33
|
+
reservationId: request.body.reservation_id,
|
|
34
|
+
runnerInstanceIds: request.body.runner_instance_ids
|
|
35
|
+
})
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=assign-runner-instances.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/presentation/routes/assign-runner-instances.ts"],"sourcesContent":["import {requireProvisionerContext} from '@shipfox/api-auth-context';\nimport {\n assignRunnerInstancesBodySchema,\n assignRunnerInstancesResponseSchema,\n} from '@shipfox/api-runners-dto';\nimport {ClientError, defineRoute} from '@shipfox/node-fastify';\nimport {\n ReservationExpiredError,\n ReservationNotFoundError,\n RunnerInstanceAlreadyAssignedError,\n RunnerInstanceNotAssignableError,\n} from '#core/errors.js';\nimport {assignRunnerInstances} from '#core/runner-assignments.js';\n\nexport const assignRunnerInstancesRoute = defineRoute({\n method: 'POST',\n path: '/runner-instances/assignments',\n description: 'Assign enrolled runner instances to an owned demand reservation',\n schema: {\n body: assignRunnerInstancesBodySchema,\n response: {200: assignRunnerInstancesResponseSchema},\n },\n errorHandler: (error) => {\n if (error instanceof ReservationNotFoundError)\n throw new ClientError('Reservation not found', 'reservation-not-found', {status: 404});\n if (error instanceof ReservationExpiredError)\n throw new ClientError('Reservation has expired', 'reservation-expired', {status: 409});\n if (\n error instanceof RunnerInstanceAlreadyAssignedError ||\n error instanceof RunnerInstanceNotAssignableError\n )\n throw new ClientError(\n 'Runner instance cannot be assigned',\n 'runner-instance-not-assignable',\n {status: 409},\n );\n throw error;\n },\n handler: async (request) => {\n const {provisionerTokenId} = requireProvisionerContext(request);\n return {\n runner_instance_ids: await assignRunnerInstances({\n provisionerId: provisionerTokenId,\n reservationId: request.body.reservation_id,\n runnerInstanceIds: request.body.runner_instance_ids,\n }),\n };\n },\n});\n"],"names":["requireProvisionerContext","assignRunnerInstancesBodySchema","assignRunnerInstancesResponseSchema","ClientError","defineRoute","ReservationExpiredError","ReservationNotFoundError","RunnerInstanceAlreadyAssignedError","RunnerInstanceNotAssignableError","assignRunnerInstances","assignRunnerInstancesRoute","method","path","description","schema","body","response","errorHandler","error","status","handler","request","provisionerTokenId","runner_instance_ids","provisionerId","reservationId","reservation_id","runnerInstanceIds"],"mappings":"AAAA,SAAQA,yBAAyB,QAAO,4BAA4B;AACpE,SACEC,+BAA+B,EAC/BC,mCAAmC,QAC9B,2BAA2B;AAClC,SAAQC,WAAW,EAAEC,WAAW,QAAO,wBAAwB;AAC/D,SACEC,uBAAuB,EACvBC,wBAAwB,EACxBC,kCAAkC,EAClCC,gCAAgC,QAC3B,kBAAkB;AACzB,SAAQC,qBAAqB,QAAO,8BAA8B;AAElE,OAAO,MAAMC,6BAA6BN,YAAY;IACpDO,QAAQ;IACRC,MAAM;IACNC,aAAa;IACbC,QAAQ;QACNC,MAAMd;QACNe,UAAU;YAAC,KAAKd;QAAmC;IACrD;IACAe,cAAc,CAACC;QACb,IAAIA,iBAAiBZ,0BACnB,MAAM,IAAIH,YAAY,yBAAyB,yBAAyB;YAACgB,QAAQ;QAAG;QACtF,IAAID,iBAAiBb,yBACnB,MAAM,IAAIF,YAAY,2BAA2B,uBAAuB;YAACgB,QAAQ;QAAG;QACtF,IACED,iBAAiBX,sCACjBW,iBAAiBV,kCAEjB,MAAM,IAAIL,YACR,sCACA,kCACA;YAACgB,QAAQ;QAAG;QAEhB,MAAMD;IACR;IACAE,SAAS,OAAOC;QACd,MAAM,EAACC,kBAAkB,EAAC,GAAGtB,0BAA0BqB;QACvD,OAAO;YACLE,qBAAqB,MAAMd,sBAAsB;gBAC/Ce,eAAeF;gBACfG,eAAeJ,QAAQN,IAAI,CAACW,cAAc;gBAC1CC,mBAAmBN,QAAQN,IAAI,CAACQ,mBAAmB;YACrD;QACF;IACF;AACF,GAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;AAC9E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/presentation/routes/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,oCAAoC,CAAC;AAC9E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,+BAA+B,CAAC;AAsF9E,eAAO,MAAM,iBAAiB,EAAE,UAAU,EAgBzC,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,qBAAqB,EAC3B,OAAO,GAAE,0BAA+B,GACvC,UAAU,EAAE,CAgBd"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AUTH_LEASED_JOB, AUTH_PROVISIONER_TOKEN, AUTH_RUNNER_REGISTRATION_TOKEN, AUTH_RUNNER_SESSION, AUTH_USER } from '@shipfox/api-auth-context';
|
|
2
|
-
import {
|
|
2
|
+
import { assignRunnerInstancesRoute } from './assign-runner-instances.js';
|
|
3
3
|
import { createManualRegistrationTokenRoute } from './create-manual-registration-token.js';
|
|
4
4
|
import { createProvisionerTokenRoute } from './create-provisioner-token.js';
|
|
5
5
|
import { getProvisionerMeRoute } from './get-provisioner-me.js';
|
|
@@ -8,8 +8,6 @@ import { listActiveProvisionersRoute } from './list-active-provisioners.js';
|
|
|
8
8
|
import { listActiveRunnersRoute } from './list-active-runners.js';
|
|
9
9
|
import { listManualRegistrationTokensRoute } from './list-manual-registration-tokens.js';
|
|
10
10
|
import { listProvisionerTokensRoute } from './list-provisioner-tokens.js';
|
|
11
|
-
import { mintRegistrationTokensRoute } from './mint-registration-tokens.js';
|
|
12
|
-
import { attachProviderRunnerRoute, createPlannedCapacityRoute } from './planned-capacity.js';
|
|
13
11
|
import { createPollDemandRoute, pollDemandRoute } from './poll-demand.js';
|
|
14
12
|
import { reconcileRunnerInstancesRoute } from './reconcile-runner-instances.js';
|
|
15
13
|
import { createRegisterRoute } from './register.js';
|
|
@@ -17,7 +15,7 @@ import { reportRunnerInstancesRoute } from './report-runner-instances.js';
|
|
|
17
15
|
import { createRequestJobRoute } from './request-job.js';
|
|
18
16
|
import { revokeManualRegistrationTokenRoute } from './revoke-manual-registration-token.js';
|
|
19
17
|
import { revokeProvisionerTokenRoute } from './revoke-provisioner-token.js';
|
|
20
|
-
import { attachRunnerControlProviderIdRoute, createRunnerInstancesRoute, enrollRunnerRoute, exchangeRunnerBootstrapRoute, runnerAssignmentPollRoute, runnerControlHeartbeatRoute } from './runner-enrollment.js';
|
|
18
|
+
import { attachRunnerControlProviderIdRoute, attachRunnerInstanceProviderIdRoute, createRunnerInstancesRoute, enrollRunnerRoute, exchangeRunnerBootstrapRoute, runnerAssignmentPollRoute, runnerControlHeartbeatRoute } from './runner-enrollment.js';
|
|
21
19
|
function createRunnerOnlyRoutes(auth) {
|
|
22
20
|
return [
|
|
23
21
|
{
|
|
@@ -63,10 +61,8 @@ function createRunnerOnlyRoutes(auth) {
|
|
|
63
61
|
routes: [
|
|
64
62
|
pollDemandRoute,
|
|
65
63
|
createRunnerInstancesRoute,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
assignCapacityRoute,
|
|
69
|
-
mintRegistrationTokensRoute,
|
|
64
|
+
attachRunnerInstanceProviderIdRoute,
|
|
65
|
+
assignRunnerInstancesRoute,
|
|
70
66
|
reportRunnerInstancesRoute,
|
|
71
67
|
reconcileRunnerInstancesRoute
|
|
72
68
|
]
|