@shipfox/api-runners 12.1.0 → 12.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +35 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +24 -2
- package/dist/config.js.map +1 -1
- package/dist/core/errors.d.ts +4 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +6 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/rate-limit.d.ts.map +1 -1
- package/dist/core/runner-control-sessions.d.ts.map +1 -1
- package/dist/core/runner-control-sessions.js +37 -11
- package/dist/core/runner-control-sessions.js.map +1 -1
- package/dist/core/runner-instances.d.ts +1 -0
- package/dist/core/runner-instances.d.ts.map +1 -1
- package/dist/core/runner-instances.js.map +1 -1
- package/dist/core/runner-labels.d.ts +11 -0
- package/dist/core/runner-labels.d.ts.map +1 -0
- package/dist/core/runner-labels.js +41 -0
- package/dist/core/runner-labels.js.map +1 -0
- package/dist/core/runner-sessions.d.ts.map +1 -1
- package/dist/core/runner-sessions.js +5 -1
- package/dist/core/runner-sessions.js.map +1 -1
- package/dist/db/db.d.ts +64 -64
- package/dist/db/ephemeral-registration-tokens.d.ts.map +1 -1
- package/dist/db/ephemeral-registration-tokens.js +12 -2
- package/dist/db/ephemeral-registration-tokens.js.map +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/reservations.d.ts.map +1 -1
- package/dist/db/reservations.js +36 -10
- package/dist/db/reservations.js.map +1 -1
- package/dist/db/runner-instances.d.ts +4 -0
- package/dist/db/runner-instances.d.ts.map +1 -1
- package/dist/db/runner-instances.js +16 -5
- package/dist/db/runner-instances.js.map +1 -1
- package/dist/db/runner-sessions.d.ts.map +1 -1
- package/dist/db/runner-sessions.js +33 -15
- package/dist/db/runner-sessions.js.map +1 -1
- package/dist/db/schema/admin-command-results.d.ts +1 -1
- package/dist/db/schema/ephemeral-registration-tokens.d.ts +1 -1
- package/dist/db/schema/manual-registration-tokens.d.ts +1 -1
- package/dist/db/schema/outbox.d.ts +1 -1
- package/dist/db/schema/pending-job-executions.d.ts +3 -3
- package/dist/db/schema/provisioner-capability-snapshots.d.ts +3 -3
- package/dist/db/schema/provisioner-tokens.d.ts +2 -2
- package/dist/db/schema/rate-limits.d.ts +1 -1
- package/dist/db/schema/reservations.d.ts +3 -3
- package/dist/db/schema/runner-activation-tokens.d.ts +1 -1
- package/dist/db/schema/runner-control-sessions.d.ts +2 -2
- package/dist/db/schema/runner-instances.d.ts +4 -4
- package/dist/db/schema/runner-instances.d.ts.map +1 -1
- package/dist/db/schema/runner-instances.js +1 -0
- package/dist/db/schema/runner-instances.js.map +1 -1
- package/dist/db/schema/runner-sessions.d.ts +4 -4
- package/dist/db/schema/running-job-executions.d.ts +5 -5
- package/dist/metrics/index.d.ts +2 -1
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +1 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/instance.d.ts +13 -8
- package/dist/metrics/instance.d.ts.map +1 -1
- package/dist/metrics/instance.js +8 -0
- package/dist/metrics/instance.js.map +1 -1
- package/dist/metrics/service.d.ts.map +1 -1
- package/dist/metrics/service.js +20 -4
- package/dist/metrics/service.js.map +1 -1
- package/dist/presentation/dto/admin-provisioner-token.d.ts +1 -1
- package/dist/presentation/dto/admin-provisioner-token.d.ts.map +1 -1
- package/dist/presentation/dto/admin-runner-instances.d.ts +2 -2
- package/dist/presentation/dto/admin-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/poll-demand.d.ts.map +1 -1
- package/dist/presentation/routes/poll-demand.js +12 -6
- package/dist/presentation/routes/poll-demand.js.map +1 -1
- package/dist/presentation/routes/rate-limit.d.ts.map +1 -1
- package/dist/presentation/routes/register.d.ts.map +1 -1
- package/dist/presentation/routes/register.js +9 -1
- package/dist/presentation/routes/register.js.map +1 -1
- package/dist/presentation/routes/report-runner-instances.d.ts.map +1 -1
- package/dist/presentation/routes/report-runner-instances.js +1 -0
- package/dist/presentation/routes/report-runner-instances.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/drizzle/0004_huge_skreet.sql +1 -0
- package/drizzle/meta/0004_snapshot.json +2194 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +9 -9
- package/src/config.test.ts +81 -0
- package/src/config.ts +39 -2
- package/src/core/errors.ts +9 -0
- package/src/core/index.ts +1 -0
- package/src/core/runner-control-sessions.test.ts +404 -0
- package/src/core/runner-control-sessions.ts +51 -11
- package/src/core/runner-instances.ts +1 -0
- package/src/core/runner-labels.test.ts +53 -0
- package/src/core/runner-labels.ts +51 -0
- package/src/core/runner-sessions.test.ts +34 -1
- package/src/core/runner-sessions.ts +8 -1
- package/src/db/ephemeral-registration-tokens.ts +15 -1
- package/src/db/index.ts +1 -0
- package/src/db/reservations.test.ts +537 -0
- package/src/db/reservations.ts +116 -17
- package/src/db/runner-instances.test.ts +276 -1
- package/src/db/runner-instances.ts +39 -3
- package/src/db/runner-sessions.ts +39 -15
- package/src/db/schema/runner-instances.ts +3 -0
- package/src/metrics/index.ts +2 -0
- package/src/metrics/instance.ts +18 -0
- package/src/metrics/service.test.ts +99 -0
- package/src/metrics/service.ts +24 -4
- package/src/presentation/routes/late-runner-enrollment.test.ts +230 -0
- package/src/presentation/routes/poll-demand.test.ts +116 -3
- package/src/presentation/routes/poll-demand.ts +18 -6
- package/src/presentation/routes/register.test.ts +116 -2
- package/src/presentation/routes/register.ts +7 -0
- package/src/presentation/routes/report-runner-instances.test.ts +33 -0
- package/src/presentation/routes/report-runner-instances.ts +1 -0
- package/src/presentation/routes/runner-enrollment.test.ts +65 -5
- package/src/temporal/activities/maintenance-activities.test.ts +24 -31
- package/test/env.ts +1 -0
- package/test/fixtures/late-runner-enrollment.ts +103 -0
- package/test/index.ts +5 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/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 {reservations} from './schema/reservations.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) 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 | null;\n provisionerId: string;\n providerRunnerIds: string[];\n requireUnlinkedSession?: boolean;\n },\n): Promise<number> {\n if (params.providerRunnerIds.length === 0) return 0;\n\n const reservationWorkspacePredicate =\n params.workspaceId === null\n ? sql``\n : sql`and ${eq(reservations.workspaceId, params.workspaceId)}`;\n\n const rows = await tx\n .select({\n id: providerRunners.id,\n releaseReservationId: sql<string | null>`coalesce(\n (select ${reservations.id}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.intendedReservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate}),\n (select ${reservations.id}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.reservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate})\n )`,\n releaseReservationWorkspaceId: sql<string | null>`coalesce(\n (select ${reservations.workspaceId}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.intendedReservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate}),\n (select ${reservations.workspaceId}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.reservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate})\n )`,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.providerRunnerId, params.providerRunnerIds),\n inArray(providerRunners.state, terminalStates),\n or(\n isNotNull(providerRunners.reservationId),\n isNotNull(providerRunners.intendedReservationId),\n ),\n params.workspaceId === null\n ? undefined\n : or(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n or(\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.reservationId),\n ),\n ),\n ),\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.intendedReservationId),\n ),\n ),\n ),\n ),\n ),\n and(\n isNull(providerRunners.workspaceId),\n isNotNull(providerRunners.intendedReservationId),\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.intendedReservationId),\n ),\n ),\n ),\n ),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .for('update');\n\n if (rows.length === 0) return 0;\n\n const updated = await tx\n .update(providerRunners)\n .set({\n intendedReservationId: null,\n reservationReleasedAt: sql`now()`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(\n providerRunners.id,\n rows.map((row) => row.id),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .returning({id: providerRunners.id});\n\n const releasesByReservationId = new Map<\n string,\n {workspaceId: string; reservationId: string; count: number}\n >();\n const updatedIds = new Set(updated.map((row) => row.id));\n for (const row of rows) {\n if (!updatedIds.has(row.id)) continue;\n if (!row.releaseReservationId || !row.releaseReservationWorkspaceId) continue;\n const key = `${row.releaseReservationWorkspaceId}:${row.releaseReservationId}`;\n const release = releasesByReservationId.get(key) ?? {\n workspaceId: row.releaseReservationWorkspaceId,\n reservationId: row.releaseReservationId,\n count: 0,\n };\n release.count += 1;\n releasesByReservationId.set(key, release);\n }\n\n if (releasesByReservationId.size === 0) return 0;\n\n let released = 0;\n for (const release of releasesByReservationId.values()) {\n released += await releaseReservationUnits(tx, {\n workspaceId: release.workspaceId,\n provisionerId: params.provisionerId,\n releases: [{reservationId: release.reservationId, count: release.count}],\n });\n }\n return released;\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 | null; provisionerId: string; providerRunnerIds: string[]}> {\n const groups = new Map<\n string,\n {workspaceId: string | null; provisionerId: string; providerRunnerIds: string[]}\n >();\n for (const row of rows) {\n if (!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","reservations","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","reservationWorkspacePredicate","releaseReservationId","intendedReservationId","releaseReservationWorkspaceId","reservationReleasedAt","for","releasesByReservationId","updatedIds","has","key","release","get","size","released","releases","lastSeenAt","groups","push","tokenRows","consumedSessionId","consumedAt","createdAt","consumedSessionIdsByRunnerInstanceId","byRunnerInstanceId","rawEvent","toRunnerInstanceReportRow","existing","mergeMilestones","compareRunnerInstanceReportEvents","mergeProjectionMetadata","source","earliestDate","pickMilestones","a","b","timeDelta","getTime","rankDelta","getRunnerInstanceStateRank","providerRunnerStateRank","milestoneNeedsUpdate","current","incoming","includes"],"mappings":"AAAA,SAAQA,MAAM,QAAO,8BAA8B;AACnD,SAAQC,kBAAkB,QAAO,yBAAyB;AAC1D,SACEC,GAAG,EACHC,GAAG,EACHC,IAAI,EACJC,EAAE,EACFC,MAAM,EACNC,EAAE,EACFC,OAAO,EACPC,SAAS,EACTC,MAAM,EACNC,EAAE,EACFC,SAAS,EACTC,UAAU,EACVC,EAAE,EAEFC,GAAG,QACE,cAAc;AACrB,SAAQC,KAAK,QAAO,sBAAsB;AAG1C,SAAQC,EAAE,QAAO,UAAU;AAC3B,SACEC,0CAA0C,QAErC,sBAAsB;AAC7B,SAAQC,uBAAuB,QAAO,oBAAoB;AAC1D,SAAQC,2BAA2B,QAAO,4CAA4C;AACtF,SAAQC,iBAAiB,QAAO,iCAAiC;AACjE,SAAQC,YAAY,QAAO,2BAA2B;AACtD,SAAQC,eAAe,EAAEC,gBAAgB,QAAO,+BAA+B;AAC/E,SAAQC,cAAc,QAAO,8BAA8B;AAC3D,SAAQC,oBAAoB,QAAO,qCAAqC;AAExE,OAAO,MAAMC,iBAAiB;IAC5B;IACA;IACA;CACD,CAAmD;AACpD,OAAO,MAAMC,eAAe;IAC1B;IACA;IACA;CACD,CAAmD;AACpD,OAAO,MAAMC,wBAAwB;IAAC;IAAY;CAAU,CAGxD;AAoDJ,OAAO,eAAeC,+BAA+BC,MAIpD;IACC,MAAMC,UAAU,MAAMf,KACnBgB,MAAM,CAACV,iBACPW,GAAG,CAAC;QAACC,kBAAkBJ,OAAOI,gBAAgB;QAAEC,WAAWrB,GAAG,CAAC,KAAK,CAAC;IAAA,GACrEsB,KAAK,CACJnC,IACEG,GAAGkB,gBAAgBe,EAAE,EAAEP,OAAOQ,gBAAgB,GAC9ClC,GAAGkB,gBAAgBiB,aAAa,EAAET,OAAOS,aAAa,GACtD9B,OAAOa,gBAAgBY,gBAAgB,GACvCtB,WAAWU,gBAAgBkB,KAAK,EAAE;WAAId;KAAe,IAGxDe,SAAS,CAAC;QAACJ,IAAIf,gBAAgBe,EAAE;IAAA;IACpC,OAAON,QAAQW,MAAM,KAAK;AAC5B;AAiBA,OAAO,eAAeC,sBAAsBb,MAAmC;IAK7E,IAAIA,OAAOc,MAAM,CAACF,MAAM,KAAK,GAC3B,OAAO;QAACG,UAAU;QAAGC,sBAAsB;QAAGC,yBAAyB,EAAE;IAAA;IAE3E,OAAO,MAAM/B,KAAKgC,WAAW,CAAC,OAAOC;QACnC,MAAMC,aAAa,IAAIC;QACvB,MAAMC,mBAAmBC,gBAAgBvB,OAAOc,MAAM,EAAEM;QACxD,MAAMI,mBAAmBF,iBAAiBG,IAAI,CAAC,CAACC,QAAUC,gBAAgBD,MAAMhB,KAAK;QAErF,IAAIc,kBAAkB;YACpB,MAAML,GAAGS,OAAO,CACd5C,GAAG,CAAC,sCAAsC,EAAEgB,OAAO6B,WAAW,IAAI7B,OAAOS,aAAa,CAAC,EAAE,CAAC;QAE9F;QAEA,MAAMK,SAAS,MAAMgB,0CAA0CX,IAAInB,QAAQsB;QAC3E,MAAML,0BAA0B,MAAMc,iDACpCZ,IACAnB,QACAc;QAGF,MAAMkB,SAASlB,OAAOmB,GAAG,CAAC,CAACP,QAAW,CAAA;gBACpCG,aAAa7B,OAAO6B,WAAW;gBAC/BpB,eAAeT,OAAOS,aAAa;gBACnCL,kBAAkBsB,MAAMtB,gBAAgB;gBACxC8B,eAAeR,MAAMQ,aAAa;gBAClCC,aAAaT,MAAMS,WAAW;gBAC9BC,QAAQ;uBAAIlE,mBAAmBwD,MAAMU,MAAM;iBAAE;gBAC7C1B,OAAOgB,MAAMhB,KAAK;gBAClB2B,QAAQX,MAAMW,MAAM;gBACpBC,iBAAiBZ,MAAMY,eAAe;gBACtCC,cAAcb,MAAMa,YAAY;gBAChCC,YAAYd,MAAMc,UAAU,GAAGpB,aAAaA,aAAaM,MAAMc,UAAU;gBACzEC,WAAWf,MAAMe,SAAS;gBAC1BC,YAAYhB,MAAMgB,UAAU;gBAC5BC,WAAWjB,MAAMiB,SAAS;gBAC1BC,UAAUlB,MAAMkB,QAAQ;gBACxBC,cAAcnB,MAAMmB,YAAY;YAClC,CAAA;QAEA,MAAM1B,GACH2B,MAAM,CAACtD,iBACPwC,MAAM,CAACA,QACPe,kBAAkB,CAAC;YAClBC,QAAQ;gBAACxD,gBAAgBiB,aAAa;gBAAEjB,gBAAgBY,gBAAgB;aAAC;YACzE6C,aAAavE,UAAUc,gBAAgBY,gBAAgB;YACvDD,KAAK;gBACH+B,eAAelD,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,wCAAwC,EAAE1D,gBAAgB0C,aAAa,CAAC,OAAO,EAAE1C,gBAAgB0C,aAAa,CAAC,IAAI,CAAC;gBAC7LC,aAAanD,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,sCAAsC,EAAE1D,gBAAgB2C,WAAW,CAAC,OAAO,EAAE3C,gBAAgB2C,WAAW,CAAC,IAAI,CAAC;gBACrLC,QAAQpD,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,2BAA2B,EAAE1D,gBAAgB4C,MAAM,CAAC,IAAI,CAAC;gBAC3H1B,OAAO1B,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,0BAA0B,EAAE1D,gBAAgBkB,KAAK,CAAC,IAAI,CAAC;gBACxH2B,QAAQrD,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,2BAA2B,EAAE1D,gBAAgB6C,MAAM,CAAC,IAAI,CAAC;gBAC3HC,iBAAiBtD,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,eAAe,EAAE1D,gBAAgB8C,eAAe,CAAC,mCAAmC,EAAE9C,gBAAgB8C,eAAe,CAAC,IAAI,CAAC;gBACtMC,cAAcvD,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,uCAAuC,EAAE1D,gBAAgB+C,YAAY,CAAC,OAAO,EAAE/C,gBAAgB+C,YAAY,CAAC,IAAI,CAAC;gBACzLC,YAAYxD,GAAG,CAAC,UAAU,EAAEkE,0CAA0C,gCAAgC,EAAE1D,gBAAgBgD,UAAU,CAAC,IAAI,CAAC;gBACxIC,WAAWU,gBAAgB3D,gBAAgBiD,SAAS,EAAEzD,GAAG,CAAC,mBAAmB,CAAC;gBAC9E0D,YAAYS,gBAAgB3D,gBAAgBkD,UAAU,EAAE1D,GAAG,CAAC,oBAAoB,CAAC;gBACjF2D,WAAWQ,gBAAgB3D,gBAAgBmD,SAAS,EAAE3D,GAAG,CAAC,mBAAmB,CAAC;gBAC9E4D,UAAUO,gBAAgB3D,gBAAgBoD,QAAQ,EAAE5D,GAAG,CAAC,kBAAkB,CAAC;gBAC3E6D,cAAcM,gBAAgB3D,gBAAgBqD,YAAY,EAAE7D,GAAG,CAAC,sBAAsB,CAAC;gBACvFqB,WAAWrB,GAAG,CAAC,KAAK,CAAC;YACvB;YACAoE,UAAUpE,GAAG,CAAC;UACZ,EAAEkE,0CAA0C;aACzC,EAAEG,yCAAyC;QAChD,CAAC;QACH;QAEF,MAAMrC,uBAAuBQ,mBACzB,MAAM8B,0CAA0CnC,IAAInB,QAAQc,UAC5D;QAEJ,OAAO;YAACC,UAAUD,OAAOF,MAAM;YAAEI;YAAsBC;QAAuB;IAChF;AACF;AAEA,OAAO,eAAesC,2CACpBpC,EAAM,EACNnB,MAAoD;IAEpD,MAAMwD,OAAO,MAAMrC,GAChBsC,MAAM,CAAC;QACNtB,aAAa3C,gBAAgB2C,WAAW;QACxCzB,OAAOlB,gBAAgBkB,KAAK;QAC5BgD,OAAO1E,GAAW,CAAC,aAAa,CAAC;IACnC,GACC2E,IAAI,CAACnE,iBACLc,KAAK,CACJnC,IACEG,GAAGkB,gBAAgBqC,WAAW,EAAE7B,OAAO6B,WAAW,GAClDvD,GAAGkB,gBAAgBiB,aAAa,EAAET,OAAOS,aAAa,GACtDhC,QAAQe,gBAAgBkB,KAAK,EAAEZ,wBAC/BpB,UAAUc,gBAAgB2C,WAAW,IAGxCyB,OAAO,CAACpE,gBAAgB2C,WAAW,EAAE3C,gBAAgBkB,KAAK;IAE7D,OAAO8C,KAAKK,OAAO,CAAC,CAACC,MACnBA,IAAI3B,WAAW,IAAI4B,uBAAuBD,IAAIpD,KAAK,IAC/C;YAAC;gBAACyB,aAAa2B,IAAI3B,WAAW;gBAAEzB,OAAOoD,IAAIpD,KAAK;gBAAEgD,OAAOI,IAAIJ,KAAK;YAAA;SAAE,GACpE,EAAE;AAEV;AAEA,OAAO,eAAeM,0BAA0BhE,MAI/C;IACC,MAAMwD,OAAO,MAAMtE,KAChBuE,MAAM,GACNE,IAAI,CAACnE,iBACLc,KAAK,CACJnC,IACEG,GAAGkB,gBAAgBqC,WAAW,EAAE7B,OAAO6B,WAAW,GAClDpD,QAAQe,gBAAgBkB,KAAK,EAAEb,eAC/Bb,GAAG,CAAC,EAAEQ,gBAAgBa,SAAS,CAAC,YAAY,EAAEL,OAAOiE,aAAa,CAAC,yBAAyB,CAAC,GAGhGC,OAAO,CAAC7F,KAAKmB,gBAAgBa,SAAS,GAAGhC,KAAKmB,gBAAgBe,EAAE,GAChE4D,KAAK,CAACnE,OAAOmE,KAAK,IAAI;IAEzB,OAAOX,KAAKvB,GAAG,CAACxC;AAClB;AAEA,OAAO,eAAe2E,gCAAgCpE,MAIrD;IACC,OAAO,MAAMd,KAAKgC,WAAW,CAAC,OAAOC;QACnC,MAAMqC,OAAO,MAAMa,qCAAqClD,IAAInB;QAC5D,OAAOwD,KAAKvB,GAAG,CAAC,CAAC6B,MAAQA,IAAI1D,gBAAgB;IAC/C;AACF;AAEA,OAAO,eAAeiE,qCACpBlD,EAAM,EACNnB,MAIC;IAED,MAAMwD,OAAO,MAAMc,iCAAiCnD,IAAInB,QACrDkE,OAAO,CAAC9F,IAAIoB,gBAAgBY,gBAAgB,GAC5C+D,KAAK,CAACnE,OAAOmE,KAAK,GAAG;IAExB,MAAMI,YAAYf,KAAK5C,MAAM,GAAGZ,OAAOmE,KAAK;IAC5C,MAAMK,eAAeD,YAAYf,KAAKiB,KAAK,CAAC,GAAGzE,OAAOmE,KAAK,IAAIX;IAC/D,IAAIe,WAAW;QACbtG,SAASyG,IAAI,CACX;YACE7C,aAAa7B,OAAO6B,WAAW;YAC/BpB,eAAeT,OAAOS,aAAa;YACnC0D,OAAOnE,OAAOmE,KAAK;YACnBQ,eAAeH,aAAa5D,MAAM;QACpC,GACA;IAEJ;IAEA,OAAO4D,aAAaX,OAAO,CAAC,CAACC,MAC3BA,IAAI1D,gBAAgB,GAAG;YAAC;gBAAC,GAAG0D,GAAG;gBAAE1D,kBAAkB0D,IAAI1D,gBAAgB;YAAA;SAAE,GAAG,EAAE;AAElF;AAEA,SAASkE,iCACPnD,EAAM,EACNnB,MAAkF;IAElF,MAAM4E,4BAA4B3F,MAAMU,sBAAsB;IAE9D,OAAOwB,GACJsC,MAAM,CAAC;QACNrD,kBAAkBZ,gBAAgBY,gBAAgB;QAClDiC,QAAQrD,GAAwC,CAAC,eAAe,CAAC;IACnE,GACC2E,IAAI,CAAChE,sBACLkF,SAAS,CACRrF,iBACArB,IACEG,GAAGkB,gBAAgBqC,WAAW,EAAElC,qBAAqBkC,WAAW,GAChEvD,GAAGkB,gBAAgBiB,aAAa,EAAEd,qBAAqBc,aAAa,GACpEnC,GAAGkB,gBAAgBY,gBAAgB,EAAET,qBAAqBS,gBAAgB,IAG7EE,KAAK,CACJnC,IACEG,GAAGqB,qBAAqBkC,WAAW,EAAE7B,OAAO6B,WAAW,GACvDvD,GAAGqB,qBAAqBc,aAAa,EAAET,OAAOS,aAAa,GAC3D/B,UAAUc,gBAAgBY,gBAAgB,GAC1C1B,UAAUiB,qBAAqBmF,uBAAuB,GACtDrG,QAAQe,gBAAgBkB,KAAK,EAAEb,eAC/BG,OAAO+E,iBAAiB,IAAI/E,OAAO+E,iBAAiB,CAACnE,MAAM,GAAG,IAC1DnC,QAAQe,gBAAgBY,gBAAgB,EAAEJ,OAAO+E,iBAAiB,IAClEC,WACJnG,UACEsC,GACGsC,MAAM,CAAC;QAAClD,IAAIqE,0BAA0BrE,EAAE;IAAA,GACxCoD,IAAI,CAACiB,2BACLtE,KAAK,CACJnC,IACEG,GAAGsG,0BAA0B/C,WAAW,EAAElC,qBAAqBkC,WAAW,GAC1EvD,GAAGsG,0BAA0BnE,aAAa,EAAEd,qBAAqBc,aAAa,GAC9EnC,GACEsG,0BAA0BxE,gBAAgB,EAC1CT,qBAAqBS,gBAAgB,GAEvCrB,GACEP,GAAGoG,0BAA0BnC,SAAS,EAAE9C,qBAAqB8C,SAAS,GACtEtE,IACEG,GAAGsG,0BAA0BnC,SAAS,EAAE9C,qBAAqB8C,SAAS,GACtEjE,GACEoG,0BAA0BK,cAAc,EACxCtF,qBAAqBsF,cAAc,SASpDrB,OAAO,CAACpE,gBAAgBY,gBAAgB;AAC7C;AAEA,eAAe2B,iDACbZ,EAAM,EACNnB,MAAmC,EACnCc,MAAmC;IAEnC,IAAI,CAACd,OAAO6B,WAAW,EAAE,OAAO,EAAE;IAClC,MAAMqD,8BAA8B;WAC/B,IAAIC,IACLrE,OAAOsE,MAAM,CAAC,CAAC1D,QAAUA,MAAMhB,KAAK,KAAK,cAAcuB,GAAG,CAAC,CAACP,QAAUA,MAAMtB,gBAAgB;KAE/F;IACD,IAAI8E,4BAA4BtE,MAAM,KAAK,GAAG,OAAO,EAAE;IAEvD,MAAM4C,OAAO,MAAMc,iCAAiCnD,IAAI;QACtDU,aAAa7B,OAAO6B,WAAW;QAC/BpB,eAAeT,OAAOS,aAAa;QACnCsE,mBAAmBG;IACrB,GAAGhB,OAAO,CAAC9F,IAAIoB,gBAAgBY,gBAAgB;IAC/C,OAAOoD,KAAKK,OAAO,CAAC,CAACC,MACnBA,IAAI1D,gBAAgB,GAAG;YAAC;gBAAC,GAAG0D,GAAG;gBAAE1D,kBAAkB0D,IAAI1D,gBAAgB;YAAA;SAAE,GAAG,EAAE;AAElF;AAEA,OAAO,eAAeiF,yBACpBrF,MAAsC;IAEtC,MAAMsF,4BAA4B;WAAI,IAAIH,IAAInF,OAAOsF,yBAAyB;KAAE;IAEhF,OAAO,MAAMpG,KAAKgC,WAAW,CAAC,OAAOC;QACnC,MAAMA,GAAGS,OAAO,CACd5C,GAAG,CAAC,sCAAsC,EAAEgB,OAAO6B,WAAW,IAAI7B,OAAOS,aAAa,CAAC,EAAE,CAAC;QAG5F,IAAI8E,YAAsB,EAAE;QAC5B,IAAIvE,uBAAuB;QAC3B,IAAIsE,0BAA0B1E,MAAM,GAAG,GAAG;YACxC,MAAM4E,kBAAkB,MAAMrE,GAC3BsC,MAAM,CAAC;gBACNlD,IAAIf,gBAAgBe,EAAE;gBACtBH,kBAAkBZ,gBAAgBY,gBAAgB;YACpD,GACCuD,IAAI,CAACnE,iBACLc,KAAK,CACJnC,IACE6B,OAAO6B,WAAW,GACdvD,GAAGkB,gBAAgBqC,WAAW,EAAE7B,OAAO6B,WAAW,IAClDlD,OAAOa,gBAAgBqC,WAAW,GACtCvD,GAAGkB,gBAAgBiB,aAAa,EAAET,OAAOS,aAAa,GACtDhC,QAAQe,gBAAgBkB,KAAK,EAAEb,eAC/BjB,GACEY,gBAAgBgD,UAAU,EAC1BxD,GAAG,CAAC,SAAS,EAAEgB,OAAOyF,qBAAqB,CAAC,yBAAyB,CAAC,GAExE3G,WAAWU,gBAAgBY,gBAAgB,EAAEkF;YAInD,IAAIE,gBAAgB5E,MAAM,GAAG,GAAG;gBAC9B,MAAMX,UAAU,MAAMkB,GACnBjB,MAAM,CAACV,iBACPW,GAAG,CAAC;oBACHO,OAAO;oBACPmC,cAAc7D,GAAG,CAAC,SAAS,EAAEQ,gBAAgBqD,YAAY,CAAC,QAAQ,CAAC;oBACnExC,WAAWrB,GAAG,CAAC,KAAK,CAAC;gBACvB,GACCsB,KAAK,CACJnC,IACEM,QACEe,gBAAgBe,EAAE,EAClBiF,gBAAgBvD,GAAG,CAAC,CAAC6B,MAAQA,IAAIvD,EAAE,IAErC9B,QAAQe,gBAAgBkB,KAAK,EAAEb,eAC/BjB,GACEY,gBAAgBgD,UAAU,EAC1BxD,GAAG,CAAC,SAAS,EAAEgB,OAAOyF,qBAAqB,CAAC,yBAAyB,CAAC,IAI3E9E,SAAS,CAAC;oBAACP,kBAAkBZ,gBAAgBY,gBAAgB;gBAAA;gBAEhEmF,YAAYtF,QAAQ4D,OAAO,CAAC,CAACC,MAASA,IAAI1D,gBAAgB,GAAG;wBAAC0D,IAAI1D,gBAAgB;qBAAC,GAAG,EAAE;gBACxF,IAAIJ,OAAO6B,WAAW,EAAE;oBACtBb,uBAAuB,MAAM0E,+CAA+CvE,IAAI;wBAC9EU,aAAa7B,OAAO6B,WAAW;wBAC/BpB,eAAeT,OAAOS,aAAa;wBACnCsE,mBAAmBQ;oBACrB;gBACF;YACF;QACF;QAEA,MAAMI,eACJL,0BAA0B1E,MAAM,KAAK,IACjC,EAAE,GACF,AACE,CAAA,MAAMO,GACHsC,MAAM,GACNE,IAAI,CAACnE,iBACLc,KAAK,CACJnC,IACE6B,OAAO6B,WAAW,GACdvD,GAAGkB,gBAAgBqC,WAAW,EAAE7B,OAAO6B,WAAW,IAClDlD,OAAOa,gBAAgBqC,WAAW,GACtCvD,GAAGkB,gBAAgBiB,aAAa,EAAET,OAAOS,aAAa,GACtDhC,QAAQe,gBAAgBY,gBAAgB,EAAEkF,4BAE9C,EACFrD,GAAG,CAACxC;QAEZ,MAAMmG,qBAAqB5F,OAAO6B,WAAW,GACzC,MAAM1C,2CAA2CgC,IAAI;YACnDU,aAAa7B,OAAO6B,WAAW;YAC/BpB,eAAeT,OAAOS,aAAa;YACnCsE,mBAAmBO;QACrB,KACA,EAAE;QAEN,OAAO;YACLK;YACAE,sCAAsC,IAAIC,IACxCF,mBAAmB3D,GAAG,CAAC,CAAC8D,eAAiB;oBAACA,aAAa3F,gBAAgB;oBAAE2F;iBAAa;YAExFR;YACAvE;QACF;IACF;AACF;AAEA,OAAO,eAAegF,yBAAyBhG,MAG9C;IACC,MAAMiG,SAASC,0BAA0BlG,OAAOmG,gBAAgB;IAEhE,OAAO,MAAMjH,KAAKgC,WAAW,CAAC,OAAOC;QACnC,MAAMiF,gBAAgB,MAAMjF,GACzBsC,MAAM,CAAC;YACNlD,IAAIf,gBAAgBe,EAAE;YACtBsB,aAAarC,gBAAgBqC,WAAW;YACxCpB,eAAejB,gBAAgBiB,aAAa;YAC5CL,kBAAkBZ,gBAAgBY,gBAAgB;QACpD,GACCuD,IAAI,CAACnE,iBACLc,KAAK,CAAC+F,yBAAyBlF,IAAI8E,SACnC/B,OAAO,CAAC9F,IAAIoB,gBAAgBa,SAAS,GAAGjC,IAAIoB,gBAAgBe,EAAE,GAC9D4D,KAAK,CAACnE,OAAOmE,KAAK;QAErB,IAAIiC,cAAcxF,MAAM,KAAK,GAAG,OAAO;YAAC0F,QAAQ;YAAGtF,sBAAsB;QAAC;QAE1E,MAAMuF,eAAe;eAChB,IAAIpB,IAAIiB,cAAcvC,OAAO,CAAC,CAACC,MAASA,IAAIjC,WAAW,GAAG;oBAACiC,IAAIjC,WAAW;iBAAC,GAAG,EAAE;SACpF,CAAC2E,IAAI;QACN,KAAK,MAAM3E,eAAe0E,aAAc;YACtC,MAAMpF,GAAGS,OAAO,CAAC5C,GAAG,CAAC,sCAAsC,EAAE6C,YAAY,EAAE,CAAC;QAC9E;QAEA,MAAM4E,cAAc,MAAMtF,GACvBjB,MAAM,CAACV,iBACPW,GAAG,CAAC;YACHO,OAAO;YACP2B,QAAQ;YACRO,UAAU5D,GAAG,CAAC,SAAS,EAAEQ,gBAAgBoD,QAAQ,CAAC,QAAQ,CAAC;YAC3DvC,WAAWrB,GAAG,CAAC,KAAK,CAAC;QACvB,GACCsB,KAAK,CACJnC,IACEM,QACEe,gBAAgBe,EAAE,EAClB6F,cAAcnE,GAAG,CAAC,CAAC6B,MAAQA,IAAIvD,EAAE,IAEnC8F,yBAAyBlF,IAAI8E,UAGhCtF,SAAS,CAAC;YACTkB,aAAarC,gBAAgBqC,WAAW;YACxCpB,eAAejB,gBAAgBiB,aAAa;YAC5CL,kBAAkBZ,gBAAgBY,gBAAgB;QACpD;QAEF,IAAIY,uBAAuB;QAC3B,KAAK,MAAM0F,SAASC,uBAAuBF,aAAc;YACvDzF,wBAAwB,MAAM0E,+CAA+CvE,IAAI;gBAC/EU,aAAa6E,MAAM7E,WAAW;gBAC9BpB,eAAeiG,MAAMjG,aAAa;gBAClCsE,mBAAmB2B,MAAM3B,iBAAiB;gBAC1C6B,wBAAwB;YAC1B;QACF;QAEA,OAAO;YAACN,QAAQG,YAAY7F,MAAM;YAAEI;QAAoB;IAC1D;AACF;AAEA,eAAesC,0CACbnC,EAAM,EACNnB,MAAmC,EACnCc,MAAmC;IAEnC,MAAM+F,iBAAiB/F,OAAOsE,MAAM,CAAC,CAAC1D,QAAUC,gBAAgBD,MAAMhB,KAAK;IAC3E,IAAImG,eAAejG,MAAM,KAAK,GAAG,OAAO;IAExC,OAAO,MAAM8E,+CAA+CvE,IAAI;QAC9DU,aAAa7B,OAAO6B,WAAW;QAC/BpB,eAAeT,OAAOS,aAAa;QACnCsE,mBAAmB8B,eAAe5E,GAAG,CAAC,CAACP,QAAUA,MAAMtB,gBAAgB;IACzE;AACF;AAEA,eAAesF,+CACbvE,EAAM,EACNnB,MAKC;IAED,IAAIA,OAAO+E,iBAAiB,CAACnE,MAAM,KAAK,GAAG,OAAO;IAElD,MAAMkG,gCACJ9G,OAAO6B,WAAW,KAAK,OACnB7C,GAAG,CAAC,CAAC,GACLA,GAAG,CAAC,IAAI,EAAEV,GAAGiB,aAAasC,WAAW,EAAE7B,OAAO6B,WAAW,EAAE,CAAC;IAElE,MAAM2B,OAAO,MAAMrC,GAChBsC,MAAM,CAAC;QACNlD,IAAIf,gBAAgBe,EAAE;QACtBwG,sBAAsB/H,GAAkB,CAAC;gBAC/B,EAAEO,aAAagB,EAAE,CAAC;cACpB,EAAEhB,aAAa;eACd,EAAEA,aAAagB,EAAE,CAAC,GAAG,EAAEf,gBAAgBwH,qBAAqB,CAAC;eAC7D,EAAEzH,aAAakB,aAAa,CAAC,GAAG,EAAET,OAAOS,aAAa,CAAC;WAC3D,EAAEqG,8BAA8B;gBAC3B,EAAEvH,aAAagB,EAAE,CAAC;cACpB,EAAEhB,aAAa;eACd,EAAEA,aAAagB,EAAE,CAAC,GAAG,EAAEf,gBAAgB0C,aAAa,CAAC;eACrD,EAAE3C,aAAakB,aAAa,CAAC,GAAG,EAAET,OAAOS,aAAa,CAAC;WAC3D,EAAEqG,8BAA8B;OACpC,CAAC;QACFG,+BAA+BjI,GAAkB,CAAC;gBACxC,EAAEO,aAAasC,WAAW,CAAC;cAC7B,EAAEtC,aAAa;eACd,EAAEA,aAAagB,EAAE,CAAC,GAAG,EAAEf,gBAAgBwH,qBAAqB,CAAC;eAC7D,EAAEzH,aAAakB,aAAa,CAAC,GAAG,EAAET,OAAOS,aAAa,CAAC;WAC3D,EAAEqG,8BAA8B;gBAC3B,EAAEvH,aAAasC,WAAW,CAAC;cAC7B,EAAEtC,aAAa;eACd,EAAEA,aAAagB,EAAE,CAAC,GAAG,EAAEf,gBAAgB0C,aAAa,CAAC;eACrD,EAAE3C,aAAakB,aAAa,CAAC,GAAG,EAAET,OAAOS,aAAa,CAAC;WAC3D,EAAEqG,8BAA8B;OACpC,CAAC;IACJ,GACCnD,IAAI,CAACnE,iBACLc,KAAK,CACJnC,IACEG,GAAGkB,gBAAgBiB,aAAa,EAAET,OAAOS,aAAa,GACtDhC,QAAQe,gBAAgBY,gBAAgB,EAAEJ,OAAO+E,iBAAiB,GAClEtG,QAAQe,gBAAgBkB,KAAK,EAAEd,iBAC/Bb,GACEL,UAAUc,gBAAgB0C,aAAa,GACvCxD,UAAUc,gBAAgBwH,qBAAqB,IAEjDhH,OAAO6B,WAAW,KAAK,OACnBmD,YACAjG,GACEZ,IACEG,GAAGkB,gBAAgBqC,WAAW,EAAE7B,OAAO6B,WAAW,GAClD9C,GACER,OACE4C,GACGsC,MAAM,CAAC;QAAClD,IAAIhB,aAAagB,EAAE;IAAA,GAC3BoD,IAAI,CAACpE,cACLe,KAAK,CACJnC,IACEG,GAAGiB,aAAasC,WAAW,EAAE7B,OAAO6B,WAAW,GAC/CvD,GAAGiB,aAAakB,aAAa,EAAET,OAAOS,aAAa,GACnDnC,GAAGiB,aAAagB,EAAE,EAAEf,gBAAgB0C,aAAa,MAIzD3D,OACE4C,GACGsC,MAAM,CAAC;QAAClD,IAAIhB,aAAagB,EAAE;IAAA,GAC3BoD,IAAI,CAACpE,cACLe,KAAK,CACJnC,IACEG,GAAGiB,aAAasC,WAAW,EAAE7B,OAAO6B,WAAW,GAC/CvD,GAAGiB,aAAakB,aAAa,EAAET,OAAOS,aAAa,GACnDnC,GAAGiB,aAAagB,EAAE,EAAEf,gBAAgBwH,qBAAqB,QAMrE7I,IACEQ,OAAOa,gBAAgBqC,WAAW,GAClCnD,UAAUc,gBAAgBwH,qBAAqB,GAC/CzI,OACE4C,GACGsC,MAAM,CAAC;QAAClD,IAAIhB,aAAagB,EAAE;IAAA,GAC3BoD,IAAI,CAACpE,cACLe,KAAK,CACJnC,IACEG,GAAGiB,aAAasC,WAAW,EAAE7B,OAAO6B,WAAW,GAC/CvD,GAAGiB,aAAakB,aAAa,EAAET,OAAOS,aAAa,GACnDnC,GAAGiB,aAAagB,EAAE,EAAEf,gBAAgBwH,qBAAqB,QAMzEhH,OAAO4G,sBAAsB,KAAK,QAC9B5B,YACArG,OAAOa,gBAAgB8C,eAAe,GAC1C3D,OAAOa,gBAAgB0H,qBAAqB,IAG/CC,GAAG,CAAC;IAEP,IAAI3D,KAAK5C,MAAM,KAAK,GAAG,OAAO;IAE9B,MAAMX,UAAU,MAAMkB,GACnBjB,MAAM,CAACV,iBACPW,GAAG,CAAC;QACH6G,uBAAuB;QACvBE,uBAAuBlI,GAAG,CAAC,KAAK,CAAC;QACjCqB,WAAWrB,GAAG,CAAC,KAAK,CAAC;IACvB,GACCsB,KAAK,CACJnC,IACEM,QACEe,gBAAgBe,EAAE,EAClBiD,KAAKvB,GAAG,CAAC,CAAC6B,MAAQA,IAAIvD,EAAE,IAE1BP,OAAO4G,sBAAsB,KAAK,QAC9B5B,YACArG,OAAOa,gBAAgB8C,eAAe,GAC1C3D,OAAOa,gBAAgB0H,qBAAqB,IAG/CvG,SAAS,CAAC;QAACJ,IAAIf,gBAAgBe,EAAE;IAAA;IAEpC,MAAM6G,0BAA0B,IAAItB;IAIpC,MAAMuB,aAAa,IAAIlC,IAAIlF,QAAQgC,GAAG,CAAC,CAAC6B,MAAQA,IAAIvD,EAAE;IACtD,KAAK,MAAMuD,OAAON,KAAM;QACtB,IAAI,CAAC6D,WAAWC,GAAG,CAACxD,IAAIvD,EAAE,GAAG;QAC7B,IAAI,CAACuD,IAAIiD,oBAAoB,IAAI,CAACjD,IAAImD,6BAA6B,EAAE;QACrE,MAAMM,MAAM,GAAGzD,IAAImD,6BAA6B,CAAC,CAAC,EAAEnD,IAAIiD,oBAAoB,EAAE;QAC9E,MAAMS,UAAUJ,wBAAwBK,GAAG,CAACF,QAAQ;YAClD1F,aAAaiC,IAAImD,6BAA6B;YAC9C/E,eAAe4B,IAAIiD,oBAAoB;YACvCrD,OAAO;QACT;QACA8D,QAAQ9D,KAAK,IAAI;QACjB0D,wBAAwBjH,GAAG,CAACoH,KAAKC;IACnC;IAEA,IAAIJ,wBAAwBM,IAAI,KAAK,GAAG,OAAO;IAE/C,IAAIC,WAAW;IACf,KAAK,MAAMH,WAAWJ,wBAAwBpF,MAAM,GAAI;QACtD2F,YAAY,MAAMvI,wBAAwB+B,IAAI;YAC5CU,aAAa2F,QAAQ3F,WAAW;YAChCpB,eAAeT,OAAOS,aAAa;YACnCmH,UAAU;gBAAC;oBAAC1F,eAAesF,QAAQtF,aAAa;oBAAEwB,OAAO8D,QAAQ9D,KAAK;gBAAA;aAAE;QAC1E;IACF;IACA,OAAOiE;AACT;AAEA,SAASzB,0BAA0BC,gBAAwB;IACzD,OAAOnH,GAAG,CAAC,SAAS,EAAEmH,iBAAiB,yBAAyB,CAAC;AACnE;AAEA,SAASE,yBAAyBlF,EAAM,EAAE8E,MAAW;IACnD,OAAO9H,IACLM,QAAQe,gBAAgBkB,KAAK,EAAEb,eAC/BjB,GAAGY,gBAAgBgD,UAAU,EAAEyD,SAC/BrH,GAAGY,gBAAgBa,SAAS,EAAE4F,SAC9B1H,OACE4C,GACGsC,MAAM,CAAC;QAAClD,IAAIjB,kBAAkBiB,EAAE;IAAA,GAChCoD,IAAI,CAACrE,mBACLgB,KAAK,CACJnC,IACEG,GAAGgB,kBAAkBiB,EAAE,EAAEf,gBAAgBiB,aAAa,GACtD1B,GAAGJ,OAAOW,kBAAkBuI,UAAU,GAAGjJ,GAAGU,kBAAkBuI,UAAU,EAAE5B,aAIlFpH,UACEsC,GACGsC,MAAM,CAAC;QAAClD,IAAIZ,qBAAqBY,EAAE;IAAA,GACnCoD,IAAI,CAAChE,sBACLW,KAAK,CACJnC,IACEG,GAAGqB,qBAAqBkC,WAAW,EAAErC,gBAAgBqC,WAAW,GAChEvD,GAAGqB,qBAAqBc,aAAa,EAAEjB,gBAAgBiB,aAAa,GACpEnC,GAAGqB,qBAAqBS,gBAAgB,EAAEZ,gBAAgBY,gBAAgB,MAIlFvB,UACEsC,GACGsC,MAAM,CAAC;QAAClD,IAAIb,eAAea,EAAE;IAAA,GAC7BoD,IAAI,CAACjE,gBACLY,KAAK,CACJnC,IACEG,GAAGoB,eAAemC,WAAW,EAAErC,gBAAgBqC,WAAW,GAC1DvD,GAAGoB,eAAee,aAAa,EAAEjB,gBAAgBiB,aAAa,GAC9DnC,GAAGoB,eAAeU,gBAAgB,EAAEZ,gBAAgBY,gBAAgB,GACpEpB,GAAG,CAAC,EAAEU,eAAeW,SAAS,CAAC,IAAI,EAAE4F,OAAO,CAAC;AAKzD;AAEA,SAASU,uBACPnD,IAIE;IAEF,MAAMsE,SAAS,IAAIhC;IAInB,KAAK,MAAMhC,OAAON,KAAM;QACtB,IAAI,CAACM,IAAI1D,gBAAgB,EAAE;QAC3B,MAAMmH,MAAM,GAAGzD,IAAIjC,WAAW,IAAI,GAAG,CAAC,EAAEiC,IAAIrD,aAAa,EAAE;QAC3D,MAAMiG,QAAQoB,OAAOL,GAAG,CAACF,QAAQ;YAC/B1F,aAAaiC,IAAIjC,WAAW;YAC5BpB,eAAeqD,IAAIrD,aAAa;YAChCsE,mBAAmB,EAAE;QACvB;QACA2B,MAAM3B,iBAAiB,CAACgD,IAAI,CAACjE,IAAI1D,gBAAgB;QACjD0H,OAAO3H,GAAG,CAACoH,KAAKb;IAClB;IACA,OAAO;WAAIoB,OAAO9F,MAAM;KAAG;AAC7B;AAEA,eAAeF,0CACbX,EAAM,EACNnB,MAAmC,EACnCc,MAAiC;IAEjC,IAAI,CAACd,OAAO6B,WAAW,EAAE,OAAOf;IAChC,MAAMiE,oBAAoB;WAAI,IAAII,IAAIrE,OAAOmB,GAAG,CAAC,CAACP,QAAUA,MAAMtB,gBAAgB;KAAG;IACrF,IAAI2E,kBAAkBnE,MAAM,KAAK,GAAG,OAAOE;IAE3C,MAAMkH,YAAY,MAAM7G,GACrBsC,MAAM,CAAC;QACNrD,kBAAkBf,4BAA4Be,gBAAgB;QAC9D6H,mBAAmB5I,4BAA4B4I,iBAAiB;IAClE,GACCtE,IAAI,CAACtE,6BACLiB,KAAK,CACJnC,IACEG,GAAGe,4BAA4BwC,WAAW,EAAE7B,OAAO6B,WAAW,GAC9DvD,GAAGe,4BAA4BoB,aAAa,EAAET,OAAOS,aAAa,GAClEhC,QAAQY,4BAA4Be,gBAAgB,EAAE2E,oBACtDrG,UAAUW,4BAA4B4I,iBAAiB,IAG1D/D,OAAO,CACN7F,KAAKgB,4BAA4B6I,UAAU,GAC3C7J,KAAKgB,4BAA4B8I,SAAS;IAG9C,MAAMC,uCAAuC,IAAItC;IACjD,KAAK,MAAMhC,OAAOkE,UAAW;QAC3B,IAAI,CAAClE,IAAImE,iBAAiB,EAAE;QAC5B,IAAIG,qCAAqCd,GAAG,CAACxD,IAAI1D,gBAAgB,GAAG;QACpEgI,qCAAqCjI,GAAG,CAAC2D,IAAI1D,gBAAgB,EAAE0D,IAAImE,iBAAiB;IACtF;IAEA,IAAIG,qCAAqCV,IAAI,KAAK,GAAG,OAAO5G;IAE5D,OAAOA,OAAOmB,GAAG,CAAC,CAACP;QACjB,MAAMuG,oBAAoBG,qCAAqCX,GAAG,CAAC/F,MAAMtB,gBAAgB;QACzF,IAAI,CAAC6H,qBAAqBvG,MAAMY,eAAe,KAAK2F,mBAAmB,OAAOvG;QAC9E,OAAO;YAAC,GAAGA,KAAK;YAAEY,iBAAiB2F;QAAiB;IACtD;AACF;AAEA,SAAS1G,gBACPT,MAAmC,EACnCM,UAAgB;IAEhB,MAAMiH,qBAAqB,IAAIvC;IAC/B,KAAK,MAAMwC,YAAYxH,OAAQ;QAC7B,MAAMY,QAAQ6G,0BAA0BD,UAAUlH;QAClD,MAAMoH,WAAWH,mBAAmBZ,GAAG,CAAC/F,MAAMtB,gBAAgB;QAC9D,IAAIoI,UAAUC,gBAAgBD,UAAU9G;QACxC,IAAI,CAAC8G,YAAYE,kCAAkChH,OAAO8G,YAAY,GAAG;YACvEH,mBAAmBlI,GAAG,CACpBuB,MAAMtB,gBAAgB,EACtBoI,WAAWG,wBAAwBjH,OAAO8G,YAAY9G;QAE1D;IACF;IACA,OAAO;WAAI2G,mBAAmBrG,MAAM;KAAG;AACzC;AAEA,SAASuG,0BACP7G,KAAgC,EAChCN,UAAgB;IAEhB,MAAMoB,aAAad,MAAMc,UAAU,GAAGpB,aAAaA,aAAaM,MAAMc,UAAU;IAChF,OAAO;QACL,GAAGd,KAAK;QACRc;QACAC,WAAWf,MAAMhB,KAAK,KAAK,YAAY8B,aAAa;QACpDE,YAAYhB,MAAMhB,KAAK,KAAK,aAAa8B,aAAa;QACtDG,WAAWjB,MAAMhB,KAAK,KAAK,YAAY8B,aAAa;QACpDI,UAAUlB,MAAMhB,KAAK,KAAK,WAAW8B,aAAa;QAClDK,cAAcnB,MAAMhB,KAAK,KAAK,eAAe8B,aAAa;IAC5D;AACF;AAEA,SAASiG,gBAAgBzF,MAA+B,EAAE4F,MAA+B;IACvF5F,OAAOP,SAAS,GAAGoG,aAAa7F,OAAOP,SAAS,EAAEmG,OAAOnG,SAAS;IAClEO,OAAON,UAAU,GAAGmG,aAAa7F,OAAON,UAAU,EAAEkG,OAAOlG,UAAU;IACrEM,OAAOL,SAAS,GAAGkG,aAAa7F,OAAOL,SAAS,EAAEiG,OAAOjG,SAAS;IAClEK,OAAOJ,QAAQ,GAAGiG,aAAa7F,OAAOJ,QAAQ,EAAEgG,OAAOhG,QAAQ;IAC/DI,OAAOH,YAAY,GAAGgG,aAAa7F,OAAOH,YAAY,EAAE+F,OAAO/F,YAAY;AAC7E;AAEA,SAAS8F,wBACPjH,KAA8B,EAC9B8G,QAAiC;IAEjC,OAAO;QACL,GAAG9G,KAAK;QACRQ,eAAeR,MAAMQ,aAAa,IAAIsG,SAAStG,aAAa;QAC5DC,aAAaT,MAAMS,WAAW,IAAIqG,SAASrG,WAAW;QACtDG,iBAAiBZ,MAAMY,eAAe,IAAIkG,SAASlG,eAAe;QAClEC,cAAcb,MAAMa,YAAY,IAAIiG,SAASjG,YAAY;QACzD,GAAGuG,eAAeN,SAAS;IAC7B;AACF;AAEA,SAASM,eAAepH,KAA8B;IACpD,OAAO;QACLe,WAAWf,MAAMe,SAAS;QAC1BC,YAAYhB,MAAMgB,UAAU;QAC5BC,WAAWjB,MAAMiB,SAAS;QAC1BC,UAAUlB,MAAMkB,QAAQ;QACxBC,cAAcnB,MAAMmB,YAAY;IAClC;AACF;AAEA,SAASgG,aAAaE,CAAc,EAAEC,CAAc;IAClD,IAAI,CAACD,GAAG,OAAOC;IACf,IAAI,CAACA,GAAG,OAAOD;IACf,OAAOA,IAAIC,IAAID,IAAIC;AACrB;AAEA,SAASN,kCACPK,CAA4B,EAC5BC,CAA4B;IAE5B,MAAMC,YAAYF,EAAEvG,UAAU,CAAC0G,OAAO,KAAKF,EAAExG,UAAU,CAAC0G,OAAO;IAC/D,MAAMC,YAAYC,2BAA2BL,EAAErI,KAAK,IAAI0I,2BAA2BJ,EAAEtI,KAAK;IAC1F,IAAIyI,cAAc,GAAG,OAAOA;IAC5B,OAAOF;AACT;AAEA,SAASG,2BAA2B1I,KAA0B;IAC5D,OAAQA;QACN,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;QACT,KAAK;YACH,OAAO;IACX;AACF;AAEA,SAAS2I,wBAAwB3I,KAAyC;IACxE,OAAO1B,GAAW,CAAC;SACZ,EAAE0B,MAAM;;;;;;;;;EASf,CAAC;AACH;AAEA,SAASwC;IACP,OAAOlE,GAAY,CAAC;IAClB,EAAEqK,wBAAwBrK,GAAG,CAAC,cAAc,CAAC,EAAE,GAAG,EAAEqK,wBAAwB7J,gBAAgBkB,KAAK,EAAE;;MAEjG,EAAE2I,wBAAwBrK,GAAG,CAAC,cAAc,CAAC,EAAE,GAAG,EAAEqK,wBAAwB7J,gBAAgBkB,KAAK,EAAE;kCACvE,EAAElB,gBAAgBgD,UAAU,CAAC;;EAE7D,CAAC;AACH;AAEA,SAASa;IACP,OAAOrE,GAAY,CAAC;IAClB,EAAEsK,qBAAqB9J,gBAAgBiD,SAAS,EAAEzD,GAAG,CAAC,mBAAmB,CAAC,EAAE;OACzE,EAAEsK,qBAAqB9J,gBAAgBkD,UAAU,EAAE1D,GAAG,CAAC,oBAAoB,CAAC,EAAE;OAC9E,EAAEsK,qBAAqB9J,gBAAgBmD,SAAS,EAAE3D,GAAG,CAAC,mBAAmB,CAAC,EAAE;OAC5E,EAAEsK,qBAAqB9J,gBAAgBoD,QAAQ,EAAE5D,GAAG,CAAC,kBAAkB,CAAC,EAAE;OAC1E,EAAEsK,qBAAqB9J,gBAAgBqD,YAAY,EAAE7D,GAAG,CAAC,sBAAsB,CAAC,EAAE;EACvF,CAAC;AACH;AAEA,SAASsK,qBACPC,OAA4C,EAC5CC,QAAa;IAEb,OAAOxK,GAAY,CAAC,EAAEwK,SAAS,kBAAkB,EAAED,QAAQ,YAAY,EAAEC,SAAS,GAAG,EAAED,QAAQ,CAAC,CAAC;AACnG;AAEA,SAASpG,gBAAgBoG,OAA4C,EAAEC,QAAa;IAClF,OAAOxK,GAAG,CAAC;;WAEF,EAAEwK,SAAS,cAAc,EAAED,QAAQ;WACnC,EAAEA,QAAQ,cAAc,EAAEC,SAAS;iBAC7B,EAAED,QAAQ,EAAE,EAAEC,SAAS;;EAEtC,CAAC;AACH;AAEA,OAAO,SAAS7H,gBAAgBjB,KAA0B;IACxD,OAAOd,eAAe6J,QAAQ,CAAC/I;AACjC;AAEA,SAASqD,uBACPrD,KAA0B;IAE1B,OAAOZ,sBAAsB2J,QAAQ,CAAC/I;AACxC"}
|
|
1
|
+
{"version":3,"sources":["../../src/db/runner-instances.ts"],"sourcesContent":["import {logger} from '@shipfox/node-opentelemetry';\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 {sanitizeRunnerLabels} from '#core/runner-labels.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 {reservations} from './schema/reservations.js';\nimport {runnerControlSessions} from './schema/runner-control-sessions.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 scope: 'installation' | 'workspace';\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: sanitizeRunnerLabels(event.labels, {\n scope: params.scope,\n logLevel: 'debug',\n source: 'runner instance report',\n }),\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(${providerRunners.reservationId}, excluded.reservation_id) 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 countStaleEnrolledRunnerInstances(params: {\n graceSeconds: number;\n}): Promise<number> {\n const [row] = await db()\n .select({count: sql<number>`count(*)::int`})\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.state, 'running'),\n isNull(providerRunners.workspaceId),\n isNull(providerRunners.runnerSessionId),\n lt(providerRunners.reportedAt, staleRunnerInstanceCutoff(params.graceSeconds)),\n exists(\n db()\n .select({id: runnerControlSessions.id})\n .from(runnerControlSessions)\n .where(\n and(\n eq(runnerControlSessions.runnerInstanceId, providerRunners.id),\n isNull(runnerControlSessions.closedAt),\n gt(runnerControlSessions.expiresAt, sql`now()`),\n ),\n ),\n ),\n ),\n );\n\n return row?.count ?? 0;\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) 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 | null;\n provisionerId: string;\n providerRunnerIds: string[];\n requireUnlinkedSession?: boolean;\n },\n): Promise<number> {\n if (params.providerRunnerIds.length === 0) return 0;\n\n const reservationWorkspacePredicate =\n params.workspaceId === null\n ? sql``\n : sql`and ${eq(reservations.workspaceId, params.workspaceId)}`;\n\n const rows = await tx\n .select({\n id: providerRunners.id,\n releaseReservationId: sql<string | null>`coalesce(\n (select ${reservations.id}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.intendedReservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate}),\n (select ${reservations.id}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.reservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate})\n )`,\n releaseReservationWorkspaceId: sql<string | null>`coalesce(\n (select ${reservations.workspaceId}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.intendedReservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate}),\n (select ${reservations.workspaceId}\n from ${reservations}\n where ${reservations.id} = ${providerRunners.reservationId}\n and ${reservations.provisionerId} = ${params.provisionerId}\n ${reservationWorkspacePredicate})\n )`,\n })\n .from(providerRunners)\n .where(\n and(\n eq(providerRunners.provisionerId, params.provisionerId),\n inArray(providerRunners.providerRunnerId, params.providerRunnerIds),\n inArray(providerRunners.state, terminalStates),\n or(\n isNotNull(providerRunners.reservationId),\n isNotNull(providerRunners.intendedReservationId),\n ),\n params.workspaceId === null\n ? undefined\n : or(\n and(\n eq(providerRunners.workspaceId, params.workspaceId),\n or(\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.reservationId),\n ),\n ),\n ),\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.intendedReservationId),\n ),\n ),\n ),\n ),\n ),\n and(\n isNull(providerRunners.workspaceId),\n isNotNull(providerRunners.intendedReservationId),\n exists(\n tx\n .select({id: reservations.id})\n .from(reservations)\n .where(\n and(\n eq(reservations.workspaceId, params.workspaceId),\n eq(reservations.provisionerId, params.provisionerId),\n eq(reservations.id, providerRunners.intendedReservationId),\n ),\n ),\n ),\n ),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .for('update');\n\n if (rows.length === 0) return 0;\n\n const updated = await tx\n .update(providerRunners)\n .set({\n intendedReservationId: null,\n reservationReleasedAt: sql`now()`,\n updatedAt: sql`now()`,\n })\n .where(\n and(\n inArray(\n providerRunners.id,\n rows.map((row) => row.id),\n ),\n params.requireUnlinkedSession === false\n ? undefined\n : isNull(providerRunners.runnerSessionId),\n isNull(providerRunners.reservationReleasedAt),\n ),\n )\n .returning({id: providerRunners.id});\n\n const releasesByReservationId = new Map<\n string,\n {workspaceId: string; reservationId: string; count: number}\n >();\n const updatedIds = new Set(updated.map((row) => row.id));\n for (const row of rows) {\n if (!updatedIds.has(row.id)) continue;\n if (!row.releaseReservationId || !row.releaseReservationWorkspaceId) continue;\n const key = `${row.releaseReservationWorkspaceId}:${row.releaseReservationId}`;\n const release = releasesByReservationId.get(key) ?? {\n workspaceId: row.releaseReservationWorkspaceId,\n reservationId: row.releaseReservationId,\n count: 0,\n };\n release.count += 1;\n releasesByReservationId.set(key, release);\n }\n\n if (releasesByReservationId.size === 0) return 0;\n\n let released = 0;\n for (const release of releasesByReservationId.values()) {\n released += await releaseReservationUnits(tx, {\n workspaceId: release.workspaceId,\n provisionerId: params.provisionerId,\n releases: [{reservationId: release.reservationId, count: release.count}],\n });\n }\n return released;\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 | null; provisionerId: string; providerRunnerIds: string[]}> {\n const groups = new Map<\n string,\n {workspaceId: string | null; provisionerId: string; providerRunnerIds: string[]}\n >();\n for (const row of rows) {\n if (!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","and","asc","desc","eq","exists","gt","inArray","isNotNull","isNull","lt","notExists","notInArray","or","sql","alias","sanitizeRunnerLabels","db","listRunningJobExecutionsByRunnerInstanceTx","releaseReservationUnits","ephemeralRegistrationTokens","provisionerTokens","reservations","runnerControlSessions","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","scope","logLevel","source","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","countStaleEnrolledRunnerInstances","staleRunnerInstanceCutoff","graceSeconds","closedAt","expiresAt","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","thresholdSeconds","candidateRows","staleRunnerInstanceWhere","reaped","workspaceIds","sort","updatedRows","group","groupRunnerInstanceIds","requireUnlinkedSession","terminalEvents","reservationWorkspacePredicate","releaseReservationId","intendedReservationId","releaseReservationWorkspaceId","reservationReleasedAt","for","releasesByReservationId","updatedIds","has","key","release","get","size","released","releases","lastSeenAt","groups","push","tokenRows","consumedSessionId","consumedAt","createdAt","consumedSessionIdsByRunnerInstanceId","byRunnerInstanceId","rawEvent","toRunnerInstanceReportRow","existing","mergeMilestones","compareRunnerInstanceReportEvents","mergeProjectionMetadata","earliestDate","pickMilestones","a","b","timeDelta","getTime","rankDelta","getRunnerInstanceStateRank","providerRunnerStateRank","milestoneNeedsUpdate","current","incoming","includes"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-sessions.d.ts","sourceRoot":"","sources":["../../src/db/runner-sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"runner-sessions.d.ts","sourceRoot":"","sources":["../../src/db/runner-sessions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,0BAA0B,CAAC;AAExE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,kCAAkC,CAAC;AAWpE,MAAM,WAAW,yBAAyB;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gBAAgB,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;CACrD;AAED,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAAC,aAAa,CAAC,CAmBxB;AAED,wBAAsB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CASjG;AAED,wBAAsB,2CAA2C,CAAC,MAAM,EAAE;IACxE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,gBAAgB,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;CACrD,0BAwFA;AAED,MAAM,WAAW,iCAAiC;IAChD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,iCAAiC,GACxC,OAAO,CAAC,MAAM,CAAC,CAuCjB"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { and, asc, eq, gt, inArray, isNull, lt, notExists, or, sql } from 'drizzle-orm';
|
|
2
|
+
import { EmptyRunnerLabelsError } from '#core/errors.js';
|
|
3
|
+
import { sanitizeRunnerLabelsOrThrow } from '#core/runner-labels.js';
|
|
2
4
|
import { db } from './db.js';
|
|
5
|
+
import { provisionerTokens } from './schema/provisioner-tokens.js';
|
|
3
6
|
import { runnerActivationTokens } from './schema/runner-activation-tokens.js';
|
|
4
7
|
import { runnerControlSessions } from './schema/runner-control-sessions.js';
|
|
5
8
|
import { providerRunners } from './schema/runner-instances.js';
|
|
@@ -28,23 +31,38 @@ export async function getRunnerSessionById(runnerSessionId) {
|
|
|
28
31
|
}
|
|
29
32
|
export async function createRunnerSessionConsumingActivationToken(params) {
|
|
30
33
|
return await db().transaction(async (tx)=>{
|
|
31
|
-
const [
|
|
32
|
-
|
|
33
|
-
runnerInstanceId:
|
|
34
|
+
const [runner] = await tx.select({
|
|
35
|
+
activationTokenId: runnerActivationTokens.id,
|
|
36
|
+
runnerInstanceId: providerRunners.id,
|
|
34
37
|
workspaceId: providerRunners.workspaceId,
|
|
35
38
|
provisionerId: providerRunners.provisionerId,
|
|
36
|
-
providerRunnerId: providerRunners.providerRunnerId
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
providerRunnerId: providerRunners.providerRunnerId,
|
|
40
|
+
runnerSessionId: providerRunners.runnerSessionId
|
|
41
|
+
}).from(runnerActivationTokens).innerJoin(providerRunners, eq(providerRunners.id, runnerActivationTokens.runnerInstanceId)).where(eq(runnerActivationTokens.id, params.activationTokenId)).limit(1).for('update', {
|
|
42
|
+
of: providerRunners
|
|
43
|
+
});
|
|
44
|
+
if (!runner?.workspaceId || !runner.providerRunnerId || runner.runnerSessionId) throw new Error('Runner activation token is invalid, expired, or has already been used');
|
|
45
|
+
const [activationToken] = await tx.select({
|
|
46
|
+
id: runnerActivationTokens.id
|
|
47
|
+
}).from(runnerActivationTokens).where(and(eq(runnerActivationTokens.id, runner.activationTokenId), eq(runnerActivationTokens.runnerInstanceId, runner.runnerInstanceId), isNull(runnerActivationTokens.consumedAt), isNull(runnerActivationTokens.revokedAt), gt(runnerActivationTokens.expiresAt, sql`now()`))).limit(1).for('update');
|
|
48
|
+
if (!activationToken) throw new Error('Runner activation token is invalid, expired, or has already been used');
|
|
49
|
+
const [provisioner] = await tx.select({
|
|
50
|
+
scope: provisionerTokens.scope
|
|
51
|
+
}).from(provisionerTokens).where(eq(provisionerTokens.id, runner.provisionerId)).limit(1);
|
|
52
|
+
const labels = sanitizeRunnerLabelsOrThrow(params.labels, {
|
|
53
|
+
scope: provisioner?.scope ?? 'workspace',
|
|
54
|
+
source: 'activation runner registration'
|
|
55
|
+
});
|
|
56
|
+
if (labels.length === 0) throw new EmptyRunnerLabelsError();
|
|
39
57
|
const [session] = await tx.insert(runnerSessions).values({
|
|
40
|
-
workspaceId:
|
|
58
|
+
workspaceId: runner.workspaceId,
|
|
41
59
|
scope: 'workspace',
|
|
42
|
-
registrationTokenId:
|
|
60
|
+
registrationTokenId: activationToken.id,
|
|
43
61
|
registrationTokenKind: 'activation',
|
|
44
|
-
runnerInstanceId:
|
|
45
|
-
provisionerId:
|
|
46
|
-
providerRunnerId:
|
|
47
|
-
labels
|
|
62
|
+
runnerInstanceId: runner.runnerInstanceId,
|
|
63
|
+
provisionerId: runner.provisionerId,
|
|
64
|
+
providerRunnerId: runner.providerRunnerId,
|
|
65
|
+
labels,
|
|
48
66
|
toolCapabilities: params.toolCapabilities ?? null,
|
|
49
67
|
toolCapabilitiesReportedAt: params.toolCapabilities ? sql`now()` : null,
|
|
50
68
|
maxClaims: 1,
|
|
@@ -54,15 +72,15 @@ export async function createRunnerSessionConsumingActivationToken(params) {
|
|
|
54
72
|
await tx.update(runnerActivationTokens).set({
|
|
55
73
|
consumedAt: sql`now()`,
|
|
56
74
|
consumedSessionId: session.id
|
|
57
|
-
}).where(eq(runnerActivationTokens.id,
|
|
75
|
+
}).where(eq(runnerActivationTokens.id, activationToken.id));
|
|
58
76
|
await tx.update(providerRunners).set({
|
|
59
77
|
runnerSessionId: session.id,
|
|
60
78
|
updatedAt: sql`now()`
|
|
61
|
-
}).where(and(eq(providerRunners.id,
|
|
79
|
+
}).where(and(eq(providerRunners.id, runner.runnerInstanceId), isNull(providerRunners.runnerSessionId)));
|
|
62
80
|
await tx.update(runnerControlSessions).set({
|
|
63
81
|
closedAt: sql`now()`,
|
|
64
82
|
closeReason: 'activated'
|
|
65
|
-
}).where(and(eq(runnerControlSessions.runnerInstanceId,
|
|
83
|
+
}).where(and(eq(runnerControlSessions.runnerInstanceId, runner.runnerInstanceId), isNull(runnerControlSessions.closedAt)));
|
|
66
84
|
return toRunnerSession(session);
|
|
67
85
|
});
|
|
68
86
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/db/runner-sessions.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {and, asc, eq, gt, inArray, isNull, lt, notExists, or, sql} from 'drizzle-orm';\nimport type {RunnerSession} from '#core/entities/runner-session.js';\nimport {db} from './db.js';\nimport {runnerActivationTokens} from './schema/runner-activation-tokens.js';\nimport {runnerControlSessions} from './schema/runner-control-sessions.js';\nimport {providerRunners} from './schema/runner-instances.js';\nimport {runnerSessions, toRunnerSession} from './schema/runner-sessions.js';\nimport {runningJobExecutions} from './schema/running-job-executions.js';\n\nexport interface CreateRunnerSessionParams {\n workspaceId: string;\n scope: 'workspace';\n registrationTokenId: string;\n labels: string[];\n toolCapabilities?: RunnerToolCapabilitiesDto | null;\n}\n\nexport async function createRunnerSession(\n params: CreateRunnerSessionParams,\n): Promise<RunnerSession> {\n const rows = await db()\n .insert(runnerSessions)\n .values({\n workspaceId: params.workspaceId,\n scope: params.scope,\n registrationTokenId: params.registrationTokenId,\n registrationTokenKind: 'manual',\n labels: params.labels,\n toolCapabilities: params.toolCapabilities ?? null,\n toolCapabilitiesReportedAt: params.toolCapabilities ? sql`now()` : null,\n maxClaims: null,\n claimsUsed: 0,\n })\n .returning();\n\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n return toRunnerSession(row);\n}\n\nexport async function getRunnerSessionById(runnerSessionId: string): Promise<RunnerSession | null> {\n const rows = await db()\n .select()\n .from(runnerSessions)\n .where(eq(runnerSessions.id, runnerSessionId))\n .limit(1);\n\n const row = rows[0];\n return row ? toRunnerSession(row) : null;\n}\n\nexport async function createRunnerSessionConsumingActivationToken(params: {\n activationTokenId: string;\n labels: string[];\n toolCapabilities?: RunnerToolCapabilitiesDto | null;\n}) {\n return await db().transaction(async (tx) => {\n const [token] = await tx\n .select({\n id: runnerActivationTokens.id,\n runnerInstanceId: runnerActivationTokens.runnerInstanceId,\n workspaceId: providerRunners.workspaceId,\n provisionerId: providerRunners.provisionerId,\n providerRunnerId: providerRunners.providerRunnerId,\n })\n .from(runnerActivationTokens)\n .innerJoin(providerRunners, eq(providerRunners.id, runnerActivationTokens.runnerInstanceId))\n .where(\n and(\n eq(runnerActivationTokens.id, params.activationTokenId),\n isNull(runnerActivationTokens.consumedAt),\n isNull(runnerActivationTokens.revokedAt),\n gt(runnerActivationTokens.expiresAt, sql`now()`),\n isNull(providerRunners.runnerSessionId),\n ),\n )\n .limit(1)\n .for('update');\n if (!token?.workspaceId || !token.providerRunnerId)\n throw new Error('Runner activation token is invalid, expired, or has already been used');\n const [session] = await tx\n .insert(runnerSessions)\n .values({\n workspaceId: token.workspaceId,\n scope: 'workspace',\n registrationTokenId: token.id,\n registrationTokenKind: 'activation',\n runnerInstanceId: token.runnerInstanceId,\n provisionerId: token.provisionerId,\n providerRunnerId: token.providerRunnerId,\n labels: params.labels,\n toolCapabilities: params.toolCapabilities ?? null,\n toolCapabilitiesReportedAt: params.toolCapabilities ? sql`now()` : null,\n maxClaims: 1,\n claimsUsed: 0,\n })\n .returning();\n if (!session) throw new Error('Runner activation session insert returned no row');\n await tx\n .update(runnerActivationTokens)\n .set({consumedAt: sql`now()`, consumedSessionId: session.id})\n .where(eq(runnerActivationTokens.id, token.id));\n await tx\n .update(providerRunners)\n .set({runnerSessionId: session.id, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, token.runnerInstanceId),\n isNull(providerRunners.runnerSessionId),\n ),\n );\n await tx\n .update(runnerControlSessions)\n .set({closedAt: sql`now()`, closeReason: 'activated'})\n .where(\n and(\n eq(runnerControlSessions.runnerInstanceId, token.runnerInstanceId),\n isNull(runnerControlSessions.closedAt),\n ),\n );\n return toRunnerSession(session);\n });\n}\n\nexport interface DeleteExpiredRunnerSessionsParams {\n manualRetentionDays: number;\n ephemeralRetentionDays: number;\n limit?: number;\n}\n\nexport async function deleteExpiredRunnerSessions(\n params: DeleteExpiredRunnerSessionsParams,\n): Promise<number> {\n const expiredIds = db()\n .select({id: runnerSessions.id})\n .from(runnerSessions)\n .where(\n and(\n or(\n and(\n eq(runnerSessions.registrationTokenKind, 'manual'),\n lt(\n runnerSessions.createdAt,\n sql`now() - (${params.manualRetentionDays} || ' days')::interval`,\n ),\n ),\n and(\n inArray(runnerSessions.registrationTokenKind, ['ephemeral', 'activation']),\n lt(\n runnerSessions.createdAt,\n sql`now() - (${params.ephemeralRetentionDays} || ' days')::interval`,\n ),\n ),\n ),\n notExists(\n db()\n .select({id: runningJobExecutions.id})\n .from(runningJobExecutions)\n .where(eq(runningJobExecutions.runnerSessionId, runnerSessions.id)),\n ),\n ),\n )\n .orderBy(asc(runnerSessions.createdAt), asc(runnerSessions.id))\n .limit(params.limit ?? 1000);\n\n const deleted = await db()\n .delete(runnerSessions)\n .where(inArray(runnerSessions.id, expiredIds))\n .returning({id: runnerSessions.id});\n\n return deleted.length;\n}\n"],"names":["and","asc","eq","gt","inArray","isNull","lt","notExists","or","sql","db","runnerActivationTokens","runnerControlSessions","providerRunners","runnerSessions","toRunnerSession","runningJobExecutions","createRunnerSession","params","rows","insert","values","workspaceId","scope","registrationTokenId","registrationTokenKind","labels","toolCapabilities","toolCapabilitiesReportedAt","maxClaims","claimsUsed","returning","row","Error","getRunnerSessionById","runnerSessionId","select","from","where","id","limit","createRunnerSessionConsumingActivationToken","transaction","tx","token","runnerInstanceId","provisionerId","providerRunnerId","innerJoin","activationTokenId","consumedAt","revokedAt","expiresAt","for","session","update","set","consumedSessionId","updatedAt","closedAt","closeReason","deleteExpiredRunnerSessions","expiredIds","createdAt","manualRetentionDays","ephemeralRetentionDays","orderBy","deleted","delete","length"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/db/runner-sessions.ts"],"sourcesContent":["import type {RunnerToolCapabilitiesDto} from '@shipfox/api-runners-dto';\nimport {and, asc, eq, gt, inArray, isNull, lt, notExists, or, sql} from 'drizzle-orm';\nimport type {RunnerSession} from '#core/entities/runner-session.js';\nimport {EmptyRunnerLabelsError} from '#core/errors.js';\nimport {sanitizeRunnerLabelsOrThrow} from '#core/runner-labels.js';\nimport {db} from './db.js';\nimport {provisionerTokens} from './schema/provisioner-tokens.js';\nimport {runnerActivationTokens} from './schema/runner-activation-tokens.js';\nimport {runnerControlSessions} from './schema/runner-control-sessions.js';\nimport {providerRunners} from './schema/runner-instances.js';\nimport {runnerSessions, toRunnerSession} from './schema/runner-sessions.js';\nimport {runningJobExecutions} from './schema/running-job-executions.js';\n\nexport interface CreateRunnerSessionParams {\n workspaceId: string;\n scope: 'workspace';\n registrationTokenId: string;\n labels: string[];\n toolCapabilities?: RunnerToolCapabilitiesDto | null;\n}\n\nexport async function createRunnerSession(\n params: CreateRunnerSessionParams,\n): Promise<RunnerSession> {\n const rows = await db()\n .insert(runnerSessions)\n .values({\n workspaceId: params.workspaceId,\n scope: params.scope,\n registrationTokenId: params.registrationTokenId,\n registrationTokenKind: 'manual',\n labels: params.labels,\n toolCapabilities: params.toolCapabilities ?? null,\n toolCapabilitiesReportedAt: params.toolCapabilities ? sql`now()` : null,\n maxClaims: null,\n claimsUsed: 0,\n })\n .returning();\n\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n return toRunnerSession(row);\n}\n\nexport async function getRunnerSessionById(runnerSessionId: string): Promise<RunnerSession | null> {\n const rows = await db()\n .select()\n .from(runnerSessions)\n .where(eq(runnerSessions.id, runnerSessionId))\n .limit(1);\n\n const row = rows[0];\n return row ? toRunnerSession(row) : null;\n}\n\nexport async function createRunnerSessionConsumingActivationToken(params: {\n activationTokenId: string;\n labels: string[];\n toolCapabilities?: RunnerToolCapabilitiesDto | null;\n}) {\n return await db().transaction(async (tx) => {\n const [runner] = await tx\n .select({\n activationTokenId: runnerActivationTokens.id,\n runnerInstanceId: providerRunners.id,\n workspaceId: providerRunners.workspaceId,\n provisionerId: providerRunners.provisionerId,\n providerRunnerId: providerRunners.providerRunnerId,\n runnerSessionId: providerRunners.runnerSessionId,\n })\n .from(runnerActivationTokens)\n .innerJoin(providerRunners, eq(providerRunners.id, runnerActivationTokens.runnerInstanceId))\n .where(eq(runnerActivationTokens.id, params.activationTokenId))\n .limit(1)\n .for('update', {of: providerRunners});\n if (!runner?.workspaceId || !runner.providerRunnerId || runner.runnerSessionId)\n throw new Error('Runner activation token is invalid, expired, or has already been used');\n\n const [activationToken] = await tx\n .select({id: runnerActivationTokens.id})\n .from(runnerActivationTokens)\n .where(\n and(\n eq(runnerActivationTokens.id, runner.activationTokenId),\n eq(runnerActivationTokens.runnerInstanceId, runner.runnerInstanceId),\n isNull(runnerActivationTokens.consumedAt),\n isNull(runnerActivationTokens.revokedAt),\n gt(runnerActivationTokens.expiresAt, sql`now()`),\n ),\n )\n .limit(1)\n .for('update');\n if (!activationToken)\n throw new Error('Runner activation token is invalid, expired, or has already been used');\n\n const [provisioner] = await tx\n .select({scope: provisionerTokens.scope})\n .from(provisionerTokens)\n .where(eq(provisionerTokens.id, runner.provisionerId))\n .limit(1);\n const labels = sanitizeRunnerLabelsOrThrow(params.labels, {\n scope: provisioner?.scope ?? 'workspace',\n source: 'activation runner registration',\n });\n if (labels.length === 0) throw new EmptyRunnerLabelsError();\n const [session] = await tx\n .insert(runnerSessions)\n .values({\n workspaceId: runner.workspaceId,\n scope: 'workspace',\n registrationTokenId: activationToken.id,\n registrationTokenKind: 'activation',\n runnerInstanceId: runner.runnerInstanceId,\n provisionerId: runner.provisionerId,\n providerRunnerId: runner.providerRunnerId,\n labels,\n toolCapabilities: params.toolCapabilities ?? null,\n toolCapabilitiesReportedAt: params.toolCapabilities ? sql`now()` : null,\n maxClaims: 1,\n claimsUsed: 0,\n })\n .returning();\n if (!session) throw new Error('Runner activation session insert returned no row');\n await tx\n .update(runnerActivationTokens)\n .set({consumedAt: sql`now()`, consumedSessionId: session.id})\n .where(eq(runnerActivationTokens.id, activationToken.id));\n await tx\n .update(providerRunners)\n .set({runnerSessionId: session.id, updatedAt: sql`now()`})\n .where(\n and(\n eq(providerRunners.id, runner.runnerInstanceId),\n isNull(providerRunners.runnerSessionId),\n ),\n );\n await tx\n .update(runnerControlSessions)\n .set({closedAt: sql`now()`, closeReason: 'activated'})\n .where(\n and(\n eq(runnerControlSessions.runnerInstanceId, runner.runnerInstanceId),\n isNull(runnerControlSessions.closedAt),\n ),\n );\n return toRunnerSession(session);\n });\n}\n\nexport interface DeleteExpiredRunnerSessionsParams {\n manualRetentionDays: number;\n ephemeralRetentionDays: number;\n limit?: number;\n}\n\nexport async function deleteExpiredRunnerSessions(\n params: DeleteExpiredRunnerSessionsParams,\n): Promise<number> {\n const expiredIds = db()\n .select({id: runnerSessions.id})\n .from(runnerSessions)\n .where(\n and(\n or(\n and(\n eq(runnerSessions.registrationTokenKind, 'manual'),\n lt(\n runnerSessions.createdAt,\n sql`now() - (${params.manualRetentionDays} || ' days')::interval`,\n ),\n ),\n and(\n inArray(runnerSessions.registrationTokenKind, ['ephemeral', 'activation']),\n lt(\n runnerSessions.createdAt,\n sql`now() - (${params.ephemeralRetentionDays} || ' days')::interval`,\n ),\n ),\n ),\n notExists(\n db()\n .select({id: runningJobExecutions.id})\n .from(runningJobExecutions)\n .where(eq(runningJobExecutions.runnerSessionId, runnerSessions.id)),\n ),\n ),\n )\n .orderBy(asc(runnerSessions.createdAt), asc(runnerSessions.id))\n .limit(params.limit ?? 1000);\n\n const deleted = await db()\n .delete(runnerSessions)\n .where(inArray(runnerSessions.id, expiredIds))\n .returning({id: runnerSessions.id});\n\n return deleted.length;\n}\n"],"names":["and","asc","eq","gt","inArray","isNull","lt","notExists","or","sql","EmptyRunnerLabelsError","sanitizeRunnerLabelsOrThrow","db","provisionerTokens","runnerActivationTokens","runnerControlSessions","providerRunners","runnerSessions","toRunnerSession","runningJobExecutions","createRunnerSession","params","rows","insert","values","workspaceId","scope","registrationTokenId","registrationTokenKind","labels","toolCapabilities","toolCapabilitiesReportedAt","maxClaims","claimsUsed","returning","row","Error","getRunnerSessionById","runnerSessionId","select","from","where","id","limit","createRunnerSessionConsumingActivationToken","transaction","tx","runner","activationTokenId","runnerInstanceId","provisionerId","providerRunnerId","innerJoin","for","of","activationToken","consumedAt","revokedAt","expiresAt","provisioner","source","length","session","update","set","consumedSessionId","updatedAt","closedAt","closeReason","deleteExpiredRunnerSessions","expiredIds","createdAt","manualRetentionDays","ephemeralRetentionDays","orderBy","deleted","delete"],"mappings":"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"}
|
|
@@ -128,7 +128,7 @@ export declare const runnersAdminCommandResults: import("drizzle-orm/pg-core").P
|
|
|
128
128
|
generated: undefined;
|
|
129
129
|
}, {}, {}>;
|
|
130
130
|
};
|
|
131
|
-
dialect:
|
|
131
|
+
dialect: 'pg';
|
|
132
132
|
}>;
|
|
133
133
|
export type RunnersAdminCommandResultDb = typeof runnersAdminCommandResults.$inferSelect;
|
|
134
134
|
//# sourceMappingURL=admin-command-results.d.ts.map
|
|
@@ -191,7 +191,7 @@ export declare const ephemeralRegistrationTokens: import("drizzle-orm/pg-core").
|
|
|
191
191
|
generated: undefined;
|
|
192
192
|
}, {}, {}>;
|
|
193
193
|
};
|
|
194
|
-
dialect:
|
|
194
|
+
dialect: 'pg';
|
|
195
195
|
}>;
|
|
196
196
|
export type EphemeralRegistrationTokenDb = typeof ephemeralRegistrationTokens.$inferSelect;
|
|
197
197
|
export type EphemeralRegistrationTokenInsertDb = typeof ephemeralRegistrationTokens.$inferInsert;
|
|
@@ -157,7 +157,7 @@ export declare const manualRegistrationTokens: import("drizzle-orm/pg-core").PgT
|
|
|
157
157
|
generated: undefined;
|
|
158
158
|
}, {}, {}>;
|
|
159
159
|
};
|
|
160
|
-
dialect:
|
|
160
|
+
dialect: 'pg';
|
|
161
161
|
}>;
|
|
162
162
|
export type ManualRegistrationTokenDb = typeof manualRegistrationTokens.$inferSelect;
|
|
163
163
|
export type ManualRegistrationTokenInsertDb = typeof manualRegistrationTokens.$inferInsert;
|
|
@@ -156,8 +156,8 @@ export declare const pendingJobExecutions: import("drizzle-orm/pg-core").PgTable
|
|
|
156
156
|
}, {}, {
|
|
157
157
|
baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
|
|
158
158
|
name: "required_labels";
|
|
159
|
-
dataType:
|
|
160
|
-
columnType:
|
|
159
|
+
dataType: 'string';
|
|
160
|
+
columnType: 'PgText';
|
|
161
161
|
data: string;
|
|
162
162
|
enumValues: [string, ...string[]];
|
|
163
163
|
driverParam: string;
|
|
@@ -182,7 +182,7 @@ export declare const pendingJobExecutions: import("drizzle-orm/pg-core").PgTable
|
|
|
182
182
|
generated: undefined;
|
|
183
183
|
}, {}, {}>;
|
|
184
184
|
};
|
|
185
|
-
dialect:
|
|
185
|
+
dialect: 'pg';
|
|
186
186
|
}>;
|
|
187
187
|
export type PendingJobExecutionDb = typeof pendingJobExecutions.$inferSelect;
|
|
188
188
|
export type PendingJobExecutionInsertDb = typeof pendingJobExecutions.$inferInsert;
|
|
@@ -106,8 +106,8 @@ export declare const provisionerCapabilitySnapshots: import("drizzle-orm/pg-core
|
|
|
106
106
|
}, {}, {
|
|
107
107
|
baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
|
|
108
108
|
name: "labels";
|
|
109
|
-
dataType:
|
|
110
|
-
columnType:
|
|
109
|
+
dataType: 'string';
|
|
110
|
+
columnType: 'PgText';
|
|
111
111
|
data: string;
|
|
112
112
|
enumValues: [string, ...string[]];
|
|
113
113
|
driverParam: string;
|
|
@@ -200,7 +200,7 @@ export declare const provisionerCapabilitySnapshots: import("drizzle-orm/pg-core
|
|
|
200
200
|
generated: undefined;
|
|
201
201
|
}, {}, {}>;
|
|
202
202
|
};
|
|
203
|
-
dialect:
|
|
203
|
+
dialect: 'pg';
|
|
204
204
|
}>;
|
|
205
205
|
export type ProvisionerCapabilitySnapshotDb = typeof provisionerCapabilitySnapshots.$inferSelect;
|
|
206
206
|
export declare function toProvisionerCapabilitySnapshot(row: ProvisionerCapabilitySnapshotDb): ProvisionerCapabilitySnapshot;
|
|
@@ -26,7 +26,7 @@ export declare const provisionerTokens: import("drizzle-orm/pg-core").PgTableWit
|
|
|
26
26
|
tableName: "provisioner_tokens";
|
|
27
27
|
dataType: "string";
|
|
28
28
|
columnType: "PgEnumColumn";
|
|
29
|
-
data: "
|
|
29
|
+
data: "installation" | "workspace";
|
|
30
30
|
driverParam: string;
|
|
31
31
|
notNull: true;
|
|
32
32
|
hasDefault: false;
|
|
@@ -226,7 +226,7 @@ export declare const provisionerTokens: import("drizzle-orm/pg-core").PgTableWit
|
|
|
226
226
|
generated: undefined;
|
|
227
227
|
}, {}, {}>;
|
|
228
228
|
};
|
|
229
|
-
dialect:
|
|
229
|
+
dialect: 'pg';
|
|
230
230
|
}>;
|
|
231
231
|
export type ProvisionerTokenDb = typeof provisionerTokens.$inferSelect;
|
|
232
232
|
export type ProvisionerTokenInsertDb = typeof provisionerTokens.$inferInsert;
|
|
@@ -139,7 +139,7 @@ export declare const runnersRateLimits: import("drizzle-orm/pg-core").PgTableWit
|
|
|
139
139
|
generated: undefined;
|
|
140
140
|
}, {}, {}>;
|
|
141
141
|
};
|
|
142
|
-
dialect:
|
|
142
|
+
dialect: 'pg';
|
|
143
143
|
}>;
|
|
144
144
|
export type RunnersRateLimitDb = typeof runnersRateLimits.$inferSelect;
|
|
145
145
|
//# sourceMappingURL=rate-limits.d.ts.map
|
|
@@ -89,8 +89,8 @@ export declare const reservations: import("drizzle-orm/pg-core").PgTableWithColu
|
|
|
89
89
|
}, {}, {
|
|
90
90
|
baseBuilder: import("drizzle-orm/pg-core").PgColumnBuilder<{
|
|
91
91
|
name: "required_labels";
|
|
92
|
-
dataType:
|
|
93
|
-
columnType:
|
|
92
|
+
dataType: 'string';
|
|
93
|
+
columnType: 'PgText';
|
|
94
94
|
data: string;
|
|
95
95
|
enumValues: [string, ...string[]];
|
|
96
96
|
driverParam: string;
|
|
@@ -149,7 +149,7 @@ export declare const reservations: import("drizzle-orm/pg-core").PgTableWithColu
|
|
|
149
149
|
generated: undefined;
|
|
150
150
|
}, {}, {}>;
|
|
151
151
|
};
|
|
152
|
-
dialect:
|
|
152
|
+
dialect: 'pg';
|
|
153
153
|
}>;
|
|
154
154
|
export type ReservationDb = typeof reservations.$inferSelect;
|
|
155
155
|
export type ReservationInsertDb = typeof reservations.$inferInsert;
|
|
@@ -156,7 +156,7 @@ export declare const runnerBootstrapTokens: import("drizzle-orm/pg-core").PgTabl
|
|
|
156
156
|
generated: undefined;
|
|
157
157
|
}, {}, {}>;
|
|
158
158
|
};
|
|
159
|
-
dialect:
|
|
159
|
+
dialect: 'pg';
|
|
160
160
|
}>;
|
|
161
161
|
export declare const runnerControlSessions: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
162
162
|
name: "runner_control_sessions";
|
|
@@ -333,6 +333,6 @@ export declare const runnerControlSessions: import("drizzle-orm/pg-core").PgTabl
|
|
|
333
333
|
generated: undefined;
|
|
334
334
|
}, {}, {}>;
|
|
335
335
|
};
|
|
336
|
-
dialect:
|
|
336
|
+
dialect: 'pg';
|
|
337
337
|
}>;
|
|
338
338
|
//# sourceMappingURL=runner-control-sessions.d.ts.map
|