@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.
Files changed (129) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +35 -0
  3. package/dist/config.d.ts +3 -0
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +24 -2
  6. package/dist/config.js.map +1 -1
  7. package/dist/core/errors.d.ts +4 -0
  8. package/dist/core/errors.d.ts.map +1 -1
  9. package/dist/core/errors.js +6 -0
  10. package/dist/core/errors.js.map +1 -1
  11. package/dist/core/index.d.ts +1 -1
  12. package/dist/core/index.d.ts.map +1 -1
  13. package/dist/core/index.js +1 -1
  14. package/dist/core/index.js.map +1 -1
  15. package/dist/core/rate-limit.d.ts.map +1 -1
  16. package/dist/core/runner-control-sessions.d.ts.map +1 -1
  17. package/dist/core/runner-control-sessions.js +37 -11
  18. package/dist/core/runner-control-sessions.js.map +1 -1
  19. package/dist/core/runner-instances.d.ts +1 -0
  20. package/dist/core/runner-instances.d.ts.map +1 -1
  21. package/dist/core/runner-instances.js.map +1 -1
  22. package/dist/core/runner-labels.d.ts +11 -0
  23. package/dist/core/runner-labels.d.ts.map +1 -0
  24. package/dist/core/runner-labels.js +41 -0
  25. package/dist/core/runner-labels.js.map +1 -0
  26. package/dist/core/runner-sessions.d.ts.map +1 -1
  27. package/dist/core/runner-sessions.js +5 -1
  28. package/dist/core/runner-sessions.js.map +1 -1
  29. package/dist/db/db.d.ts +64 -64
  30. package/dist/db/ephemeral-registration-tokens.d.ts.map +1 -1
  31. package/dist/db/ephemeral-registration-tokens.js +12 -2
  32. package/dist/db/ephemeral-registration-tokens.js.map +1 -1
  33. package/dist/db/index.d.ts +1 -1
  34. package/dist/db/index.d.ts.map +1 -1
  35. package/dist/db/index.js +1 -1
  36. package/dist/db/index.js.map +1 -1
  37. package/dist/db/reservations.d.ts.map +1 -1
  38. package/dist/db/reservations.js +36 -10
  39. package/dist/db/reservations.js.map +1 -1
  40. package/dist/db/runner-instances.d.ts +4 -0
  41. package/dist/db/runner-instances.d.ts.map +1 -1
  42. package/dist/db/runner-instances.js +16 -5
  43. package/dist/db/runner-instances.js.map +1 -1
  44. package/dist/db/runner-sessions.d.ts.map +1 -1
  45. package/dist/db/runner-sessions.js +33 -15
  46. package/dist/db/runner-sessions.js.map +1 -1
  47. package/dist/db/schema/admin-command-results.d.ts +1 -1
  48. package/dist/db/schema/ephemeral-registration-tokens.d.ts +1 -1
  49. package/dist/db/schema/manual-registration-tokens.d.ts +1 -1
  50. package/dist/db/schema/outbox.d.ts +1 -1
  51. package/dist/db/schema/pending-job-executions.d.ts +3 -3
  52. package/dist/db/schema/provisioner-capability-snapshots.d.ts +3 -3
  53. package/dist/db/schema/provisioner-tokens.d.ts +2 -2
  54. package/dist/db/schema/rate-limits.d.ts +1 -1
  55. package/dist/db/schema/reservations.d.ts +3 -3
  56. package/dist/db/schema/runner-activation-tokens.d.ts +1 -1
  57. package/dist/db/schema/runner-control-sessions.d.ts +2 -2
  58. package/dist/db/schema/runner-instances.d.ts +4 -4
  59. package/dist/db/schema/runner-instances.d.ts.map +1 -1
  60. package/dist/db/schema/runner-instances.js +1 -0
  61. package/dist/db/schema/runner-instances.js.map +1 -1
  62. package/dist/db/schema/runner-sessions.d.ts +4 -4
  63. package/dist/db/schema/running-job-executions.d.ts +5 -5
  64. package/dist/metrics/index.d.ts +2 -1
  65. package/dist/metrics/index.d.ts.map +1 -1
  66. package/dist/metrics/index.js +1 -1
  67. package/dist/metrics/index.js.map +1 -1
  68. package/dist/metrics/instance.d.ts +13 -8
  69. package/dist/metrics/instance.d.ts.map +1 -1
  70. package/dist/metrics/instance.js +8 -0
  71. package/dist/metrics/instance.js.map +1 -1
  72. package/dist/metrics/service.d.ts.map +1 -1
  73. package/dist/metrics/service.js +20 -4
  74. package/dist/metrics/service.js.map +1 -1
  75. package/dist/presentation/dto/admin-provisioner-token.d.ts +1 -1
  76. package/dist/presentation/dto/admin-provisioner-token.d.ts.map +1 -1
  77. package/dist/presentation/dto/admin-runner-instances.d.ts +2 -2
  78. package/dist/presentation/dto/admin-runner-instances.d.ts.map +1 -1
  79. package/dist/presentation/routes/poll-demand.d.ts.map +1 -1
  80. package/dist/presentation/routes/poll-demand.js +12 -6
  81. package/dist/presentation/routes/poll-demand.js.map +1 -1
  82. package/dist/presentation/routes/rate-limit.d.ts.map +1 -1
  83. package/dist/presentation/routes/register.d.ts.map +1 -1
  84. package/dist/presentation/routes/register.js +9 -1
  85. package/dist/presentation/routes/register.js.map +1 -1
  86. package/dist/presentation/routes/report-runner-instances.d.ts.map +1 -1
  87. package/dist/presentation/routes/report-runner-instances.js +1 -0
  88. package/dist/presentation/routes/report-runner-instances.js.map +1 -1
  89. package/dist/tsconfig.test.tsbuildinfo +1 -1
  90. package/drizzle/0004_huge_skreet.sql +1 -0
  91. package/drizzle/meta/0004_snapshot.json +2194 -0
  92. package/drizzle/meta/_journal.json +7 -0
  93. package/package.json +9 -9
  94. package/src/config.test.ts +81 -0
  95. package/src/config.ts +39 -2
  96. package/src/core/errors.ts +9 -0
  97. package/src/core/index.ts +1 -0
  98. package/src/core/runner-control-sessions.test.ts +404 -0
  99. package/src/core/runner-control-sessions.ts +51 -11
  100. package/src/core/runner-instances.ts +1 -0
  101. package/src/core/runner-labels.test.ts +53 -0
  102. package/src/core/runner-labels.ts +51 -0
  103. package/src/core/runner-sessions.test.ts +34 -1
  104. package/src/core/runner-sessions.ts +8 -1
  105. package/src/db/ephemeral-registration-tokens.ts +15 -1
  106. package/src/db/index.ts +1 -0
  107. package/src/db/reservations.test.ts +537 -0
  108. package/src/db/reservations.ts +116 -17
  109. package/src/db/runner-instances.test.ts +276 -1
  110. package/src/db/runner-instances.ts +39 -3
  111. package/src/db/runner-sessions.ts +39 -15
  112. package/src/db/schema/runner-instances.ts +3 -0
  113. package/src/metrics/index.ts +2 -0
  114. package/src/metrics/instance.ts +18 -0
  115. package/src/metrics/service.test.ts +99 -0
  116. package/src/metrics/service.ts +24 -4
  117. package/src/presentation/routes/late-runner-enrollment.test.ts +230 -0
  118. package/src/presentation/routes/poll-demand.test.ts +116 -3
  119. package/src/presentation/routes/poll-demand.ts +18 -6
  120. package/src/presentation/routes/register.test.ts +116 -2
  121. package/src/presentation/routes/register.ts +7 -0
  122. package/src/presentation/routes/report-runner-instances.test.ts +33 -0
  123. package/src/presentation/routes/report-runner-instances.ts +1 -0
  124. package/src/presentation/routes/runner-enrollment.test.ts +65 -5
  125. package/src/temporal/activities/maintenance-activities.test.ts +24 -31
  126. package/test/env.ts +1 -0
  127. package/test/fixtures/late-runner-enrollment.ts +103 -0
  128. package/test/index.ts +5 -0
  129. 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":"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"}
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;AAQpE,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,0BAmEA;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
+ {"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 [token] = await tx.select({
32
- id: runnerActivationTokens.id,
33
- runnerInstanceId: runnerActivationTokens.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
- }).from(runnerActivationTokens).innerJoin(providerRunners, eq(providerRunners.id, runnerActivationTokens.runnerInstanceId)).where(and(eq(runnerActivationTokens.id, params.activationTokenId), isNull(runnerActivationTokens.consumedAt), isNull(runnerActivationTokens.revokedAt), gt(runnerActivationTokens.expiresAt, sql`now()`), isNull(providerRunners.runnerSessionId))).limit(1).for('update');
38
- if (!token?.workspaceId || !token.providerRunnerId) throw new Error('Runner activation token is invalid, expired, or has already been used');
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: token.workspaceId,
58
+ workspaceId: runner.workspaceId,
41
59
  scope: 'workspace',
42
- registrationTokenId: token.id,
60
+ registrationTokenId: activationToken.id,
43
61
  registrationTokenKind: 'activation',
44
- runnerInstanceId: token.runnerInstanceId,
45
- provisionerId: token.provisionerId,
46
- providerRunnerId: token.providerRunnerId,
47
- labels: params.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, token.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, token.runnerInstanceId), isNull(providerRunners.runnerSessionId)));
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, token.runnerInstanceId), isNull(runnerControlSessions.closedAt)));
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: "pg";
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: "pg";
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: "pg";
160
+ dialect: 'pg';
161
161
  }>;
162
162
  export type ManualRegistrationTokenDb = typeof manualRegistrationTokens.$inferSelect;
163
163
  export type ManualRegistrationTokenInsertDb = typeof manualRegistrationTokens.$inferInsert;
@@ -190,6 +190,6 @@ export declare const runnersOutbox: import("drizzle-orm/pg-core").PgTableWithCol
190
190
  generated: undefined;
191
191
  }, {}, {}>;
192
192
  };
193
- dialect: "pg";
193
+ dialect: 'pg';
194
194
  }>;
195
195
  //# sourceMappingURL=outbox.d.ts.map
@@ -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: "string";
160
- columnType: "PgText";
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: "pg";
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: "string";
110
- columnType: "PgText";
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: "pg";
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: "workspace" | "installation";
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: "pg";
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: "pg";
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: "string";
93
- columnType: "PgText";
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: "pg";
152
+ dialect: 'pg';
153
153
  }>;
154
154
  export type ReservationDb = typeof reservations.$inferSelect;
155
155
  export type ReservationInsertDb = typeof reservations.$inferInsert;
@@ -156,6 +156,6 @@ export declare const runnerActivationTokens: import("drizzle-orm/pg-core").PgTab
156
156
  generated: undefined;
157
157
  }, {}, {}>;
158
158
  };
159
- dialect: "pg";
159
+ dialect: 'pg';
160
160
  }>;
161
161
  //# sourceMappingURL=runner-activation-tokens.d.ts.map
@@ -156,7 +156,7 @@ export declare const runnerBootstrapTokens: import("drizzle-orm/pg-core").PgTabl
156
156
  generated: undefined;
157
157
  }, {}, {}>;
158
158
  };
159
- dialect: "pg";
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: "pg";
336
+ dialect: 'pg';
337
337
  }>;
338
338
  //# sourceMappingURL=runner-control-sessions.d.ts.map