@shipfox/api-workflows 12.7.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +9 -0
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/index.js.map +1 -1
- package/dist/db/job-listeners.d.ts.map +1 -1
- package/dist/db/job-listeners.js +17 -1
- package/dist/db/job-listeners.js.map +1 -1
- package/dist/db/workflow-runs/job-executions.d.ts +2 -3
- package/dist/db/workflow-runs/job-executions.d.ts.map +1 -1
- package/dist/db/workflow-runs/job-executions.js +48 -20
- package/dist/db/workflow-runs/job-executions.js.map +1 -1
- package/dist/db/workflow-runs/outbox.d.ts +15 -0
- package/dist/db/workflow-runs/outbox.d.ts.map +1 -1
- package/dist/db/workflow-runs/outbox.js +35 -1
- package/dist/db/workflow-runs/outbox.js.map +1 -1
- package/dist/db/workflow-runs/run-graph.d.ts.map +1 -1
- package/dist/db/workflow-runs/run-graph.js +12 -0
- package/dist/db/workflow-runs/run-graph.js.map +1 -1
- package/dist/db/workflow-runs/run-status.d.ts.map +1 -1
- package/dist/db/workflow-runs/run-status.js +13 -1
- package/dist/db/workflow-runs/run-status.js.map +1 -1
- package/dist/db/workflow-runs.d.ts +2 -2
- package/dist/db/workflow-runs.d.ts.map +1 -1
- package/dist/db/workflow-runs.js +2 -2
- package/dist/db/workflow-runs.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/presentation/index.d.ts +1 -1
- package/dist/presentation/index.d.ts.map +1 -1
- package/dist/presentation/index.js +1 -1
- package/dist/presentation/index.js.map +1 -1
- package/dist/presentation/subscribers/index.d.ts +0 -1
- package/dist/presentation/subscribers/index.d.ts.map +1 -1
- package/dist/presentation/subscribers/index.js +0 -1
- package/dist/presentation/subscribers/index.js.map +1 -1
- package/dist/temporal/activities/index.d.ts +2 -18
- package/dist/temporal/activities/index.d.ts.map +1 -1
- package/dist/temporal/activities/index.js +3 -5
- package/dist/temporal/activities/index.js.map +1 -1
- package/dist/temporal/activities/orchestration-activities.d.ts +5 -14
- package/dist/temporal/activities/orchestration-activities.d.ts.map +1 -1
- package/dist/temporal/activities/orchestration-activities.js +13 -34
- package/dist/temporal/activities/orchestration-activities.js.map +1 -1
- package/dist/temporal/workflows/index.bundle.js +20 -68
- package/dist/temporal/workflows/job-execution-orchestration.d.ts +0 -3
- package/dist/temporal/workflows/job-execution-orchestration.d.ts.map +1 -1
- package/dist/temporal/workflows/job-execution-orchestration.js +17 -41
- package/dist/temporal/workflows/job-execution-orchestration.js.map +1 -1
- package/dist/temporal/workflows/job-listener-orchestration.d.ts +0 -3
- package/dist/temporal/workflows/job-listener-orchestration.d.ts.map +1 -1
- package/dist/temporal/workflows/job-listener-orchestration.js +1 -9
- package/dist/temporal/workflows/job-listener-orchestration.js.map +1 -1
- package/dist/temporal/workflows/run-orchestration.d.ts.map +1 -1
- package/dist/temporal/workflows/run-orchestration.js +2 -18
- package/dist/temporal/workflows/run-orchestration.js.map +1 -1
- package/dist/temporal/workflows/test-env.d.ts +4 -6
- package/dist/temporal/workflows/test-env.d.ts.map +1 -1
- package/dist/temporal/workflows/test-env.js +13 -24
- package/dist/temporal/workflows/test-env.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/db/index.ts +1 -1
- package/src/db/job-listeners.test.ts +21 -0
- package/src/db/job-listeners.ts +18 -0
- package/src/db/workflow-runs/job-executions.test.ts +110 -12
- package/src/db/workflow-runs/job-executions.ts +54 -29
- package/src/db/workflow-runs/outbox.ts +63 -0
- package/src/db/workflow-runs/run-graph.ts +17 -0
- package/src/db/workflow-runs/run-status.test.ts +13 -0
- package/src/db/workflow-runs/run-status.ts +15 -1
- package/src/db/workflow-runs.ts +3 -1
- package/src/index.ts +1 -5
- package/src/presentation/index.ts +0 -1
- package/src/presentation/subscribers/index.ts +0 -1
- package/src/temporal/activities/index.ts +2 -8
- package/src/temporal/activities/orchestration-activities.test.ts +17 -1
- package/src/temporal/activities/orchestration-activities.ts +13 -46
- package/src/temporal/workflows/job-execution-orchestration.test.ts +6 -25
- package/src/temporal/workflows/job-execution-orchestration.ts +17 -43
- package/src/temporal/workflows/job-listener-orchestration-continuation.test.ts +0 -3
- package/src/temporal/workflows/job-listener-orchestration.test.ts +9 -12
- package/src/temporal/workflows/job-listener-orchestration.ts +0 -8
- package/src/temporal/workflows/run-orchestration.test.ts +22 -33
- package/src/temporal/workflows/run-orchestration.ts +4 -28
- package/src/temporal/workflows/test-env.ts +14 -34
- package/test/fixtures/runners-inter-module.ts +0 -3
- package/test/helpers/workflow-runs.ts +25 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/presentation/subscribers/on-runner-job-queued.d.ts +0 -3
- package/dist/presentation/subscribers/on-runner-job-queued.d.ts.map +0 -1
- package/dist/presentation/subscribers/on-runner-job-queued.js +0 -20
- package/dist/presentation/subscribers/on-runner-job-queued.js.map +0 -1
- package/src/presentation/subscribers/on-runner-job-queued.test.ts +0 -57
- package/src/presentation/subscribers/on-runner-job-queued.ts +0 -23
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db/workflow-runs/job-executions.ts"],"sourcesContent":["import {readPersistedWorkflowModel} from '@shipfox/api-definitions-dto';\nimport type {SecretsInterModuleClient} from '@shipfox/api-secrets-dto/inter-module';\nimport {WORKFLOWS_JOB_EXECUTION_TIMED_OUT} from '@shipfox/api-workflows-dto';\nimport {and, asc, desc, eq, isNull, notInArray, sql} from 'drizzle-orm';\nimport type {JobStatusReason} from '#core/entities/job.js';\nimport type {JobExecution, JobExecutionStatus} from '#core/entities/job-execution.js';\nimport {\n InterpolationUnresolvableError,\n JobNotFoundError,\n JobOutputNotJsonSafeError,\n JobOutputTooLargeError,\n JobOutputTooManyEntriesError,\n} from '#core/errors.js';\nimport {deriveJobExecutionOutputs} from '#core/job-transition/index.js';\nimport {deriveCompletion, isTerminal} from '#core/step-transition/decide-step-transition.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\nimport {\n recordWorkflowJobExecutionLeaseExpiryResolved,\n recordWorkflowJobExecutionQueued,\n recordWorkflowJobExecutionStarted,\n recordWorkflowJobExecutionStatusChanged,\n recordWorkflowJobExecutionTimedOut,\n} from '#metrics/instance.js';\nimport {db, type Tx} from '../db.js';\nimport {writeWorkflowsOutboxEvent} from '../outbox-writes.js';\nimport {jobExecutions, toJobExecution} from '../schema/job-executions.js';\nimport {jobs, toJob} from '../schema/jobs.js';\nimport {stepAttempts, toStepAttempt} from '../schema/step-attempts.js';\nimport {steps, toStep} from '../schema/steps.js';\nimport {workflowRunAttempts} from '../schema/workflow-run-attempts.js';\nimport {toWorkflowRun, workflowRuns} from '../schema/workflow-runs.js';\nimport {getDirectDependencyJobContexts} from './jobs.js';\nimport {loadReferencedVariables} from './runs.js';\nimport {\n getWorkflowContextForJob,\n optimisticLockRetry,\n TERMINAL_EXECUTION_STATUSES,\n} from './shared.js';\nimport {bulkUpdateStepStatuses, getStepsByJobExecutionIdForUpdate} from './steps.js';\n\nasync function getJobExecutionFallbackName(tx: Tx, jobExecutionId: string): Promise<string> {\n const [row] = await tx\n .select({job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.id, jobExecutionId))\n .limit(1);\n if (!row) throw new JobNotFoundError(jobExecutionId);\n return row.job.name ?? row.job.key;\n}\n\nexport async function getJobExecutionById(id: string, tx?: Tx): Promise<JobExecution | undefined> {\n const rows = await (tx ?? db())\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.id, id))\n .limit(1);\n const row = rows[0];\n return row ? toJobExecution(row.jobExecution, row.job.name ?? row.job.key) : undefined;\n}\n\nexport async function getJobExecutionsByWorkflowRunAttemptId(\n workflowRunAttemptId: string,\n): Promise<JobExecution[]> {\n const rows = await db()\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobs.workflowRunAttemptId, workflowRunAttemptId))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id));\n return rows.map((row) => toJobExecution(row.jobExecution, row.job.name ?? row.job.key));\n}\n\nexport async function getJobExecutionsByJobId(jobId: string): Promise<JobExecution[]> {\n const rows = await db()\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.jobId, jobId))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id));\n return rows.map((row) => toJobExecution(row.jobExecution, row.job.name ?? row.job.key));\n}\n\nexport async function getFirstJobExecutionByJobId(\n jobId: string,\n tx?: Tx,\n): Promise<JobExecution | undefined> {\n const rows = await (tx ?? db())\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.jobId, jobId))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id))\n .limit(1);\n const row = rows[0];\n return row ? toJobExecution(row.jobExecution, row.job.name ?? row.job.key) : undefined;\n}\n\nexport async function getLatestJobExecutionByJobId(\n jobId: string,\n tx?: Tx,\n): Promise<JobExecution | undefined> {\n const rows = await (tx ?? db())\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.jobId, jobId))\n .orderBy(desc(jobExecutions.sequence), desc(jobExecutions.id))\n .limit(1);\n const row = rows[0];\n return row ? toJobExecution(row.jobExecution, row.job.name ?? row.job.key) : undefined;\n}\n\nexport interface UpdateJobExecutionStatusAtVersionParams {\n jobExecutionId: string;\n status: JobExecutionStatus;\n expectedVersion: number;\n statusReason?: JobStatusReason | null | undefined;\n statusReasonMessage?: string | null | undefined;\n markTimedOut?: boolean;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}\n\nconst MAX_STATUS_REASON_MESSAGE_LENGTH = 2048;\n\nexport type JobOutputFailure = {\n statusReason: Extract<JobStatusReason, 'output_invalid' | 'output_too_large'>;\n statusReasonMessage: string;\n};\n\nexport function classifyJobOutputFailure(error: unknown): JobOutputFailure | null {\n if (error instanceof JobOutputTooLargeError) {\n return {\n statusReason: 'output_too_large',\n statusReasonMessage: boundedStatusReasonMessage(error.message),\n };\n }\n\n if (\n (error instanceof InterpolationUnresolvableError && error.field === 'job.outputs') ||\n error instanceof JobOutputNotJsonSafeError ||\n error instanceof JobOutputTooManyEntriesError\n ) {\n return {\n statusReason: 'output_invalid',\n statusReasonMessage: boundedStatusReasonMessage(error.message),\n };\n }\n\n return null;\n}\n\nfunction boundedStatusReasonMessage(message: string): string {\n return message.length <= MAX_STATUS_REASON_MESSAGE_LENGTH\n ? message\n : `${message.slice(0, MAX_STATUS_REASON_MESSAGE_LENGTH - 1)}…`;\n}\n\nasync function resolveJobExecutionOutputs(\n tx: Tx,\n params: {\n jobExecutionId: string;\n status: JobExecutionStatus;\n statusReason: JobStatusReason | null;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n },\n): Promise<Record<string, unknown> | null> {\n const [target] = await tx\n .select({execution: jobExecutions, job: jobs, attempt: workflowRunAttempts, run: workflowRuns})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .innerJoin(workflowRunAttempts, eq(jobs.workflowRunAttemptId, workflowRunAttempts.id))\n .innerJoin(workflowRuns, eq(workflowRunAttempts.workflowRunId, workflowRuns.id))\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1);\n if (!target) throw new JobNotFoundError(params.jobExecutionId);\n const model =\n target.attempt.model === null ? null : readPersistedWorkflowModel(target.attempt.model);\n if (!model) return null;\n const modelJob = model.jobs.find((job) => job.key === target.job.key);\n if (!modelJob || modelJob.outputs === undefined) return null;\n\n const executionRows = await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.jobId, target.job.id))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id));\n const fallbackName = target.job.name ?? target.job.key;\n const executions = executionRows.map((row) =>\n row.id === target.execution.id\n ? toJobExecution(\n {...row, status: params.status, statusReason: params.statusReason},\n fallbackName,\n )\n : toJobExecution(row, fallbackName),\n );\n const jobExecution = executions.find((execution) => execution.id === target.execution.id);\n if (!jobExecution) throw new JobNotFoundError(params.jobExecutionId);\n\n const stepRows = await tx\n .select()\n .from(steps)\n .where(eq(steps.jobExecutionId, params.jobExecutionId))\n .orderBy(asc(steps.position), asc(steps.id));\n const attemptRows = await tx\n .select()\n .from(stepAttempts)\n .where(eq(stepAttempts.jobExecutionId, params.jobExecutionId))\n .orderBy(asc(stepAttempts.executionOrder), asc(stepAttempts.id));\n const dependencyJobs = await getDirectDependencyJobContexts(target.job.id, tx);\n\n return deriveJobExecutionOutputs({\n run: toWorkflowRun(target.run),\n modelJob,\n job: toJob(target.job),\n jobExecution,\n executions,\n steps: stepRows.map(toStep),\n attempts: attemptRows.map(toStepAttempt),\n jobs: dependencyJobs,\n vars: await loadReferencedVariables({\n model,\n jobs: [modelJob],\n workspaceId: target.run.workspaceId,\n projectId: target.run.projectId,\n definitionId: target.run.definitionId,\n secrets: params.secrets,\n }),\n });\n}\n\nasync function updateJobExecutionStatusAtVersion(\n tx: Tx,\n params: UpdateJobExecutionStatusAtVersionParams,\n): Promise<{execution: JobExecution; changed: boolean} | null> {\n let status = params.status;\n let statusReason = params.statusReason ?? null;\n let statusReasonMessage = params.statusReasonMessage ?? null;\n let outputs: Record<string, unknown> | null | undefined;\n if (TERMINAL_EXECUTION_STATUSES.includes(status)) {\n outputs = null;\n }\n if (status === 'succeeded') {\n try {\n outputs = await resolveJobExecutionOutputs(tx, {\n jobExecutionId: params.jobExecutionId,\n status,\n statusReason,\n secrets: params.secrets,\n });\n } catch (error) {\n const outputFailure = classifyJobOutputFailure(error);\n if (outputFailure === null) throw error;\n status = 'failed';\n statusReason = outputFailure.statusReason;\n statusReasonMessage = outputFailure.statusReasonMessage;\n outputs = null;\n }\n }\n\n const rows = await tx\n .update(jobExecutions)\n .set({\n status,\n statusReason,\n statusReasonMessage,\n ...(outputs === undefined ? {} : {outputs}),\n version: sql`${jobExecutions.version} + 1`,\n updatedAt: new Date(),\n ...(params.markTimedOut ? {timedOutAt: new Date()} : {}),\n ...(TERMINAL_EXECUTION_STATUSES.includes(status) ? {finishedAt: sql`now()`} : {}),\n })\n .where(\n and(\n eq(jobExecutions.id, params.jobExecutionId),\n eq(jobExecutions.version, params.expectedVersion),\n notInArray(jobExecutions.status, TERMINAL_EXECUTION_STATUSES),\n ),\n )\n .returning();\n\n const row = rows[0];\n if (!row) return null;\n return {\n execution: toJobExecution(row, await getJobExecutionFallbackName(tx, row.id)),\n changed: true,\n };\n}\n\nexport interface UpdateJobExecutionStatusParams {\n jobExecutionId: string;\n status: JobExecutionStatus;\n expectedVersion: number;\n statusReason?: JobStatusReason | null | undefined;\n statusReasonMessage?: string | null | undefined;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}\n\nexport async function updateJobExecutionStatus(\n params: UpdateJobExecutionStatusParams,\n): Promise<JobExecution> {\n const statusReason = params.statusReason ?? null;\n const result = await db().transaction(async (tx) => {\n return await optimisticLockRetry({\n updateFn: () =>\n updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status: params.status,\n expectedVersion: params.expectedVersion,\n statusReason,\n statusReasonMessage: params.statusReasonMessage,\n secrets: params.secrets,\n }),\n fetchFn: async () => {\n const row = (\n await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1)\n )[0];\n return row ? toJobExecution(row, await getJobExecutionFallbackName(tx, row.id)) : undefined;\n },\n matchFn: (execution) =>\n (execution.status === params.status && execution.statusReason === statusReason) ||\n TERMINAL_EXECUTION_STATUSES.includes(execution.status)\n ? {execution, changed: false}\n : null,\n failureMessage: `Optimistic lock failure: job execution ${params.jobExecutionId} version ${params.expectedVersion}`,\n });\n });\n\n if (result.changed) recordWorkflowJobExecutionStatusChanged(result.execution.status);\n\n return result.execution;\n}\n\nexport async function recordJobExecutionQueuedAt(params: {\n jobExecutionId: string;\n queuedAt: Date;\n}): Promise<void> {\n const updated = await db()\n .update(jobExecutions)\n .set({queuedAt: params.queuedAt})\n .where(and(eq(jobExecutions.id, params.jobExecutionId), isNull(jobExecutions.queuedAt)))\n .returning({id: jobExecutions.id});\n\n if (updated.length > 0) recordWorkflowJobExecutionQueued();\n}\n\nexport async function recordJobExecutionStartedAt(params: {\n jobExecutionId: string;\n startedAt: Date;\n}): Promise<void> {\n const updated = await db()\n .update(jobExecutions)\n .set({startedAt: params.startedAt})\n .where(and(eq(jobExecutions.id, params.jobExecutionId), isNull(jobExecutions.startedAt)))\n .returning({id: jobExecutions.id});\n\n if (updated.length > 0) recordWorkflowJobExecutionStarted();\n}\n\nexport async function failJobExecutionAsTimedOut(params: {\n jobExecutionId: string;\n workflowRunAttemptId: string;\n expectedVersion: number;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}): Promise<JobExecution> {\n const result = await db().transaction(async (tx) => {\n const updated = await optimisticLockRetry({\n updateFn: () =>\n updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status: 'failed',\n expectedVersion: params.expectedVersion,\n statusReason: 'timed_out',\n markTimedOut: true,\n secrets: params.secrets,\n }),\n fetchFn: async () => {\n const row = (\n await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1)\n )[0];\n return row ? toJobExecution(row, await getJobExecutionFallbackName(tx, row.id)) : undefined;\n },\n matchFn: (execution) => (execution.timedOutAt !== null ? {execution, changed: false} : null),\n failureMessage: `Optimistic lock failure: job execution ${params.jobExecutionId} version ${params.expectedVersion}`,\n });\n\n if (updated.changed) {\n const identity = await getWorkflowContextForJob(updated.execution.jobId, tx);\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_JOB_EXECUTION_TIMED_OUT,\n payload: {\n jobId: identity.jobId,\n jobExecutionId: params.jobExecutionId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n },\n });\n }\n\n return updated;\n });\n\n if (result.changed) {\n recordWorkflowJobExecutionStatusChanged(result.execution.status);\n recordWorkflowJobExecutionTimedOut();\n }\n\n return result.execution;\n}\n\nexport async function resolveJobExecutionAfterLeaseExpiry(params: {\n jobExecutionId: string;\n expectedVersion: number;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}): Promise<{status: RuntimeCompletionStatus; executionVersion: number}> {\n const result = await db().transaction(async (tx) => {\n const jobExecutionSteps = await getStepsByJobExecutionIdForUpdate(params.jobExecutionId, tx);\n let changedJobExecution: JobExecution | null = null;\n\n if (jobExecutionSteps.length === 0) {\n throw new JobNotFoundError(params.jobExecutionId);\n }\n\n if (jobExecutionSteps.every((step) => isTerminal(step.status))) {\n const status = deriveCompletion(jobExecutionSteps);\n const updated = await updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status,\n expectedVersion: params.expectedVersion,\n statusReason: statusReasonForStepCompletion(status),\n secrets: params.secrets,\n });\n changedJobExecution = updated?.changed ? updated.execution : null;\n } else {\n const updated = await updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status: 'failed',\n expectedVersion: params.expectedVersion,\n statusReason: 'runner_lost',\n secrets: params.secrets,\n });\n if (updated?.changed) {\n changedJobExecution = updated.execution;\n await bulkUpdateStepStatuses(\n {jobExecutionId: params.jobExecutionId, status: 'cancelled'},\n tx,\n );\n }\n }\n\n const jobExecutionRow = (\n await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1)\n )[0];\n if (!jobExecutionRow) {\n throw new Error(`Job execution not found resolving lease expiry: ${params.jobExecutionId}`);\n }\n const status: RuntimeCompletionStatus =\n jobExecutionRow.status === 'succeeded' ? 'succeeded' : 'failed';\n return {status, executionVersion: jobExecutionRow.version, changedJobExecution};\n });\n\n recordWorkflowJobExecutionLeaseExpiryResolved(result.status);\n if (result.changedJobExecution) {\n recordWorkflowJobExecutionStatusChanged(result.changedJobExecution.status);\n }\n\n return {status: result.status, executionVersion: result.executionVersion};\n}\n\nfunction statusReasonForStepCompletion(status: RuntimeCompletionStatus): JobStatusReason | null {\n return status === 'failed' ? 'step_failed' : null;\n}\n"],"names":["readPersistedWorkflowModel","WORKFLOWS_JOB_EXECUTION_TIMED_OUT","and","asc","desc","eq","isNull","notInArray","sql","InterpolationUnresolvableError","JobNotFoundError","JobOutputNotJsonSafeError","JobOutputTooLargeError","JobOutputTooManyEntriesError","deriveJobExecutionOutputs","deriveCompletion","isTerminal","recordWorkflowJobExecutionLeaseExpiryResolved","recordWorkflowJobExecutionQueued","recordWorkflowJobExecutionStarted","recordWorkflowJobExecutionStatusChanged","recordWorkflowJobExecutionTimedOut","db","writeWorkflowsOutboxEvent","jobExecutions","toJobExecution","jobs","toJob","stepAttempts","toStepAttempt","steps","toStep","workflowRunAttempts","toWorkflowRun","workflowRuns","getDirectDependencyJobContexts","loadReferencedVariables","getWorkflowContextForJob","optimisticLockRetry","TERMINAL_EXECUTION_STATUSES","bulkUpdateStepStatuses","getStepsByJobExecutionIdForUpdate","getJobExecutionFallbackName","tx","jobExecutionId","row","select","job","from","innerJoin","jobId","id","where","limit","name","key","getJobExecutionById","rows","jobExecution","undefined","getJobExecutionsByWorkflowRunAttemptId","workflowRunAttemptId","orderBy","sequence","map","getJobExecutionsByJobId","getFirstJobExecutionByJobId","getLatestJobExecutionByJobId","MAX_STATUS_REASON_MESSAGE_LENGTH","classifyJobOutputFailure","error","statusReason","statusReasonMessage","boundedStatusReasonMessage","message","field","length","slice","resolveJobExecutionOutputs","params","target","execution","attempt","run","workflowRunId","model","modelJob","find","outputs","executionRows","fallbackName","executions","status","stepRows","position","attemptRows","executionOrder","dependencyJobs","attempts","vars","workspaceId","projectId","definitionId","secrets","updateJobExecutionStatusAtVersion","includes","outputFailure","update","set","version","updatedAt","Date","markTimedOut","timedOutAt","finishedAt","expectedVersion","returning","changed","updateJobExecutionStatus","result","transaction","updateFn","fetchFn","matchFn","failureMessage","recordJobExecutionQueuedAt","updated","queuedAt","recordJobExecutionStartedAt","startedAt","failJobExecutionAsTimedOut","identity","type","payload","resolveJobExecutionAfterLeaseExpiry","jobExecutionSteps","changedJobExecution","every","step","statusReasonForStepCompletion","jobExecutionRow","Error","executionVersion"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/db/workflow-runs/job-executions.ts"],"sourcesContent":["import {readPersistedWorkflowModel} from '@shipfox/api-definitions-dto';\nimport type {SecretsInterModuleClient} from '@shipfox/api-secrets-dto/inter-module';\nimport {canonicalizeLabels} from '@shipfox/runner-labels';\nimport {and, asc, desc, eq, isNull, notInArray, sql} from 'drizzle-orm';\nimport type {JobStatusReason} from '#core/entities/job.js';\nimport type {JobExecution, JobExecutionStatus} from '#core/entities/job-execution.js';\nimport {\n InterpolationUnresolvableError,\n JobNotFoundError,\n JobOutputNotJsonSafeError,\n JobOutputTooLargeError,\n JobOutputTooManyEntriesError,\n} from '#core/errors.js';\nimport {deriveJobExecutionOutputs} from '#core/job-transition/index.js';\nimport {deriveCompletion, isTerminal} from '#core/step-transition/decide-step-transition.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\nimport {\n recordWorkflowJobExecutionLeaseExpiryResolved,\n recordWorkflowJobExecutionQueued,\n recordWorkflowJobExecutionStarted,\n recordWorkflowJobExecutionStatusChanged,\n recordWorkflowJobExecutionTimedOut,\n} from '#metrics/instance.js';\nimport {db, type Tx} from '../db.js';\nimport {jobExecutions, toJobExecution} from '../schema/job-executions.js';\nimport {jobs, toJob} from '../schema/jobs.js';\nimport {stepAttempts, toStepAttempt} from '../schema/step-attempts.js';\nimport {steps, toStep} from '../schema/steps.js';\nimport {workflowRunAttempts} from '../schema/workflow-run-attempts.js';\nimport {toWorkflowRun, workflowRuns} from '../schema/workflow-runs.js';\nimport {getDirectDependencyJobContexts} from './jobs.js';\nimport {writeJobExecutionQueuedOutbox, writeJobExecutionTerminatedOutbox} from './outbox.js';\nimport {loadReferencedVariables} from './runs.js';\nimport {optimisticLockRetry, TERMINAL_EXECUTION_STATUSES} from './shared.js';\nimport {bulkUpdateStepStatuses, getStepsByJobExecutionIdForUpdate} from './steps.js';\n\nasync function getJobExecutionFallbackName(tx: Tx, jobExecutionId: string): Promise<string> {\n const [row] = await tx\n .select({job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.id, jobExecutionId))\n .limit(1);\n if (!row) throw new JobNotFoundError(jobExecutionId);\n return row.job.name ?? row.job.key;\n}\n\nexport async function getJobExecutionById(id: string, tx?: Tx): Promise<JobExecution | undefined> {\n const rows = await (tx ?? db())\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.id, id))\n .limit(1);\n const row = rows[0];\n return row ? toJobExecution(row.jobExecution, row.job.name ?? row.job.key) : undefined;\n}\n\nexport async function getJobExecutionsByWorkflowRunAttemptId(\n workflowRunAttemptId: string,\n): Promise<JobExecution[]> {\n const rows = await db()\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobs.workflowRunAttemptId, workflowRunAttemptId))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id));\n return rows.map((row) => toJobExecution(row.jobExecution, row.job.name ?? row.job.key));\n}\n\nexport async function getJobExecutionsByJobId(jobId: string): Promise<JobExecution[]> {\n const rows = await db()\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.jobId, jobId))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id));\n return rows.map((row) => toJobExecution(row.jobExecution, row.job.name ?? row.job.key));\n}\n\nexport async function getFirstJobExecutionByJobId(\n jobId: string,\n tx?: Tx,\n): Promise<JobExecution | undefined> {\n const rows = await (tx ?? db())\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.jobId, jobId))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id))\n .limit(1);\n const row = rows[0];\n return row ? toJobExecution(row.jobExecution, row.job.name ?? row.job.key) : undefined;\n}\n\nexport async function getLatestJobExecutionByJobId(\n jobId: string,\n tx?: Tx,\n): Promise<JobExecution | undefined> {\n const rows = await (tx ?? db())\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.jobId, jobId))\n .orderBy(desc(jobExecutions.sequence), desc(jobExecutions.id))\n .limit(1);\n const row = rows[0];\n return row ? toJobExecution(row.jobExecution, row.job.name ?? row.job.key) : undefined;\n}\n\nexport interface UpdateJobExecutionStatusAtVersionParams {\n jobExecutionId: string;\n status: JobExecutionStatus;\n expectedVersion: number;\n statusReason?: JobStatusReason | null | undefined;\n statusReasonMessage?: string | null | undefined;\n markTimedOut?: boolean;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}\n\nconst MAX_STATUS_REASON_MESSAGE_LENGTH = 2048;\n\nexport type JobOutputFailure = {\n statusReason: Extract<JobStatusReason, 'output_invalid' | 'output_too_large'>;\n statusReasonMessage: string;\n};\n\nexport function classifyJobOutputFailure(error: unknown): JobOutputFailure | null {\n if (error instanceof JobOutputTooLargeError) {\n return {\n statusReason: 'output_too_large',\n statusReasonMessage: boundedStatusReasonMessage(error.message),\n };\n }\n\n if (\n (error instanceof InterpolationUnresolvableError && error.field === 'job.outputs') ||\n error instanceof JobOutputNotJsonSafeError ||\n error instanceof JobOutputTooManyEntriesError\n ) {\n return {\n statusReason: 'output_invalid',\n statusReasonMessage: boundedStatusReasonMessage(error.message),\n };\n }\n\n return null;\n}\n\nfunction boundedStatusReasonMessage(message: string): string {\n return message.length <= MAX_STATUS_REASON_MESSAGE_LENGTH\n ? message\n : `${message.slice(0, MAX_STATUS_REASON_MESSAGE_LENGTH - 1)}…`;\n}\n\nasync function resolveJobExecutionOutputs(\n tx: Tx,\n params: {\n jobExecutionId: string;\n status: JobExecutionStatus;\n statusReason: JobStatusReason | null;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n },\n): Promise<Record<string, unknown> | null> {\n const [target] = await tx\n .select({execution: jobExecutions, job: jobs, attempt: workflowRunAttempts, run: workflowRuns})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .innerJoin(workflowRunAttempts, eq(jobs.workflowRunAttemptId, workflowRunAttempts.id))\n .innerJoin(workflowRuns, eq(workflowRunAttempts.workflowRunId, workflowRuns.id))\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1);\n if (!target) throw new JobNotFoundError(params.jobExecutionId);\n const model =\n target.attempt.model === null ? null : readPersistedWorkflowModel(target.attempt.model);\n if (!model) return null;\n const modelJob = model.jobs.find((job) => job.key === target.job.key);\n if (!modelJob || modelJob.outputs === undefined) return null;\n\n const executionRows = await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.jobId, target.job.id))\n .orderBy(asc(jobExecutions.sequence), asc(jobExecutions.id));\n const fallbackName = target.job.name ?? target.job.key;\n const executions = executionRows.map((row) =>\n row.id === target.execution.id\n ? toJobExecution(\n {...row, status: params.status, statusReason: params.statusReason},\n fallbackName,\n )\n : toJobExecution(row, fallbackName),\n );\n const jobExecution = executions.find((execution) => execution.id === target.execution.id);\n if (!jobExecution) throw new JobNotFoundError(params.jobExecutionId);\n\n const stepRows = await tx\n .select()\n .from(steps)\n .where(eq(steps.jobExecutionId, params.jobExecutionId))\n .orderBy(asc(steps.position), asc(steps.id));\n const attemptRows = await tx\n .select()\n .from(stepAttempts)\n .where(eq(stepAttempts.jobExecutionId, params.jobExecutionId))\n .orderBy(asc(stepAttempts.executionOrder), asc(stepAttempts.id));\n const dependencyJobs = await getDirectDependencyJobContexts(target.job.id, tx);\n\n return deriveJobExecutionOutputs({\n run: toWorkflowRun(target.run),\n modelJob,\n job: toJob(target.job),\n jobExecution,\n executions,\n steps: stepRows.map(toStep),\n attempts: attemptRows.map(toStepAttempt),\n jobs: dependencyJobs,\n vars: await loadReferencedVariables({\n model,\n jobs: [modelJob],\n workspaceId: target.run.workspaceId,\n projectId: target.run.projectId,\n definitionId: target.run.definitionId,\n secrets: params.secrets,\n }),\n });\n}\n\nasync function updateJobExecutionStatusAtVersion(\n tx: Tx,\n params: UpdateJobExecutionStatusAtVersionParams,\n): Promise<{execution: JobExecution; changed: boolean} | null> {\n let status = params.status;\n let statusReason = params.statusReason ?? null;\n let statusReasonMessage = params.statusReasonMessage ?? null;\n let outputs: Record<string, unknown> | null | undefined;\n if (TERMINAL_EXECUTION_STATUSES.includes(status)) {\n outputs = null;\n }\n if (status === 'succeeded') {\n try {\n outputs = await resolveJobExecutionOutputs(tx, {\n jobExecutionId: params.jobExecutionId,\n status,\n statusReason,\n secrets: params.secrets,\n });\n } catch (error) {\n const outputFailure = classifyJobOutputFailure(error);\n if (outputFailure === null) throw error;\n status = 'failed';\n statusReason = outputFailure.statusReason;\n statusReasonMessage = outputFailure.statusReasonMessage;\n outputs = null;\n }\n }\n\n const rows = await tx\n .update(jobExecutions)\n .set({\n status,\n statusReason,\n statusReasonMessage,\n ...(outputs === undefined ? {} : {outputs}),\n version: sql`${jobExecutions.version} + 1`,\n updatedAt: new Date(),\n ...(params.markTimedOut ? {timedOutAt: new Date()} : {}),\n ...(TERMINAL_EXECUTION_STATUSES.includes(status) ? {finishedAt: sql`now()`} : {}),\n })\n .where(\n and(\n eq(jobExecutions.id, params.jobExecutionId),\n eq(jobExecutions.version, params.expectedVersion),\n notInArray(jobExecutions.status, TERMINAL_EXECUTION_STATUSES),\n ),\n )\n .returning();\n\n const row = rows[0];\n if (!row) return null;\n if (TERMINAL_EXECUTION_STATUSES.includes(row.status)) {\n await writeJobExecutionTerminatedOutbox(tx, {\n jobId: row.jobId,\n jobExecutionId: row.id,\n status: row.status,\n statusReason: row.statusReason,\n statusReasonMessage: row.statusReasonMessage,\n });\n }\n return {\n execution: toJobExecution(row, await getJobExecutionFallbackName(tx, row.id)),\n changed: true,\n };\n}\n\nexport interface UpdateJobExecutionStatusParams {\n jobExecutionId: string;\n status: JobExecutionStatus;\n expectedVersion: number;\n statusReason?: JobStatusReason | null | undefined;\n statusReasonMessage?: string | null | undefined;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}\n\nexport async function updateJobExecutionStatus(\n params: UpdateJobExecutionStatusParams,\n): Promise<JobExecution> {\n const statusReason = params.statusReason ?? null;\n const result = await db().transaction(async (tx) => {\n return await optimisticLockRetry({\n updateFn: () =>\n updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status: params.status,\n expectedVersion: params.expectedVersion,\n statusReason,\n statusReasonMessage: params.statusReasonMessage,\n secrets: params.secrets,\n }),\n fetchFn: async () => {\n const row = (\n await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1)\n )[0];\n return row ? toJobExecution(row, await getJobExecutionFallbackName(tx, row.id)) : undefined;\n },\n matchFn: (execution) =>\n (execution.status === params.status && execution.statusReason === statusReason) ||\n TERMINAL_EXECUTION_STATUSES.includes(execution.status)\n ? {execution, changed: false}\n : null,\n failureMessage: `Optimistic lock failure: job execution ${params.jobExecutionId} version ${params.expectedVersion}`,\n });\n });\n\n if (result.changed) recordWorkflowJobExecutionStatusChanged(result.execution.status);\n\n return result.execution;\n}\n\nexport async function queueJobExecution(params: {jobExecutionId: string}): Promise<JobExecution> {\n const result = await db().transaction(async (tx) => {\n const [row] = await tx\n .select({jobExecution: jobExecutions, job: jobs})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1)\n .for('update');\n if (!row) throw new JobNotFoundError(params.jobExecutionId);\n\n const existing = toJobExecution(row.jobExecution, row.job.name ?? row.job.key);\n if (existing.queuedAt !== null || TERMINAL_EXECUTION_STATUSES.includes(existing.status)) {\n return {execution: existing, changed: false};\n }\n\n const requiredLabels = [...canonicalizeLabels(existing.runner ?? row.job.runner ?? [])];\n if (requiredLabels.length === 0) {\n throw new Error(`Job execution ${params.jobExecutionId} has no required runner labels`);\n }\n\n const [queued] = await tx\n .update(jobExecutions)\n .set({queuedAt: sql`now()`})\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .returning();\n if (!queued?.queuedAt) throw new Error(`Cannot queue job execution ${params.jobExecutionId}`);\n\n await writeJobExecutionQueuedOutbox(tx, {\n jobId: queued.jobId,\n jobExecutionId: queued.id,\n requiredLabels,\n queuedAt: queued.queuedAt,\n });\n\n return {\n execution: toJobExecution(queued, row.job.name ?? row.job.key),\n changed: true,\n };\n });\n\n if (result.changed) recordWorkflowJobExecutionQueued();\n return result.execution;\n}\n\nexport async function recordJobExecutionStartedAt(params: {\n jobExecutionId: string;\n startedAt: Date;\n}): Promise<void> {\n const updated = await db()\n .update(jobExecutions)\n .set({startedAt: params.startedAt})\n .where(and(eq(jobExecutions.id, params.jobExecutionId), isNull(jobExecutions.startedAt)))\n .returning({id: jobExecutions.id});\n\n if (updated.length > 0) recordWorkflowJobExecutionStarted();\n}\n\nexport async function failJobExecutionAsTimedOut(params: {\n jobExecutionId: string;\n workflowRunAttemptId: string;\n expectedVersion: number;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}): Promise<JobExecution> {\n const result = await db().transaction(async (tx) => {\n const updated = await optimisticLockRetry({\n updateFn: () =>\n updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status: 'failed',\n expectedVersion: params.expectedVersion,\n statusReason: 'timed_out',\n markTimedOut: true,\n secrets: params.secrets,\n }),\n fetchFn: async () => {\n const row = (\n await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1)\n )[0];\n return row ? toJobExecution(row, await getJobExecutionFallbackName(tx, row.id)) : undefined;\n },\n matchFn: (execution) => (execution.timedOutAt !== null ? {execution, changed: false} : null),\n failureMessage: `Optimistic lock failure: job execution ${params.jobExecutionId} version ${params.expectedVersion}`,\n });\n\n return updated;\n });\n\n if (result.changed) {\n recordWorkflowJobExecutionStatusChanged(result.execution.status);\n recordWorkflowJobExecutionTimedOut();\n }\n\n return result.execution;\n}\n\nexport async function resolveJobExecutionAfterLeaseExpiry(params: {\n jobExecutionId: string;\n expectedVersion: number;\n secrets?: Pick<SecretsInterModuleClient, 'getVariablesByNamespace'> | undefined;\n}): Promise<{status: RuntimeCompletionStatus; executionVersion: number}> {\n const result = await db().transaction(async (tx) => {\n const jobExecutionSteps = await getStepsByJobExecutionIdForUpdate(params.jobExecutionId, tx);\n let changedJobExecution: JobExecution | null = null;\n\n if (jobExecutionSteps.length === 0) {\n throw new JobNotFoundError(params.jobExecutionId);\n }\n\n if (jobExecutionSteps.every((step) => isTerminal(step.status))) {\n const status = deriveCompletion(jobExecutionSteps);\n const updated = await updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status,\n expectedVersion: params.expectedVersion,\n statusReason: statusReasonForStepCompletion(status),\n secrets: params.secrets,\n });\n changedJobExecution = updated?.changed ? updated.execution : null;\n } else {\n const updated = await updateJobExecutionStatusAtVersion(tx, {\n jobExecutionId: params.jobExecutionId,\n status: 'failed',\n expectedVersion: params.expectedVersion,\n statusReason: 'runner_lost',\n secrets: params.secrets,\n });\n if (updated?.changed) {\n changedJobExecution = updated.execution;\n await bulkUpdateStepStatuses(\n {jobExecutionId: params.jobExecutionId, status: 'cancelled'},\n tx,\n );\n }\n }\n\n const jobExecutionRow = (\n await tx\n .select()\n .from(jobExecutions)\n .where(eq(jobExecutions.id, params.jobExecutionId))\n .limit(1)\n )[0];\n if (!jobExecutionRow) {\n throw new Error(`Job execution not found resolving lease expiry: ${params.jobExecutionId}`);\n }\n const status: RuntimeCompletionStatus =\n jobExecutionRow.status === 'succeeded' ? 'succeeded' : 'failed';\n return {status, executionVersion: jobExecutionRow.version, changedJobExecution};\n });\n\n recordWorkflowJobExecutionLeaseExpiryResolved(result.status);\n if (result.changedJobExecution) {\n recordWorkflowJobExecutionStatusChanged(result.changedJobExecution.status);\n }\n\n return {status: result.status, executionVersion: result.executionVersion};\n}\n\nfunction statusReasonForStepCompletion(status: RuntimeCompletionStatus): JobStatusReason | null {\n return status === 'failed' ? 'step_failed' : null;\n}\n"],"names":["readPersistedWorkflowModel","canonicalizeLabels","and","asc","desc","eq","isNull","notInArray","sql","InterpolationUnresolvableError","JobNotFoundError","JobOutputNotJsonSafeError","JobOutputTooLargeError","JobOutputTooManyEntriesError","deriveJobExecutionOutputs","deriveCompletion","isTerminal","recordWorkflowJobExecutionLeaseExpiryResolved","recordWorkflowJobExecutionQueued","recordWorkflowJobExecutionStarted","recordWorkflowJobExecutionStatusChanged","recordWorkflowJobExecutionTimedOut","db","jobExecutions","toJobExecution","jobs","toJob","stepAttempts","toStepAttempt","steps","toStep","workflowRunAttempts","toWorkflowRun","workflowRuns","getDirectDependencyJobContexts","writeJobExecutionQueuedOutbox","writeJobExecutionTerminatedOutbox","loadReferencedVariables","optimisticLockRetry","TERMINAL_EXECUTION_STATUSES","bulkUpdateStepStatuses","getStepsByJobExecutionIdForUpdate","getJobExecutionFallbackName","tx","jobExecutionId","row","select","job","from","innerJoin","jobId","id","where","limit","name","key","getJobExecutionById","rows","jobExecution","undefined","getJobExecutionsByWorkflowRunAttemptId","workflowRunAttemptId","orderBy","sequence","map","getJobExecutionsByJobId","getFirstJobExecutionByJobId","getLatestJobExecutionByJobId","MAX_STATUS_REASON_MESSAGE_LENGTH","classifyJobOutputFailure","error","statusReason","statusReasonMessage","boundedStatusReasonMessage","message","field","length","slice","resolveJobExecutionOutputs","params","target","execution","attempt","run","workflowRunId","model","modelJob","find","outputs","executionRows","fallbackName","executions","status","stepRows","position","attemptRows","executionOrder","dependencyJobs","attempts","vars","workspaceId","projectId","definitionId","secrets","updateJobExecutionStatusAtVersion","includes","outputFailure","update","set","version","updatedAt","Date","markTimedOut","timedOutAt","finishedAt","expectedVersion","returning","changed","updateJobExecutionStatus","result","transaction","updateFn","fetchFn","matchFn","failureMessage","queueJobExecution","for","existing","queuedAt","requiredLabels","runner","Error","queued","recordJobExecutionStartedAt","updated","startedAt","failJobExecutionAsTimedOut","resolveJobExecutionAfterLeaseExpiry","jobExecutionSteps","changedJobExecution","every","step","statusReasonForStepCompletion","jobExecutionRow","executionVersion"],"mappings":"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"}
|
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import { type LogOutcomeDto } from '@shipfox/api-workflows-dto';
|
|
2
|
+
import type { JobStatusReason } from '#core/entities/job.js';
|
|
3
|
+
import type { JobExecutionStatus } from '#core/entities/job-execution.js';
|
|
2
4
|
import type { Tx } from '../db.js';
|
|
5
|
+
export declare function writeJobExecutionQueuedOutbox(tx: Tx, params: {
|
|
6
|
+
jobId: string;
|
|
7
|
+
jobExecutionId: string;
|
|
8
|
+
requiredLabels: string[];
|
|
9
|
+
queuedAt: Date;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
export declare function writeJobExecutionTerminatedOutbox(tx: Tx, params: {
|
|
12
|
+
jobId: string;
|
|
13
|
+
jobExecutionId: string;
|
|
14
|
+
status: JobExecutionStatus;
|
|
15
|
+
statusReason: JobStatusReason | null;
|
|
16
|
+
statusReasonMessage?: string | null | undefined;
|
|
17
|
+
}): Promise<void>;
|
|
3
18
|
export declare function writeJobStepsSettledOutbox(tx: Tx, params: {
|
|
4
19
|
jobId: string;
|
|
5
20
|
jobExecutionId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../../src/db/workflow-runs/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,
|
|
1
|
+
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../../src/db/workflow-runs/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,aAAa,EAMnB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,UAAU,CAAC;AAMjC,wBAAsB,6BAA6B,CACjD,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,IAAI,CAAC;CAChB,GACA,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,wBAAsB,iCAAiC,CACrD,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CACjD,GACA,OAAO,CAAC,IAAI,CAAC,CAsBf;AAMD,wBAAsB,0BAA0B,CAC9C,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAA;CAAC,GAC9E,OAAO,CAAC,IAAI,CAAC,CAaf;AAED,wBAAsB,gCAAgC,CACpD,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC7C,UAAU,EAAE,aAAa,CAAC;CAC3B,GACA,OAAO,CAAC,IAAI,CAAC,CAiBf;AA8BD,wBAAsB,8BAA8B,CAClD,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB,GACA,OAAO,CAAC,IAAI,CAAC,CAef"}
|
|
@@ -1,9 +1,43 @@
|
|
|
1
|
-
import { WORKFLOWS_JOB_STEPS_SETTLED, WORKFLOWS_STEP_ATTEMPT_TERMINATED, WORKFLOWS_STEP_RESTART_ENQUEUED } from '@shipfox/api-workflows-dto';
|
|
1
|
+
import { WORKFLOWS_JOB_EXECUTION_QUEUED, WORKFLOWS_JOB_EXECUTION_TERMINATED, WORKFLOWS_JOB_STEPS_SETTLED, WORKFLOWS_STEP_ATTEMPT_TERMINATED, WORKFLOWS_STEP_RESTART_ENQUEUED } from '@shipfox/api-workflows-dto';
|
|
2
2
|
import { eq } from 'drizzle-orm';
|
|
3
3
|
import { writeWorkflowsOutboxEvent } from '../outbox-writes.js';
|
|
4
4
|
import { jobExecutions } from '../schema/job-executions.js';
|
|
5
5
|
import { steps } from '../schema/steps.js';
|
|
6
6
|
import { getWorkflowContextForJob } from './shared.js';
|
|
7
|
+
export async function writeJobExecutionQueuedOutbox(tx, params) {
|
|
8
|
+
const identity = await getWorkflowContextForJob(params.jobId, tx);
|
|
9
|
+
await writeWorkflowsOutboxEvent(tx, {
|
|
10
|
+
type: WORKFLOWS_JOB_EXECUTION_QUEUED,
|
|
11
|
+
payload: {
|
|
12
|
+
jobId: params.jobId,
|
|
13
|
+
jobExecutionId: params.jobExecutionId,
|
|
14
|
+
workflowRunId: identity.workflowRunId,
|
|
15
|
+
workflowRunAttemptId: identity.workflowRunAttemptId,
|
|
16
|
+
workspaceId: identity.workspaceId,
|
|
17
|
+
projectId: identity.projectId,
|
|
18
|
+
requiredLabels: params.requiredLabels,
|
|
19
|
+
queuedAt: params.queuedAt.toISOString()
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
export async function writeJobExecutionTerminatedOutbox(tx, params) {
|
|
24
|
+
if (params.status !== 'succeeded' && params.status !== 'failed' && params.status !== 'cancelled') {
|
|
25
|
+
throw new Error(`Cannot enqueue terminal job execution event for status ${params.status}`);
|
|
26
|
+
}
|
|
27
|
+
const identity = await getWorkflowContextForJob(params.jobId, tx);
|
|
28
|
+
await writeWorkflowsOutboxEvent(tx, {
|
|
29
|
+
type: WORKFLOWS_JOB_EXECUTION_TERMINATED,
|
|
30
|
+
payload: {
|
|
31
|
+
jobId: params.jobId,
|
|
32
|
+
jobExecutionId: params.jobExecutionId,
|
|
33
|
+
workflowRunId: identity.workflowRunId,
|
|
34
|
+
workflowRunAttemptId: identity.workflowRunAttemptId,
|
|
35
|
+
status: params.status,
|
|
36
|
+
statusReason: params.statusReason,
|
|
37
|
+
statusReasonMessage: params.statusReasonMessage ?? null
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
7
41
|
// Enqueue the steps-settled signal in the same transaction as the final per-step
|
|
8
42
|
// result, so per-step execution observes it exactly once (the outbox is at-least-once;
|
|
9
43
|
// the job workflow dedupes the signal). Drives the Temporal JOB_FINISHED_SIGNAL; the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db/workflow-runs/outbox.ts"],"sourcesContent":["import {\n type LogOutcomeDto,\n WORKFLOWS_JOB_STEPS_SETTLED,\n WORKFLOWS_STEP_ATTEMPT_TERMINATED,\n WORKFLOWS_STEP_RESTART_ENQUEUED,\n} from '@shipfox/api-workflows-dto';\nimport {eq} from 'drizzle-orm';\nimport type {Tx} from '../db.js';\nimport {writeWorkflowsOutboxEvent} from '../outbox-writes.js';\nimport {jobExecutions} from '../schema/job-executions.js';\nimport {steps} from '../schema/steps.js';\nimport {getWorkflowContextForJob} from './shared.js';\n\n// Enqueue the steps-settled signal in the same transaction as the final per-step\n// result, so per-step execution observes it exactly once (the outbox is at-least-once;\n// the job workflow dedupes the signal). Drives the Temporal JOB_FINISHED_SIGNAL; the\n// job's terminal fact is emitted separately by updateJobStatusAtVersion.\nexport async function writeJobStepsSettledOutbox(\n tx: Tx,\n params: {jobId: string; jobExecutionId: string; status: 'succeeded' | 'failed'},\n): Promise<void> {\n const identity = await getWorkflowContextForJob(params.jobId, tx);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_JOB_STEPS_SETTLED,\n payload: {\n jobId: params.jobId,\n jobExecutionId: params.jobExecutionId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n status: params.status,\n },\n });\n}\n\nexport async function writeStepAttemptTerminatedOutbox(\n tx: Tx,\n params: {\n stepId: string;\n attempt: number;\n status: 'succeeded' | 'failed' | 'cancelled';\n logOutcome: LogOutcomeDto;\n },\n): Promise<void> {\n const identity = await getStepAttemptTerminatedOutboxIdentity(tx, params.stepId);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_STEP_ATTEMPT_TERMINATED,\n payload: {\n jobId: identity.jobId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n workspaceId: identity.workspaceId,\n projectId: identity.projectId,\n stepId: params.stepId,\n attempt: params.attempt,\n status: params.status,\n logOutcome: params.logOutcome,\n },\n });\n}\n\nasync function getStepAttemptTerminatedOutboxIdentity(\n tx: Tx,\n stepId: string,\n): Promise<{\n jobId: string;\n workflowRunId: string;\n workflowRunAttemptId: string;\n workspaceId: string;\n projectId: string;\n}> {\n const rows = await tx\n .select({\n jobId: jobExecutions.jobId,\n })\n .from(steps)\n .innerJoin(jobExecutions, eq(steps.jobExecutionId, jobExecutions.id))\n .where(eq(steps.id, stepId))\n .limit(1);\n const step = rows[0];\n if (!step) {\n throw new Error(`Cannot enqueue step-attempt-terminated event: step ${stepId} not found`);\n }\n\n return getWorkflowContextForJob(step.jobId, tx);\n}\n\n// Enqueue the durable audit record of a restart, in the same transaction as the\n// rewind. Looks up the workflow run id like writeJobStepsSettledOutbox.\nexport async function writeStepRestartEnqueuedOutbox(\n tx: Tx,\n params: {\n jobId: string;\n failedStepId: string;\n failedStepAttempt: number;\n restartFromStepId: string;\n feedback: string;\n },\n): Promise<void> {\n const identity = await getWorkflowContextForJob(params.jobId, tx);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_STEP_RESTART_ENQUEUED,\n payload: {\n jobId: params.jobId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n failedStepId: params.failedStepId,\n failedStepAttempt: params.failedStepAttempt,\n restartFromStepId: params.restartFromStepId,\n feedback: params.feedback,\n },\n });\n}\n"],"names":["WORKFLOWS_JOB_STEPS_SETTLED","WORKFLOWS_STEP_ATTEMPT_TERMINATED","WORKFLOWS_STEP_RESTART_ENQUEUED","eq","writeWorkflowsOutboxEvent","jobExecutions","steps","getWorkflowContextForJob","
|
|
1
|
+
{"version":3,"sources":["../../../src/db/workflow-runs/outbox.ts"],"sourcesContent":["import {\n type LogOutcomeDto,\n WORKFLOWS_JOB_EXECUTION_QUEUED,\n WORKFLOWS_JOB_EXECUTION_TERMINATED,\n WORKFLOWS_JOB_STEPS_SETTLED,\n WORKFLOWS_STEP_ATTEMPT_TERMINATED,\n WORKFLOWS_STEP_RESTART_ENQUEUED,\n} from '@shipfox/api-workflows-dto';\nimport {eq} from 'drizzle-orm';\nimport type {JobStatusReason} from '#core/entities/job.js';\nimport type {JobExecutionStatus} from '#core/entities/job-execution.js';\nimport type {Tx} from '../db.js';\nimport {writeWorkflowsOutboxEvent} from '../outbox-writes.js';\nimport {jobExecutions} from '../schema/job-executions.js';\nimport {steps} from '../schema/steps.js';\nimport {getWorkflowContextForJob} from './shared.js';\n\nexport async function writeJobExecutionQueuedOutbox(\n tx: Tx,\n params: {\n jobId: string;\n jobExecutionId: string;\n requiredLabels: string[];\n queuedAt: Date;\n },\n): Promise<void> {\n const identity = await getWorkflowContextForJob(params.jobId, tx);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_JOB_EXECUTION_QUEUED,\n payload: {\n jobId: params.jobId,\n jobExecutionId: params.jobExecutionId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n workspaceId: identity.workspaceId,\n projectId: identity.projectId,\n requiredLabels: params.requiredLabels,\n queuedAt: params.queuedAt.toISOString(),\n },\n });\n}\n\nexport async function writeJobExecutionTerminatedOutbox(\n tx: Tx,\n params: {\n jobId: string;\n jobExecutionId: string;\n status: JobExecutionStatus;\n statusReason: JobStatusReason | null;\n statusReasonMessage?: string | null | undefined;\n },\n): Promise<void> {\n if (\n params.status !== 'succeeded' &&\n params.status !== 'failed' &&\n params.status !== 'cancelled'\n ) {\n throw new Error(`Cannot enqueue terminal job execution event for status ${params.status}`);\n }\n const identity = await getWorkflowContextForJob(params.jobId, tx);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_JOB_EXECUTION_TERMINATED,\n payload: {\n jobId: params.jobId,\n jobExecutionId: params.jobExecutionId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n status: params.status,\n statusReason: params.statusReason,\n statusReasonMessage: params.statusReasonMessage ?? null,\n },\n });\n}\n\n// Enqueue the steps-settled signal in the same transaction as the final per-step\n// result, so per-step execution observes it exactly once (the outbox is at-least-once;\n// the job workflow dedupes the signal). Drives the Temporal JOB_FINISHED_SIGNAL; the\n// job's terminal fact is emitted separately by updateJobStatusAtVersion.\nexport async function writeJobStepsSettledOutbox(\n tx: Tx,\n params: {jobId: string; jobExecutionId: string; status: 'succeeded' | 'failed'},\n): Promise<void> {\n const identity = await getWorkflowContextForJob(params.jobId, tx);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_JOB_STEPS_SETTLED,\n payload: {\n jobId: params.jobId,\n jobExecutionId: params.jobExecutionId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n status: params.status,\n },\n });\n}\n\nexport async function writeStepAttemptTerminatedOutbox(\n tx: Tx,\n params: {\n stepId: string;\n attempt: number;\n status: 'succeeded' | 'failed' | 'cancelled';\n logOutcome: LogOutcomeDto;\n },\n): Promise<void> {\n const identity = await getStepAttemptTerminatedOutboxIdentity(tx, params.stepId);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_STEP_ATTEMPT_TERMINATED,\n payload: {\n jobId: identity.jobId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n workspaceId: identity.workspaceId,\n projectId: identity.projectId,\n stepId: params.stepId,\n attempt: params.attempt,\n status: params.status,\n logOutcome: params.logOutcome,\n },\n });\n}\n\nasync function getStepAttemptTerminatedOutboxIdentity(\n tx: Tx,\n stepId: string,\n): Promise<{\n jobId: string;\n workflowRunId: string;\n workflowRunAttemptId: string;\n workspaceId: string;\n projectId: string;\n}> {\n const rows = await tx\n .select({\n jobId: jobExecutions.jobId,\n })\n .from(steps)\n .innerJoin(jobExecutions, eq(steps.jobExecutionId, jobExecutions.id))\n .where(eq(steps.id, stepId))\n .limit(1);\n const step = rows[0];\n if (!step) {\n throw new Error(`Cannot enqueue step-attempt-terminated event: step ${stepId} not found`);\n }\n\n return getWorkflowContextForJob(step.jobId, tx);\n}\n\n// Enqueue the durable audit record of a restart, in the same transaction as the\n// rewind. Looks up the workflow run id like writeJobStepsSettledOutbox.\nexport async function writeStepRestartEnqueuedOutbox(\n tx: Tx,\n params: {\n jobId: string;\n failedStepId: string;\n failedStepAttempt: number;\n restartFromStepId: string;\n feedback: string;\n },\n): Promise<void> {\n const identity = await getWorkflowContextForJob(params.jobId, tx);\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_STEP_RESTART_ENQUEUED,\n payload: {\n jobId: params.jobId,\n workflowRunId: identity.workflowRunId,\n workflowRunAttemptId: identity.workflowRunAttemptId,\n failedStepId: params.failedStepId,\n failedStepAttempt: params.failedStepAttempt,\n restartFromStepId: params.restartFromStepId,\n feedback: params.feedback,\n },\n });\n}\n"],"names":["WORKFLOWS_JOB_EXECUTION_QUEUED","WORKFLOWS_JOB_EXECUTION_TERMINATED","WORKFLOWS_JOB_STEPS_SETTLED","WORKFLOWS_STEP_ATTEMPT_TERMINATED","WORKFLOWS_STEP_RESTART_ENQUEUED","eq","writeWorkflowsOutboxEvent","jobExecutions","steps","getWorkflowContextForJob","writeJobExecutionQueuedOutbox","tx","params","identity","jobId","type","payload","jobExecutionId","workflowRunId","workflowRunAttemptId","workspaceId","projectId","requiredLabels","queuedAt","toISOString","writeJobExecutionTerminatedOutbox","status","Error","statusReason","statusReasonMessage","writeJobStepsSettledOutbox","writeStepAttemptTerminatedOutbox","getStepAttemptTerminatedOutboxIdentity","stepId","attempt","logOutcome","rows","select","from","innerJoin","id","where","limit","step","writeStepRestartEnqueuedOutbox","failedStepId","failedStepAttempt","restartFromStepId","feedback"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-graph.d.ts","sourceRoot":"","sources":["../../../src/db/workflow-runs/run-graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAChE,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,UAAU,CAAC;AAEjC,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EAEpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAC,KAAK,WAAW,EAAE,KAAK,KAAK,EAAO,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAC,KAAK,YAAY,EAAQ,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-graph.d.ts","sourceRoot":"","sources":["../../../src/db/workflow-runs/run-graph.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAChE,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,UAAU,CAAC;AAEjC,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EAEpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAC,KAAK,WAAW,EAAE,KAAK,KAAK,EAAO,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAC,KAAK,YAAY,EAAQ,MAAM,oBAAoB,CAAC;AAG5D,KAAK,gCAAgC,GAAG,IAAI,CAAC,oBAAoB,EAAE,YAAY,GAAG,OAAO,CAAC,GAAG;IAC3F,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC,YAAY,CAAC,GAAG,GAAG,GAAG,SAAS,CAAC;CAC5E,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC;IACxD,QAAQ,CAAC,eAAe,CAAC,EACrB,CAAC,CAAC,GAAG,EAAE,KAAK,KAAK,gCAAgC,GAAG,SAAS,CAAC,GAC9D,SAAS,CAAC;IACd,QAAQ,CAAC,WAAW,CAAC,EACjB,CAAC,CAAC,MAAM,EAAE;QACR,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;QACpB,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;KACvC,KAAK,SAAS,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,EAAE,CAAC,GACtD,SAAS,CAAC;CACf;AAED,wBAAsB,2BAA2B,CAC/C,EAAE,EAAE,EAAE,EACN,MAAM,EAAE;IACN,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,GAAG,aAAa,GAAG,WAAW,GAAG,cAAc,CAAC,CAAC;IACrF,QAAQ,CAAC,kBAAkB,EAAE;QAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAC,CAAC;IAC7E,QAAQ,CAAC,gBAAgB,EAAE,SAAS,uBAAuB,EAAE,CAAC;CAC/D,GACA,OAAO,CAAC,IAAI,CAAC,CAyEf"}
|
|
@@ -3,6 +3,7 @@ import { writeWorkflowsOutboxEvent } from '../outbox-writes.js';
|
|
|
3
3
|
import { jobExecutions } from '../schema/job-executions.js';
|
|
4
4
|
import { jobs } from '../schema/jobs.js';
|
|
5
5
|
import { steps } from '../schema/steps.js';
|
|
6
|
+
import { writeJobExecutionTerminatedOutbox } from './outbox.js';
|
|
6
7
|
export async function persistMaterializedRunGraph(tx, params) {
|
|
7
8
|
const jobRows = params.materializedJobs.length === 0 ? [] : await tx.insert(jobs).values(params.materializedJobs.map((materializedJob)=>({
|
|
8
9
|
...materializedJob.job,
|
|
@@ -19,6 +20,17 @@ export async function persistMaterializedRunGraph(tx, params) {
|
|
|
19
20
|
];
|
|
20
21
|
});
|
|
21
22
|
const jobExecutionRows = jobExecutionValues.length === 0 ? [] : await tx.insert(jobExecutions).values(jobExecutionValues).returning();
|
|
23
|
+
for (const jobExecution of jobExecutionRows){
|
|
24
|
+
if (jobExecution.status === 'succeeded' || jobExecution.status === 'failed' || jobExecution.status === 'cancelled') {
|
|
25
|
+
await writeJobExecutionTerminatedOutbox(tx, {
|
|
26
|
+
jobId: jobExecution.jobId,
|
|
27
|
+
jobExecutionId: jobExecution.id,
|
|
28
|
+
status: jobExecution.status,
|
|
29
|
+
statusReason: jobExecution.statusReason,
|
|
30
|
+
statusReasonMessage: jobExecution.statusReasonMessage
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
22
34
|
const jobById = new Map(jobRows.map((job)=>[
|
|
23
35
|
job.id,
|
|
24
36
|
job
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db/workflow-runs/run-graph.ts"],"sourcesContent":["import {WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED} from '@shipfox/api-workflows-dto';\nimport type {SQL} from 'drizzle-orm';\nimport type {WorkflowRun} from '#core/entities/workflow-run.js';\nimport type {Tx} from '../db.js';\nimport {writeWorkflowsOutboxEvent} from '../outbox-writes.js';\nimport {\n type JobExecutionCreateDb,\n type JobExecutionDb,\n jobExecutions,\n} from '../schema/job-executions.js';\nimport {type JobCreateDb, type JobDb, jobs} from '../schema/jobs.js';\nimport {type StepCreateDb, steps} from '../schema/steps.js';\n\ntype MaterializedRunGraphJobExecution = Omit<JobExecutionCreateDb, 'finishedAt' | 'jobId'> & {\n readonly finishedAt?: JobExecutionCreateDb['finishedAt'] | SQL | undefined;\n};\n\nexport interface MaterializedRunGraphJob {\n readonly job: Omit<JobCreateDb, 'workflowRunAttemptId'>;\n readonly createExecution?:\n | ((job: JobDb) => MaterializedRunGraphJobExecution | undefined)\n | undefined;\n readonly createSteps?:\n | ((params: {\n readonly job: JobDb;\n readonly jobExecution: JobExecutionDb;\n }) => readonly Omit<StepCreateDb, 'jobExecutionId'>[])\n | undefined;\n}\n\nexport async function persistMaterializedRunGraph(\n tx: Tx,\n params: {\n readonly run: Pick<WorkflowRun, 'id' | 'workspaceId' | 'projectId' | 'definitionId'>;\n readonly workflowRunAttempt: {readonly id: string; readonly attempt: number};\n readonly materializedJobs: readonly MaterializedRunGraphJob[];\n },\n): Promise<void> {\n const jobRows =\n params.materializedJobs.length === 0\n ? []\n : await tx\n .insert(jobs)\n .values(\n params.materializedJobs.map((materializedJob) => ({\n ...materializedJob.job,\n workflowRunAttemptId: params.workflowRunAttempt.id,\n })),\n )\n .returning();\n\n const jobExecutionValues = jobRows.flatMap((jobRow, jobIndex) => {\n const materializedJob = params.materializedJobs[jobIndex];\n const jobExecution = materializedJob?.createExecution?.(jobRow);\n return jobExecution === undefined ? [] : [{...jobExecution, jobId: jobRow.id}];\n });\n const jobExecutionRows =\n jobExecutionValues.length === 0\n ? []\n : await tx.insert(jobExecutions).values(jobExecutionValues).returning();\n\n const jobById = new Map(jobRows.map((job) => [job.id, job]));\n const materializedJobByJobId = new Map(\n jobRows.flatMap((jobRow, index) => {\n const materializedJob = params.materializedJobs[index];\n return materializedJob === undefined ? [] : [[jobRow.id, materializedJob] as const];\n }),\n );\n const stepValues = jobExecutionRows.flatMap((jobExecution) => {\n const job = jobById.get(jobExecution.jobId);\n const materializedJob = materializedJobByJobId.get(jobExecution.jobId);\n if (!job || !materializedJob) return [];\n\n return (materializedJob.createSteps?.({job, jobExecution}) ?? []).map((step) => ({\n ...step,\n jobExecutionId: jobExecution.id,\n }));\n });\n\n if (stepValues.length > 0) {\n await tx.insert(steps).values(stepValues);\n }\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED,\n payload: {\n workflowRunId: params.run.id,\n workflowRunAttemptId: params.workflowRunAttempt.id,\n attempt: params.workflowRunAttempt.attempt,\n workspaceId: params.run.workspaceId,\n projectId: params.run.projectId,\n definitionId: params.run.definitionId,\n },\n });\n}\n"],"names":["WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED","writeWorkflowsOutboxEvent","jobExecutions","jobs","steps","persistMaterializedRunGraph","tx","params","jobRows","materializedJobs","length","insert","values","map","materializedJob","job","workflowRunAttemptId","workflowRunAttempt","id","returning","jobExecutionValues","flatMap","jobRow","jobIndex","jobExecution","createExecution","undefined","jobId","jobExecutionRows","jobById","Map","materializedJobByJobId","index","stepValues","get","createSteps","step","
|
|
1
|
+
{"version":3,"sources":["../../../src/db/workflow-runs/run-graph.ts"],"sourcesContent":["import {WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED} from '@shipfox/api-workflows-dto';\nimport type {SQL} from 'drizzle-orm';\nimport type {WorkflowRun} from '#core/entities/workflow-run.js';\nimport type {Tx} from '../db.js';\nimport {writeWorkflowsOutboxEvent} from '../outbox-writes.js';\nimport {\n type JobExecutionCreateDb,\n type JobExecutionDb,\n jobExecutions,\n} from '../schema/job-executions.js';\nimport {type JobCreateDb, type JobDb, jobs} from '../schema/jobs.js';\nimport {type StepCreateDb, steps} from '../schema/steps.js';\nimport {writeJobExecutionTerminatedOutbox} from './outbox.js';\n\ntype MaterializedRunGraphJobExecution = Omit<JobExecutionCreateDb, 'finishedAt' | 'jobId'> & {\n readonly finishedAt?: JobExecutionCreateDb['finishedAt'] | SQL | undefined;\n};\n\nexport interface MaterializedRunGraphJob {\n readonly job: Omit<JobCreateDb, 'workflowRunAttemptId'>;\n readonly createExecution?:\n | ((job: JobDb) => MaterializedRunGraphJobExecution | undefined)\n | undefined;\n readonly createSteps?:\n | ((params: {\n readonly job: JobDb;\n readonly jobExecution: JobExecutionDb;\n }) => readonly Omit<StepCreateDb, 'jobExecutionId'>[])\n | undefined;\n}\n\nexport async function persistMaterializedRunGraph(\n tx: Tx,\n params: {\n readonly run: Pick<WorkflowRun, 'id' | 'workspaceId' | 'projectId' | 'definitionId'>;\n readonly workflowRunAttempt: {readonly id: string; readonly attempt: number};\n readonly materializedJobs: readonly MaterializedRunGraphJob[];\n },\n): Promise<void> {\n const jobRows =\n params.materializedJobs.length === 0\n ? []\n : await tx\n .insert(jobs)\n .values(\n params.materializedJobs.map((materializedJob) => ({\n ...materializedJob.job,\n workflowRunAttemptId: params.workflowRunAttempt.id,\n })),\n )\n .returning();\n\n const jobExecutionValues = jobRows.flatMap((jobRow, jobIndex) => {\n const materializedJob = params.materializedJobs[jobIndex];\n const jobExecution = materializedJob?.createExecution?.(jobRow);\n return jobExecution === undefined ? [] : [{...jobExecution, jobId: jobRow.id}];\n });\n const jobExecutionRows =\n jobExecutionValues.length === 0\n ? []\n : await tx.insert(jobExecutions).values(jobExecutionValues).returning();\n\n for (const jobExecution of jobExecutionRows) {\n if (\n jobExecution.status === 'succeeded' ||\n jobExecution.status === 'failed' ||\n jobExecution.status === 'cancelled'\n ) {\n await writeJobExecutionTerminatedOutbox(tx, {\n jobId: jobExecution.jobId,\n jobExecutionId: jobExecution.id,\n status: jobExecution.status,\n statusReason: jobExecution.statusReason,\n statusReasonMessage: jobExecution.statusReasonMessage,\n });\n }\n }\n\n const jobById = new Map(jobRows.map((job) => [job.id, job]));\n const materializedJobByJobId = new Map(\n jobRows.flatMap((jobRow, index) => {\n const materializedJob = params.materializedJobs[index];\n return materializedJob === undefined ? [] : [[jobRow.id, materializedJob] as const];\n }),\n );\n const stepValues = jobExecutionRows.flatMap((jobExecution) => {\n const job = jobById.get(jobExecution.jobId);\n const materializedJob = materializedJobByJobId.get(jobExecution.jobId);\n if (!job || !materializedJob) return [];\n\n return (materializedJob.createSteps?.({job, jobExecution}) ?? []).map((step) => ({\n ...step,\n jobExecutionId: jobExecution.id,\n }));\n });\n\n if (stepValues.length > 0) {\n await tx.insert(steps).values(stepValues);\n }\n\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED,\n payload: {\n workflowRunId: params.run.id,\n workflowRunAttemptId: params.workflowRunAttempt.id,\n attempt: params.workflowRunAttempt.attempt,\n workspaceId: params.run.workspaceId,\n projectId: params.run.projectId,\n definitionId: params.run.definitionId,\n },\n });\n}\n"],"names":["WORKFLOWS_WORKFLOW_RUN_ATTEMPT_CREATED","writeWorkflowsOutboxEvent","jobExecutions","jobs","steps","writeJobExecutionTerminatedOutbox","persistMaterializedRunGraph","tx","params","jobRows","materializedJobs","length","insert","values","map","materializedJob","job","workflowRunAttemptId","workflowRunAttempt","id","returning","jobExecutionValues","flatMap","jobRow","jobIndex","jobExecution","createExecution","undefined","jobId","jobExecutionRows","status","jobExecutionId","statusReason","statusReasonMessage","jobById","Map","materializedJobByJobId","index","stepValues","get","createSteps","step","type","payload","workflowRunId","run","attempt","workspaceId","projectId","definitionId"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-status.d.ts","sourceRoot":"","sources":["../../../src/db/workflow-runs/run-status.ts"],"names":[],"mappings":"AAKA,OAAO,EAA0B,KAAK,eAAe,EAAC,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"run-status.d.ts","sourceRoot":"","sources":["../../../src/db/workflow-runs/run-status.ts"],"names":[],"mappings":"AAKA,OAAO,EAA0B,KAAK,eAAe,EAAC,MAAM,uBAAuB,CAAC;AACpF,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACvB,MAAM,gCAAgC,CAAC;AAmBxC,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,+BAA+B;IAC9C,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,OAAO,CAAC,iBAAiB,EAAE,QAAQ,GAAG,WAAW,CAAC,CAAC;IACnE,YAAY,EAAE,OAAO,CAAC,eAAe,EAAE,WAAW,GAAG,eAAe,CAAC,CAAC;IACtE,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAwJD,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAC,CA4C7F;AAED,MAAM,WAAW,6BAA6B;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,6BAA6B,GACpC,OAAO,CAAC,WAAW,CAAC,CAuHtB"}
|
|
@@ -12,6 +12,7 @@ import { steps } from '../schema/steps.js';
|
|
|
12
12
|
import { workflowRunAttempts } from '../schema/workflow-run-attempts.js';
|
|
13
13
|
import { toWorkflowRun, workflowRuns } from '../schema/workflow-runs.js';
|
|
14
14
|
import { updateJobStatusAtVersion } from './jobs.js';
|
|
15
|
+
import { writeJobExecutionTerminatedOutbox } from './outbox.js';
|
|
15
16
|
import { lockWorkflowRun, TERMINAL_EXECUTION_STATUSES, TERMINAL_WORKFLOW_RUN_STATUSES } from './shared.js';
|
|
16
17
|
import { bulkUpdateStepStatuses } from './steps.js';
|
|
17
18
|
/**
|
|
@@ -57,9 +58,20 @@ import { bulkUpdateStepStatuses } from './steps.js';
|
|
|
57
58
|
timedOutAt: sql`now()`
|
|
58
59
|
} : {}
|
|
59
60
|
}).where(and(eq(jobExecutions.jobId, jobRow.id), notInArray(jobExecutions.status, TERMINAL_EXECUTION_STATUSES))).returning({
|
|
60
|
-
id: jobExecutions.id
|
|
61
|
+
id: jobExecutions.id,
|
|
62
|
+
jobId: jobExecutions.jobId,
|
|
63
|
+
status: jobExecutions.status,
|
|
64
|
+
statusReason: jobExecutions.statusReason,
|
|
65
|
+
statusReasonMessage: jobExecutions.statusReasonMessage
|
|
61
66
|
});
|
|
62
67
|
for (const jobExecution of terminatedExecutions){
|
|
68
|
+
await writeJobExecutionTerminatedOutbox(tx, {
|
|
69
|
+
jobId: jobExecution.jobId,
|
|
70
|
+
jobExecutionId: jobExecution.id,
|
|
71
|
+
status: jobExecution.status,
|
|
72
|
+
statusReason: jobExecution.statusReason,
|
|
73
|
+
statusReasonMessage: jobExecution.statusReasonMessage
|
|
74
|
+
});
|
|
63
75
|
await bulkUpdateStepStatuses({
|
|
64
76
|
jobExecutionId: jobExecution.id,
|
|
65
77
|
status: spec.terminalStatus
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/db/workflow-runs/run-status.ts"],"sourcesContent":["import {\n WORKFLOWS_WORKFLOW_RUN_CANCELLED,\n WORKFLOWS_WORKFLOW_RUN_TERMINATED,\n} from '@shipfox/api-workflows-dto';\nimport {and, asc, eq, inArray, notInArray, sql} from 'drizzle-orm';\nimport {isJobTerminal, type Job, type JobStatusReason} from '#core/entities/job.js';\nimport {\n isWorkflowRunTerminal,\n type WorkflowRun,\n type WorkflowRunStatus,\n} from '#core/entities/workflow-run.js';\nimport {WorkflowRunNotCancellableError, WorkflowRunNotFoundError} from '#core/errors.js';\nimport {recordWorkflowJobStatusChanged, recordWorkflowRunStatusChanged} from '#metrics/instance.js';\nimport {db, type Tx} from '../db.js';\nimport {writeWorkflowsOutboxEvent} from '../outbox-writes.js';\nimport {jobExecutions} from '../schema/job-executions.js';\nimport {jobs} from '../schema/jobs.js';\nimport {steps} from '../schema/steps.js';\nimport {workflowRunAttempts} from '../schema/workflow-run-attempts.js';\nimport {toWorkflowRun, workflowRuns} from '../schema/workflow-runs.js';\nimport {updateJobStatusAtVersion} from './jobs.js';\nimport {\n lockWorkflowRun,\n TERMINAL_EXECUTION_STATUSES,\n TERMINAL_WORKFLOW_RUN_STATUSES,\n} from './shared.js';\nimport {bulkUpdateStepStatuses} from './steps.js';\n\nexport interface CancelWorkflowRunParams {\n workflowRunId: string;\n}\n\nexport interface FailWorkflowRunAsTimedOutParams {\n runAttemptId: string;\n}\n\nexport interface RunTerminationSpec {\n terminalStatus: Extract<WorkflowRunStatus, 'failed' | 'cancelled'>;\n statusReason: Extract<JobStatusReason, 'timed_out' | 'run_cancelled'>;\n markExecutionTimedOut: boolean;\n emitCancelledEvent: boolean;\n}\n\n/**\n * Shared terminal transition for a run attempt. The caller locks the run and the\n * attempt (and decides how an already-terminal run is handled: timeout returns\n * idempotently, cancellation rejects), then this drives every non-terminal job,\n * execution, and step to `spec.terminalStatus`, resolves still-listening jobs,\n * flips the attempt and run, and writes the outbox. Callers record metrics after\n * the transaction commits.\n */\nasync function terminateRunAttempt(\n tx: Tx,\n params: {\n lockedRun: typeof workflowRuns.$inferSelect;\n lockedAttempt: typeof workflowRunAttempts.$inferSelect;\n spec: RunTerminationSpec;\n },\n): Promise<{run: WorkflowRun; changedJobs: Job[]}> {\n const {lockedRun, lockedAttempt, spec} = params;\n\n const runJobExecutionIds = tx\n .select({id: jobExecutions.id})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobs.workflowRunAttemptId, lockedAttempt.id));\n\n await tx\n .select({id: steps.id})\n .from(steps)\n .where(inArray(steps.jobExecutionId, runJobExecutionIds))\n .orderBy(asc(steps.jobExecutionId), asc(steps.position))\n .for('update');\n\n const jobRows = await tx\n .select()\n .from(jobs)\n .where(eq(jobs.workflowRunAttemptId, lockedAttempt.id))\n .orderBy(asc(jobs.position), asc(jobs.id))\n .for('update');\n\n const changedJobs: Job[] = [];\n for (const jobRow of jobRows) {\n if (isJobTerminal(jobRow.status)) continue;\n\n const updated = await updateJobStatusAtVersion(tx, {\n jobId: jobRow.id,\n status: spec.terminalStatus,\n expectedVersion: jobRow.version,\n statusReason: spec.statusReason,\n });\n if (updated?.changed) changedJobs.push(updated.job);\n\n if (jobRow.mode === 'listening') {\n await tx\n .update(jobs)\n .set({listenerStatus: 'resolved', resolutionReason: 'cancelled', updatedAt: new Date()})\n .where(eq(jobs.id, jobRow.id));\n }\n\n const terminatedExecutions = await tx\n .update(jobExecutions)\n .set({\n status: spec.terminalStatus,\n statusReason: spec.statusReason,\n version: sql`${jobExecutions.version} + 1`,\n updatedAt: new Date(),\n finishedAt: sql`now()`,\n ...(spec.markExecutionTimedOut ? {timedOutAt: sql`now()`} : {}),\n })\n .where(\n and(\n eq(jobExecutions.jobId, jobRow.id),\n notInArray(jobExecutions.status, TERMINAL_EXECUTION_STATUSES),\n ),\n )\n .returning({id: jobExecutions.id});\n for (const jobExecution of terminatedExecutions) {\n await bulkUpdateStepStatuses(\n {jobExecutionId: jobExecution.id, status: spec.terminalStatus},\n tx,\n );\n }\n }\n\n await tx\n .update(workflowRunAttempts)\n .set({\n status: spec.terminalStatus,\n version: sql`${workflowRunAttempts.version} + 1`,\n updatedAt: new Date(),\n finishedAt: sql`now()`,\n })\n .where(\n and(\n eq(workflowRunAttempts.id, lockedAttempt.id),\n notInArray(workflowRunAttempts.status, TERMINAL_WORKFLOW_RUN_STATUSES),\n ),\n );\n\n const [terminatedRunRow] = await tx\n .update(workflowRuns)\n .set({\n status: spec.terminalStatus,\n version: sql`${workflowRuns.version} + 1`,\n updatedAt: new Date(),\n finishedAt: sql`now()`,\n })\n .where(\n and(\n eq(workflowRuns.id, lockedRun.id),\n notInArray(workflowRuns.status, TERMINAL_WORKFLOW_RUN_STATUSES),\n ),\n )\n .returning();\n\n const run = toWorkflowRun(terminatedRunRow ?? lockedRun);\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_TERMINATED,\n payload: {\n workflowRunId: run.id,\n workflowRunAttemptId: lockedAttempt.id,\n projectId: run.projectId,\n status: spec.terminalStatus,\n },\n });\n if (spec.emitCancelledEvent) {\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_CANCELLED,\n payload: {\n workflowRunId: run.id,\n workflowRunAttemptId: lockedAttempt.id,\n projectId: run.projectId,\n },\n });\n }\n\n return {run, changedJobs};\n}\n\nexport async function failWorkflowRunAsTimedOut(\n params: FailWorkflowRunAsTimedOutParams,\n): Promise<WorkflowRun> {\n const result = await db().transaction(async (tx) => {\n const [lockedAttempt] = await tx\n .select()\n .from(workflowRunAttempts)\n .where(eq(workflowRunAttempts.id, params.runAttemptId))\n .limit(1)\n .for('update');\n if (!lockedAttempt) throw new WorkflowRunNotFoundError(params.runAttemptId);\n\n const lockedRun = await lockWorkflowRun(lockedAttempt.workflowRunId, tx);\n if (!lockedRun) throw new WorkflowRunNotFoundError(lockedAttempt.workflowRunId);\n if (isWorkflowRunTerminal(lockedRun.status)) {\n return {run: toWorkflowRun(lockedRun), changedJobs: [], changed: false};\n }\n\n const result = await terminateRunAttempt(tx, {\n lockedRun,\n lockedAttempt,\n spec: {\n terminalStatus: 'failed',\n statusReason: 'timed_out',\n markExecutionTimedOut: true,\n emitCancelledEvent: false,\n },\n });\n return {...result, changed: true};\n });\n\n if (result.changed) recordWorkflowRunStatusChanged(result.run.status);\n for (const job of result.changedJobs) recordWorkflowJobStatusChanged(job.status);\n return result.run;\n}\n\nexport async function cancelWorkflowRun(params: CancelWorkflowRunParams): Promise<WorkflowRun> {\n const result = await db().transaction(async (tx) => {\n const lockedRun = await lockWorkflowRun(params.workflowRunId, tx);\n\n if (!lockedRun) {\n throw new WorkflowRunNotFoundError(params.workflowRunId);\n }\n if (isWorkflowRunTerminal(lockedRun.status)) {\n throw new WorkflowRunNotCancellableError(lockedRun.id, lockedRun.status);\n }\n\n const [lockedAttempt] = await tx\n .select()\n .from(workflowRunAttempts)\n .where(\n and(\n eq(workflowRunAttempts.workflowRunId, lockedRun.id),\n eq(workflowRunAttempts.attempt, lockedRun.currentAttempt),\n ),\n )\n .limit(1)\n .for('update');\n if (!lockedAttempt) {\n throw new Error(\n `Current attempt ${lockedRun.currentAttempt} missing for run ${lockedRun.id}`,\n );\n }\n\n return terminateRunAttempt(tx, {\n lockedRun,\n lockedAttempt,\n spec: {\n terminalStatus: 'cancelled',\n statusReason: 'run_cancelled',\n markExecutionTimedOut: false,\n emitCancelledEvent: true,\n },\n });\n });\n\n recordWorkflowRunStatusChanged(result.run.status);\n for (const job of result.changedJobs) recordWorkflowJobStatusChanged(job.status);\n\n return result.run;\n}\n\nexport interface UpdateWorkflowRunStatusParams {\n workflowRunId?: string;\n workflowRunAttemptId?: string;\n status: WorkflowRunStatus;\n expectedVersion: number;\n}\n\nexport async function updateWorkflowRunStatus(\n params: UpdateWorkflowRunStatusParams,\n): Promise<WorkflowRun> {\n const result = await db().transaction(async (tx) => {\n const [attemptRef] = params.workflowRunAttemptId\n ? await tx\n .select({\n id: workflowRunAttempts.id,\n workflowRunId: workflowRunAttempts.workflowRunId,\n })\n .from(workflowRunAttempts)\n .where(eq(workflowRunAttempts.id, params.workflowRunAttemptId))\n .limit(1)\n : [];\n\n const workflowRunId = attemptRef?.workflowRunId ?? params.workflowRunId ?? '';\n const lockedRun = await lockWorkflowRun(workflowRunId, tx);\n\n if (!lockedRun) {\n throw new WorkflowRunNotFoundError(params.workflowRunId ?? params.workflowRunAttemptId ?? '');\n }\n\n const [lockedAttempt] = await tx\n .select()\n .from(workflowRunAttempts)\n .where(\n params.workflowRunAttemptId\n ? eq(workflowRunAttempts.id, params.workflowRunAttemptId)\n : and(\n eq(workflowRunAttempts.workflowRunId, lockedRun.id),\n eq(workflowRunAttempts.attempt, lockedRun.currentAttempt),\n ),\n )\n .limit(1)\n .for('update');\n\n if (!lockedAttempt) {\n throw new WorkflowRunNotFoundError(params.workflowRunId ?? params.workflowRunAttemptId ?? '');\n }\n\n const target = {run: lockedRun, attempt: lockedAttempt};\n\n const rows = await tx\n .update(workflowRunAttempts)\n .set({\n status: params.status,\n version: sql`${workflowRunAttempts.version} + 1`,\n updatedAt: new Date(),\n ...(params.status === 'running'\n ? {startedAt: sql`coalesce(${workflowRunAttempts.startedAt}, now())`}\n : {}),\n ...(isWorkflowRunTerminal(params.status) ? {finishedAt: sql`now()`} : {}),\n })\n .where(\n and(\n eq(workflowRunAttempts.id, target.attempt.id),\n eq(workflowRunAttempts.version, params.expectedVersion),\n notInArray(workflowRunAttempts.status, TERMINAL_WORKFLOW_RUN_STATUSES),\n ),\n )\n .returning();\n\n const attemptRow = rows[0];\n if (!attemptRow) {\n const existing = await tx\n .select()\n .from(workflowRunAttempts)\n .where(eq(workflowRunAttempts.id, target.attempt.id))\n .limit(1);\n const existingRow = existing[0];\n if (\n existingRow &&\n (existingRow.status === params.status || isWorkflowRunTerminal(existingRow.status))\n ) {\n return {\n run: {...toWorkflowRun(target.run), version: existingRow.version},\n changed: false,\n };\n }\n throw new Error(\n `Optimistic lock failure: run attempt ${target.attempt.id} version ${params.expectedVersion}`,\n );\n }\n\n const shouldMirror = target.run.currentAttempt === attemptRow.attempt;\n const [runRow] = shouldMirror\n ? await tx\n .update(workflowRuns)\n .set({\n status: params.status,\n version: sql`${workflowRuns.version} + 1`,\n updatedAt: new Date(),\n ...(params.status === 'running'\n ? {startedAt: sql`coalesce(${workflowRuns.startedAt}, now())`}\n : {}),\n ...(isWorkflowRunTerminal(params.status) ? {finishedAt: sql`now()`} : {}),\n })\n .where(eq(workflowRuns.id, target.run.id))\n .returning()\n : [target.run];\n\n const run = {...toWorkflowRun(runRow ?? target.run), version: attemptRow.version};\n\n if (shouldMirror && isWorkflowRunTerminal(run.status)) {\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_TERMINATED,\n payload: {\n workflowRunId: run.id,\n workflowRunAttemptId: attemptRow.id,\n projectId: run.projectId,\n status: run.status,\n },\n });\n }\n\n return {run, changed: true};\n });\n\n if (result.changed) recordWorkflowRunStatusChanged(result.run.status);\n\n return result.run;\n}\n"],"names":["WORKFLOWS_WORKFLOW_RUN_CANCELLED","WORKFLOWS_WORKFLOW_RUN_TERMINATED","and","asc","eq","inArray","notInArray","sql","isJobTerminal","isWorkflowRunTerminal","WorkflowRunNotCancellableError","WorkflowRunNotFoundError","recordWorkflowJobStatusChanged","recordWorkflowRunStatusChanged","db","writeWorkflowsOutboxEvent","jobExecutions","jobs","steps","workflowRunAttempts","toWorkflowRun","workflowRuns","updateJobStatusAtVersion","lockWorkflowRun","TERMINAL_EXECUTION_STATUSES","TERMINAL_WORKFLOW_RUN_STATUSES","bulkUpdateStepStatuses","terminateRunAttempt","tx","params","lockedRun","lockedAttempt","spec","runJobExecutionIds","select","id","from","innerJoin","jobId","where","workflowRunAttemptId","jobExecutionId","orderBy","position","for","jobRows","changedJobs","jobRow","status","updated","terminalStatus","expectedVersion","version","statusReason","changed","push","job","mode","update","set","listenerStatus","resolutionReason","updatedAt","Date","terminatedExecutions","finishedAt","markExecutionTimedOut","timedOutAt","returning","jobExecution","terminatedRunRow","run","type","payload","workflowRunId","projectId","emitCancelledEvent","failWorkflowRunAsTimedOut","result","transaction","runAttemptId","limit","cancelWorkflowRun","attempt","currentAttempt","Error","updateWorkflowRunStatus","attemptRef","target","rows","startedAt","attemptRow","existing","existingRow","shouldMirror","runRow"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/db/workflow-runs/run-status.ts"],"sourcesContent":["import {\n WORKFLOWS_WORKFLOW_RUN_CANCELLED,\n WORKFLOWS_WORKFLOW_RUN_TERMINATED,\n} from '@shipfox/api-workflows-dto';\nimport {and, asc, eq, inArray, notInArray, sql} from 'drizzle-orm';\nimport {isJobTerminal, type Job, type JobStatusReason} from '#core/entities/job.js';\nimport {\n isWorkflowRunTerminal,\n type WorkflowRun,\n type WorkflowRunStatus,\n} from '#core/entities/workflow-run.js';\nimport {WorkflowRunNotCancellableError, WorkflowRunNotFoundError} from '#core/errors.js';\nimport {recordWorkflowJobStatusChanged, recordWorkflowRunStatusChanged} from '#metrics/instance.js';\nimport {db, type Tx} from '../db.js';\nimport {writeWorkflowsOutboxEvent} from '../outbox-writes.js';\nimport {jobExecutions} from '../schema/job-executions.js';\nimport {jobs} from '../schema/jobs.js';\nimport {steps} from '../schema/steps.js';\nimport {workflowRunAttempts} from '../schema/workflow-run-attempts.js';\nimport {toWorkflowRun, workflowRuns} from '../schema/workflow-runs.js';\nimport {updateJobStatusAtVersion} from './jobs.js';\nimport {writeJobExecutionTerminatedOutbox} from './outbox.js';\nimport {\n lockWorkflowRun,\n TERMINAL_EXECUTION_STATUSES,\n TERMINAL_WORKFLOW_RUN_STATUSES,\n} from './shared.js';\nimport {bulkUpdateStepStatuses} from './steps.js';\n\nexport interface CancelWorkflowRunParams {\n workflowRunId: string;\n}\n\nexport interface FailWorkflowRunAsTimedOutParams {\n runAttemptId: string;\n}\n\nexport interface RunTerminationSpec {\n terminalStatus: Extract<WorkflowRunStatus, 'failed' | 'cancelled'>;\n statusReason: Extract<JobStatusReason, 'timed_out' | 'run_cancelled'>;\n markExecutionTimedOut: boolean;\n emitCancelledEvent: boolean;\n}\n\n/**\n * Shared terminal transition for a run attempt. The caller locks the run and the\n * attempt (and decides how an already-terminal run is handled: timeout returns\n * idempotently, cancellation rejects), then this drives every non-terminal job,\n * execution, and step to `spec.terminalStatus`, resolves still-listening jobs,\n * flips the attempt and run, and writes the outbox. Callers record metrics after\n * the transaction commits.\n */\nasync function terminateRunAttempt(\n tx: Tx,\n params: {\n lockedRun: typeof workflowRuns.$inferSelect;\n lockedAttempt: typeof workflowRunAttempts.$inferSelect;\n spec: RunTerminationSpec;\n },\n): Promise<{run: WorkflowRun; changedJobs: Job[]}> {\n const {lockedRun, lockedAttempt, spec} = params;\n\n const runJobExecutionIds = tx\n .select({id: jobExecutions.id})\n .from(jobExecutions)\n .innerJoin(jobs, eq(jobExecutions.jobId, jobs.id))\n .where(eq(jobs.workflowRunAttemptId, lockedAttempt.id));\n\n await tx\n .select({id: steps.id})\n .from(steps)\n .where(inArray(steps.jobExecutionId, runJobExecutionIds))\n .orderBy(asc(steps.jobExecutionId), asc(steps.position))\n .for('update');\n\n const jobRows = await tx\n .select()\n .from(jobs)\n .where(eq(jobs.workflowRunAttemptId, lockedAttempt.id))\n .orderBy(asc(jobs.position), asc(jobs.id))\n .for('update');\n\n const changedJobs: Job[] = [];\n for (const jobRow of jobRows) {\n if (isJobTerminal(jobRow.status)) continue;\n\n const updated = await updateJobStatusAtVersion(tx, {\n jobId: jobRow.id,\n status: spec.terminalStatus,\n expectedVersion: jobRow.version,\n statusReason: spec.statusReason,\n });\n if (updated?.changed) changedJobs.push(updated.job);\n\n if (jobRow.mode === 'listening') {\n await tx\n .update(jobs)\n .set({listenerStatus: 'resolved', resolutionReason: 'cancelled', updatedAt: new Date()})\n .where(eq(jobs.id, jobRow.id));\n }\n\n const terminatedExecutions = await tx\n .update(jobExecutions)\n .set({\n status: spec.terminalStatus,\n statusReason: spec.statusReason,\n version: sql`${jobExecutions.version} + 1`,\n updatedAt: new Date(),\n finishedAt: sql`now()`,\n ...(spec.markExecutionTimedOut ? {timedOutAt: sql`now()`} : {}),\n })\n .where(\n and(\n eq(jobExecutions.jobId, jobRow.id),\n notInArray(jobExecutions.status, TERMINAL_EXECUTION_STATUSES),\n ),\n )\n .returning({\n id: jobExecutions.id,\n jobId: jobExecutions.jobId,\n status: jobExecutions.status,\n statusReason: jobExecutions.statusReason,\n statusReasonMessage: jobExecutions.statusReasonMessage,\n });\n for (const jobExecution of terminatedExecutions) {\n await writeJobExecutionTerminatedOutbox(tx, {\n jobId: jobExecution.jobId,\n jobExecutionId: jobExecution.id,\n status: jobExecution.status,\n statusReason: jobExecution.statusReason,\n statusReasonMessage: jobExecution.statusReasonMessage,\n });\n await bulkUpdateStepStatuses(\n {jobExecutionId: jobExecution.id, status: spec.terminalStatus},\n tx,\n );\n }\n }\n\n await tx\n .update(workflowRunAttempts)\n .set({\n status: spec.terminalStatus,\n version: sql`${workflowRunAttempts.version} + 1`,\n updatedAt: new Date(),\n finishedAt: sql`now()`,\n })\n .where(\n and(\n eq(workflowRunAttempts.id, lockedAttempt.id),\n notInArray(workflowRunAttempts.status, TERMINAL_WORKFLOW_RUN_STATUSES),\n ),\n );\n\n const [terminatedRunRow] = await tx\n .update(workflowRuns)\n .set({\n status: spec.terminalStatus,\n version: sql`${workflowRuns.version} + 1`,\n updatedAt: new Date(),\n finishedAt: sql`now()`,\n })\n .where(\n and(\n eq(workflowRuns.id, lockedRun.id),\n notInArray(workflowRuns.status, TERMINAL_WORKFLOW_RUN_STATUSES),\n ),\n )\n .returning();\n\n const run = toWorkflowRun(terminatedRunRow ?? lockedRun);\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_TERMINATED,\n payload: {\n workflowRunId: run.id,\n workflowRunAttemptId: lockedAttempt.id,\n projectId: run.projectId,\n status: spec.terminalStatus,\n },\n });\n if (spec.emitCancelledEvent) {\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_CANCELLED,\n payload: {\n workflowRunId: run.id,\n workflowRunAttemptId: lockedAttempt.id,\n projectId: run.projectId,\n },\n });\n }\n\n return {run, changedJobs};\n}\n\nexport async function failWorkflowRunAsTimedOut(\n params: FailWorkflowRunAsTimedOutParams,\n): Promise<WorkflowRun> {\n const result = await db().transaction(async (tx) => {\n const [lockedAttempt] = await tx\n .select()\n .from(workflowRunAttempts)\n .where(eq(workflowRunAttempts.id, params.runAttemptId))\n .limit(1)\n .for('update');\n if (!lockedAttempt) throw new WorkflowRunNotFoundError(params.runAttemptId);\n\n const lockedRun = await lockWorkflowRun(lockedAttempt.workflowRunId, tx);\n if (!lockedRun) throw new WorkflowRunNotFoundError(lockedAttempt.workflowRunId);\n if (isWorkflowRunTerminal(lockedRun.status)) {\n return {run: toWorkflowRun(lockedRun), changedJobs: [], changed: false};\n }\n\n const result = await terminateRunAttempt(tx, {\n lockedRun,\n lockedAttempt,\n spec: {\n terminalStatus: 'failed',\n statusReason: 'timed_out',\n markExecutionTimedOut: true,\n emitCancelledEvent: false,\n },\n });\n return {...result, changed: true};\n });\n\n if (result.changed) recordWorkflowRunStatusChanged(result.run.status);\n for (const job of result.changedJobs) recordWorkflowJobStatusChanged(job.status);\n return result.run;\n}\n\nexport async function cancelWorkflowRun(params: CancelWorkflowRunParams): Promise<WorkflowRun> {\n const result = await db().transaction(async (tx) => {\n const lockedRun = await lockWorkflowRun(params.workflowRunId, tx);\n\n if (!lockedRun) {\n throw new WorkflowRunNotFoundError(params.workflowRunId);\n }\n if (isWorkflowRunTerminal(lockedRun.status)) {\n throw new WorkflowRunNotCancellableError(lockedRun.id, lockedRun.status);\n }\n\n const [lockedAttempt] = await tx\n .select()\n .from(workflowRunAttempts)\n .where(\n and(\n eq(workflowRunAttempts.workflowRunId, lockedRun.id),\n eq(workflowRunAttempts.attempt, lockedRun.currentAttempt),\n ),\n )\n .limit(1)\n .for('update');\n if (!lockedAttempt) {\n throw new Error(\n `Current attempt ${lockedRun.currentAttempt} missing for run ${lockedRun.id}`,\n );\n }\n\n return terminateRunAttempt(tx, {\n lockedRun,\n lockedAttempt,\n spec: {\n terminalStatus: 'cancelled',\n statusReason: 'run_cancelled',\n markExecutionTimedOut: false,\n emitCancelledEvent: true,\n },\n });\n });\n\n recordWorkflowRunStatusChanged(result.run.status);\n for (const job of result.changedJobs) recordWorkflowJobStatusChanged(job.status);\n\n return result.run;\n}\n\nexport interface UpdateWorkflowRunStatusParams {\n workflowRunId?: string;\n workflowRunAttemptId?: string;\n status: WorkflowRunStatus;\n expectedVersion: number;\n}\n\nexport async function updateWorkflowRunStatus(\n params: UpdateWorkflowRunStatusParams,\n): Promise<WorkflowRun> {\n const result = await db().transaction(async (tx) => {\n const [attemptRef] = params.workflowRunAttemptId\n ? await tx\n .select({\n id: workflowRunAttempts.id,\n workflowRunId: workflowRunAttempts.workflowRunId,\n })\n .from(workflowRunAttempts)\n .where(eq(workflowRunAttempts.id, params.workflowRunAttemptId))\n .limit(1)\n : [];\n\n const workflowRunId = attemptRef?.workflowRunId ?? params.workflowRunId ?? '';\n const lockedRun = await lockWorkflowRun(workflowRunId, tx);\n\n if (!lockedRun) {\n throw new WorkflowRunNotFoundError(params.workflowRunId ?? params.workflowRunAttemptId ?? '');\n }\n\n const [lockedAttempt] = await tx\n .select()\n .from(workflowRunAttempts)\n .where(\n params.workflowRunAttemptId\n ? eq(workflowRunAttempts.id, params.workflowRunAttemptId)\n : and(\n eq(workflowRunAttempts.workflowRunId, lockedRun.id),\n eq(workflowRunAttempts.attempt, lockedRun.currentAttempt),\n ),\n )\n .limit(1)\n .for('update');\n\n if (!lockedAttempt) {\n throw new WorkflowRunNotFoundError(params.workflowRunId ?? params.workflowRunAttemptId ?? '');\n }\n\n const target = {run: lockedRun, attempt: lockedAttempt};\n\n const rows = await tx\n .update(workflowRunAttempts)\n .set({\n status: params.status,\n version: sql`${workflowRunAttempts.version} + 1`,\n updatedAt: new Date(),\n ...(params.status === 'running'\n ? {startedAt: sql`coalesce(${workflowRunAttempts.startedAt}, now())`}\n : {}),\n ...(isWorkflowRunTerminal(params.status) ? {finishedAt: sql`now()`} : {}),\n })\n .where(\n and(\n eq(workflowRunAttempts.id, target.attempt.id),\n eq(workflowRunAttempts.version, params.expectedVersion),\n notInArray(workflowRunAttempts.status, TERMINAL_WORKFLOW_RUN_STATUSES),\n ),\n )\n .returning();\n\n const attemptRow = rows[0];\n if (!attemptRow) {\n const existing = await tx\n .select()\n .from(workflowRunAttempts)\n .where(eq(workflowRunAttempts.id, target.attempt.id))\n .limit(1);\n const existingRow = existing[0];\n if (\n existingRow &&\n (existingRow.status === params.status || isWorkflowRunTerminal(existingRow.status))\n ) {\n return {\n run: {...toWorkflowRun(target.run), version: existingRow.version},\n changed: false,\n };\n }\n throw new Error(\n `Optimistic lock failure: run attempt ${target.attempt.id} version ${params.expectedVersion}`,\n );\n }\n\n const shouldMirror = target.run.currentAttempt === attemptRow.attempt;\n const [runRow] = shouldMirror\n ? await tx\n .update(workflowRuns)\n .set({\n status: params.status,\n version: sql`${workflowRuns.version} + 1`,\n updatedAt: new Date(),\n ...(params.status === 'running'\n ? {startedAt: sql`coalesce(${workflowRuns.startedAt}, now())`}\n : {}),\n ...(isWorkflowRunTerminal(params.status) ? {finishedAt: sql`now()`} : {}),\n })\n .where(eq(workflowRuns.id, target.run.id))\n .returning()\n : [target.run];\n\n const run = {...toWorkflowRun(runRow ?? target.run), version: attemptRow.version};\n\n if (shouldMirror && isWorkflowRunTerminal(run.status)) {\n await writeWorkflowsOutboxEvent(tx, {\n type: WORKFLOWS_WORKFLOW_RUN_TERMINATED,\n payload: {\n workflowRunId: run.id,\n workflowRunAttemptId: attemptRow.id,\n projectId: run.projectId,\n status: run.status,\n },\n });\n }\n\n return {run, changed: true};\n });\n\n if (result.changed) recordWorkflowRunStatusChanged(result.run.status);\n\n return result.run;\n}\n"],"names":["WORKFLOWS_WORKFLOW_RUN_CANCELLED","WORKFLOWS_WORKFLOW_RUN_TERMINATED","and","asc","eq","inArray","notInArray","sql","isJobTerminal","isWorkflowRunTerminal","WorkflowRunNotCancellableError","WorkflowRunNotFoundError","recordWorkflowJobStatusChanged","recordWorkflowRunStatusChanged","db","writeWorkflowsOutboxEvent","jobExecutions","jobs","steps","workflowRunAttempts","toWorkflowRun","workflowRuns","updateJobStatusAtVersion","writeJobExecutionTerminatedOutbox","lockWorkflowRun","TERMINAL_EXECUTION_STATUSES","TERMINAL_WORKFLOW_RUN_STATUSES","bulkUpdateStepStatuses","terminateRunAttempt","tx","params","lockedRun","lockedAttempt","spec","runJobExecutionIds","select","id","from","innerJoin","jobId","where","workflowRunAttemptId","jobExecutionId","orderBy","position","for","jobRows","changedJobs","jobRow","status","updated","terminalStatus","expectedVersion","version","statusReason","changed","push","job","mode","update","set","listenerStatus","resolutionReason","updatedAt","Date","terminatedExecutions","finishedAt","markExecutionTimedOut","timedOutAt","returning","statusReasonMessage","jobExecution","terminatedRunRow","run","type","payload","workflowRunId","projectId","emitCancelledEvent","failWorkflowRunAsTimedOut","result","transaction","runAttemptId","limit","cancelWorkflowRun","attempt","currentAttempt","Error","updateWorkflowRunStatus","attemptRef","target","rows","startedAt","attemptRow","existing","existingRow","shouldMirror","runRow"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type { UpdateJobExecutionStatusAtVersionParams, UpdateJobExecutionStatusParams, } from './workflow-runs/job-executions.js';
|
|
2
|
-
export { failJobExecutionAsTimedOut, getFirstJobExecutionByJobId, getJobExecutionById, getJobExecutionsByJobId, getJobExecutionsByWorkflowRunAttemptId, getLatestJobExecutionByJobId,
|
|
2
|
+
export { failJobExecutionAsTimedOut, getFirstJobExecutionByJobId, getJobExecutionById, getJobExecutionsByJobId, getJobExecutionsByWorkflowRunAttemptId, getLatestJobExecutionByJobId, queueJobExecution, recordJobExecutionStartedAt, resolveJobExecutionAfterLeaseExpiry, updateJobExecutionStatus, } from './workflow-runs/job-executions.js';
|
|
3
3
|
export type { EvaluateJobActivationsParams, EvaluateJobSuccessResult, JobActivationDecision, JobScope, UpdateJobStatusAtVersionParams, UpdateJobStatusParams, } from './workflow-runs/jobs.js';
|
|
4
4
|
export { evaluateJobActivations, evaluateJobSuccess, getDirectDependencyJobContexts, getJobById, getJobScope, getJobsByWorkflowRunAttemptId, getJobsByWorkflowRunId, resolveJobStatusFromJobExecutions, updateJobStatus, updateJobStatusAtVersion, } from './workflow-runs/jobs.js';
|
|
5
|
-
export { writeJobStepsSettledOutbox, writeStepAttemptTerminatedOutbox, writeStepRestartEnqueuedOutbox, } from './workflow-runs/outbox.js';
|
|
5
|
+
export { writeJobExecutionQueuedOutbox, writeJobExecutionTerminatedOutbox, writeJobStepsSettledOutbox, writeStepAttemptTerminatedOutbox, writeStepRestartEnqueuedOutbox, } from './workflow-runs/outbox.js';
|
|
6
6
|
export type { ListWorkflowRunsParams, ListWorkflowRunsResult, WorkflowJobExecutionDepth, WorkflowJobExecutionDepthParams, WorkflowRunAggregates, WorkflowRunCursor, WorkflowRunFilters, WorkflowRunJobRawStatusCount, WorkflowRunJobStatusCount, WorkflowRunJobSummary, WorkflowRunJobSummaryTarget, WorkflowRunJobsSummary, } from './workflow-runs/queries.js';
|
|
7
7
|
export { buildWorkflowRunListConditions, getJobExecutionDetail, getLatestAttempt, getWorkflowJobExecutionDepth, getWorkflowRunAggregates, getWorkflowRunAttemptById, getWorkflowRunByAttemptId, getWorkflowRunById, getWorkflowRunDetail, listRunAttempts, listWorkflowRunJobSummaries, listWorkflowRuns, listWorkflowRunsByProject, } from './workflow-runs/queries.js';
|
|
8
8
|
export type { CancelWorkflowRunParams, CreateRerunWorkflowRunParams, CreateWorkflowRunParams, FailWorkflowRunAsTimedOutParams, UpdateWorkflowRunStatusParams, } from './workflow-runs/runs.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-runs.d.ts","sourceRoot":"","sources":["../../src/db/workflow-runs.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,uCAAuC,EACvC,8BAA8B,GAC/B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,EACvB,sCAAsC,EACtC,4BAA4B,EAC5B,
|
|
1
|
+
{"version":3,"file":"workflow-runs.d.ts","sourceRoot":"","sources":["../../src/db/workflow-runs.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,uCAAuC,EACvC,8BAA8B,GAC/B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,uBAAuB,EACvB,sCAAsC,EACtC,4BAA4B,EAC5B,iBAAiB,EACjB,2BAA2B,EAC3B,mCAAmC,EACnC,wBAAwB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,4BAA4B,EAC5B,wBAAwB,EACxB,qBAAqB,EACrB,QAAQ,EACR,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,8BAA8B,EAC9B,UAAU,EACV,WAAW,EACX,6BAA6B,EAC7B,sBAAsB,EACtB,iCAAiC,EACjC,eAAe,EACf,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,EAC7B,iCAAiC,EACjC,0BAA0B,EAC1B,gCAAgC,EAChC,8BAA8B,GAC/B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,+BAA+B,EAC/B,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,EACzB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,GACvB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,8BAA8B,EAC9B,qBAAqB,EACrB,gBAAgB,EAChB,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,2BAA2B,EAC3B,gBAAgB,EAChB,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,uBAAuB,EACvB,4BAA4B,EAC5B,uBAAuB,EACvB,+BAA+B,EAC/B,6BAA6B,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EACjB,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAC,wBAAwB,EAAC,MAAM,2BAA2B,CAAC;AACnE,YAAY,EACV,qBAAqB,EACrB,4BAA4B,EAC5B,0BAA0B,EAC1B,qCAAqC,EACrC,uBAAuB,EACvB,8BAA8B,EAC9B,yBAAyB,EACzB,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,iBAAiB,GAClB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,+BAA+B,EAC/B,iBAAiB,EACjB,4BAA4B,EAC5B,oBAAoB,EACpB,eAAe,EACf,+BAA+B,EAC/B,uBAAuB,EACvB,WAAW,EACX,0BAA0B,EAC1B,wBAAwB,EACxB,iCAAiC,EACjC,eAAe,EACf,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,eAAe,GAChB,MAAM,0BAA0B,CAAC"}
|
package/dist/db/workflow-runs.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { failJobExecutionAsTimedOut, getFirstJobExecutionByJobId, getJobExecutionById, getJobExecutionsByJobId, getJobExecutionsByWorkflowRunAttemptId, getLatestJobExecutionByJobId,
|
|
1
|
+
export { failJobExecutionAsTimedOut, getFirstJobExecutionByJobId, getJobExecutionById, getJobExecutionsByJobId, getJobExecutionsByWorkflowRunAttemptId, getLatestJobExecutionByJobId, queueJobExecution, recordJobExecutionStartedAt, resolveJobExecutionAfterLeaseExpiry, updateJobExecutionStatus } from './workflow-runs/job-executions.js';
|
|
2
2
|
export { evaluateJobActivations, evaluateJobSuccess, getDirectDependencyJobContexts, getJobById, getJobScope, getJobsByWorkflowRunAttemptId, getJobsByWorkflowRunId, resolveJobStatusFromJobExecutions, updateJobStatus, updateJobStatusAtVersion } from './workflow-runs/jobs.js';
|
|
3
|
-
export { writeJobStepsSettledOutbox, writeStepAttemptTerminatedOutbox, writeStepRestartEnqueuedOutbox } from './workflow-runs/outbox.js';
|
|
3
|
+
export { writeJobExecutionQueuedOutbox, writeJobExecutionTerminatedOutbox, writeJobStepsSettledOutbox, writeStepAttemptTerminatedOutbox, writeStepRestartEnqueuedOutbox } from './workflow-runs/outbox.js';
|
|
4
4
|
export { buildWorkflowRunListConditions, getJobExecutionDetail, getLatestAttempt, getWorkflowJobExecutionDepth, getWorkflowRunAggregates, getWorkflowRunAttemptById, getWorkflowRunByAttemptId, getWorkflowRunById, getWorkflowRunDetail, listRunAttempts, listWorkflowRunJobSummaries, listWorkflowRuns, listWorkflowRunsByProject } from './workflow-runs/queries.js';
|
|
5
5
|
export { cancelWorkflowRun, createRerunWorkflowRun, createWorkflowRun, failWorkflowRunAsTimedOut, loadReferencedVariables, updateWorkflowRunStatus } from './workflow-runs/runs.js';
|
|
6
6
|
export { getWorkflowContextForJob } from './workflow-runs/shared.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/db/workflow-runs.ts"],"sourcesContent":["export type {\n UpdateJobExecutionStatusAtVersionParams,\n UpdateJobExecutionStatusParams,\n} from './workflow-runs/job-executions.js';\nexport {\n failJobExecutionAsTimedOut,\n getFirstJobExecutionByJobId,\n getJobExecutionById,\n getJobExecutionsByJobId,\n getJobExecutionsByWorkflowRunAttemptId,\n getLatestJobExecutionByJobId,\n
|
|
1
|
+
{"version":3,"sources":["../../src/db/workflow-runs.ts"],"sourcesContent":["export type {\n UpdateJobExecutionStatusAtVersionParams,\n UpdateJobExecutionStatusParams,\n} from './workflow-runs/job-executions.js';\nexport {\n failJobExecutionAsTimedOut,\n getFirstJobExecutionByJobId,\n getJobExecutionById,\n getJobExecutionsByJobId,\n getJobExecutionsByWorkflowRunAttemptId,\n getLatestJobExecutionByJobId,\n queueJobExecution,\n recordJobExecutionStartedAt,\n resolveJobExecutionAfterLeaseExpiry,\n updateJobExecutionStatus,\n} from './workflow-runs/job-executions.js';\nexport type {\n EvaluateJobActivationsParams,\n EvaluateJobSuccessResult,\n JobActivationDecision,\n JobScope,\n UpdateJobStatusAtVersionParams,\n UpdateJobStatusParams,\n} from './workflow-runs/jobs.js';\nexport {\n evaluateJobActivations,\n evaluateJobSuccess,\n getDirectDependencyJobContexts,\n getJobById,\n getJobScope,\n getJobsByWorkflowRunAttemptId,\n getJobsByWorkflowRunId,\n resolveJobStatusFromJobExecutions,\n updateJobStatus,\n updateJobStatusAtVersion,\n} from './workflow-runs/jobs.js';\nexport {\n writeJobExecutionQueuedOutbox,\n writeJobExecutionTerminatedOutbox,\n writeJobStepsSettledOutbox,\n writeStepAttemptTerminatedOutbox,\n writeStepRestartEnqueuedOutbox,\n} from './workflow-runs/outbox.js';\nexport type {\n ListWorkflowRunsParams,\n ListWorkflowRunsResult,\n WorkflowJobExecutionDepth,\n WorkflowJobExecutionDepthParams,\n WorkflowRunAggregates,\n WorkflowRunCursor,\n WorkflowRunFilters,\n WorkflowRunJobRawStatusCount,\n WorkflowRunJobStatusCount,\n WorkflowRunJobSummary,\n WorkflowRunJobSummaryTarget,\n WorkflowRunJobsSummary,\n} from './workflow-runs/queries.js';\nexport {\n buildWorkflowRunListConditions,\n getJobExecutionDetail,\n getLatestAttempt,\n getWorkflowJobExecutionDepth,\n getWorkflowRunAggregates,\n getWorkflowRunAttemptById,\n getWorkflowRunByAttemptId,\n getWorkflowRunById,\n getWorkflowRunDetail,\n listRunAttempts,\n listWorkflowRunJobSummaries,\n listWorkflowRuns,\n listWorkflowRunsByProject,\n} from './workflow-runs/queries.js';\nexport type {\n CancelWorkflowRunParams,\n CreateRerunWorkflowRunParams,\n CreateWorkflowRunParams,\n FailWorkflowRunAsTimedOutParams,\n UpdateWorkflowRunStatusParams,\n} from './workflow-runs/runs.js';\nexport {\n cancelWorkflowRun,\n createRerunWorkflowRun,\n createWorkflowRun,\n failWorkflowRunAsTimedOut,\n loadReferencedVariables,\n updateWorkflowRunStatus,\n} from './workflow-runs/runs.js';\nexport {getWorkflowContextForJob} from './workflow-runs/shared.js';\nexport type {\n ApplyStepResultParams,\n BulkUpdateStepStatusesParams,\n CancelRemainingStepsParams,\n DispatchStepWithCompletedConfigParams,\n FinishStepAttemptParams,\n InsertRunningStepAttemptParams,\n JobExecutionFailureOrigin,\n MarkStepRunningParams,\n MarkStepSkippedParams,\n RewindStepsToPendingParams,\n StepAttemptDetail,\n} from './workflow-runs/steps.js';\nexport {\n applyStepResult,\n bulkUpdateStepStatuses,\n cancelRemainingSteps,\n countStepAttempts,\n dispatchStepWithCompletedConfig,\n finishStepAttempt,\n getJobExecutionFailureOrigin,\n getStepAttemptDetail,\n getStepAttempts,\n getStepAttemptsByJobExecutionId,\n getStepAttemptsByJobIds,\n getStepById,\n getStepByIdForJobExecution,\n getStepsByJobExecutionId,\n getStepsByJobExecutionIdForUpdate,\n getStepsByJobId,\n insertRunningStepAttempt,\n markStepRunning,\n markStepSkipped,\n rewindStepsToPending,\n settleJobFailed,\n} from './workflow-runs/steps.js';\n"],"names":["failJobExecutionAsTimedOut","getFirstJobExecutionByJobId","getJobExecutionById","getJobExecutionsByJobId","getJobExecutionsByWorkflowRunAttemptId","getLatestJobExecutionByJobId","queueJobExecution","recordJobExecutionStartedAt","resolveJobExecutionAfterLeaseExpiry","updateJobExecutionStatus","evaluateJobActivations","evaluateJobSuccess","getDirectDependencyJobContexts","getJobById","getJobScope","getJobsByWorkflowRunAttemptId","getJobsByWorkflowRunId","resolveJobStatusFromJobExecutions","updateJobStatus","updateJobStatusAtVersion","writeJobExecutionQueuedOutbox","writeJobExecutionTerminatedOutbox","writeJobStepsSettledOutbox","writeStepAttemptTerminatedOutbox","writeStepRestartEnqueuedOutbox","buildWorkflowRunListConditions","getJobExecutionDetail","getLatestAttempt","getWorkflowJobExecutionDepth","getWorkflowRunAggregates","getWorkflowRunAttemptById","getWorkflowRunByAttemptId","getWorkflowRunById","getWorkflowRunDetail","listRunAttempts","listWorkflowRunJobSummaries","listWorkflowRuns","listWorkflowRunsByProject","cancelWorkflowRun","createRerunWorkflowRun","createWorkflowRun","failWorkflowRunAsTimedOut","loadReferencedVariables","updateWorkflowRunStatus","getWorkflowContextForJob","applyStepResult","bulkUpdateStepStatuses","cancelRemainingSteps","countStepAttempts","dispatchStepWithCompletedConfig","finishStepAttempt","getJobExecutionFailureOrigin","getStepAttemptDetail","getStepAttempts","getStepAttemptsByJobExecutionId","getStepAttemptsByJobIds","getStepById","getStepByIdForJobExecution","getStepsByJobExecutionId","getStepsByJobExecutionIdForUpdate","getStepsByJobId","insertRunningStepAttempt","markStepRunning","markStepSkipped","rewindStepsToPending","settleJobFailed"],"mappings":"AAIA,SACEA,0BAA0B,EAC1BC,2BAA2B,EAC3BC,mBAAmB,EACnBC,uBAAuB,EACvBC,sCAAsC,EACtCC,4BAA4B,EAC5BC,iBAAiB,EACjBC,2BAA2B,EAC3BC,mCAAmC,EACnCC,wBAAwB,QACnB,oCAAoC;AAS3C,SACEC,sBAAsB,EACtBC,kBAAkB,EAClBC,8BAA8B,EAC9BC,UAAU,EACVC,WAAW,EACXC,6BAA6B,EAC7BC,sBAAsB,EACtBC,iCAAiC,EACjCC,eAAe,EACfC,wBAAwB,QACnB,0BAA0B;AACjC,SACEC,6BAA6B,EAC7BC,iCAAiC,EACjCC,0BAA0B,EAC1BC,gCAAgC,EAChCC,8BAA8B,QACzB,4BAA4B;AAenC,SACEC,8BAA8B,EAC9BC,qBAAqB,EACrBC,gBAAgB,EAChBC,4BAA4B,EAC5BC,wBAAwB,EACxBC,yBAAyB,EACzBC,yBAAyB,EACzBC,kBAAkB,EAClBC,oBAAoB,EACpBC,eAAe,EACfC,2BAA2B,EAC3BC,gBAAgB,EAChBC,yBAAyB,QACpB,6BAA6B;AAQpC,SACEC,iBAAiB,EACjBC,sBAAsB,EACtBC,iBAAiB,EACjBC,yBAAyB,EACzBC,uBAAuB,EACvBC,uBAAuB,QAClB,0BAA0B;AACjC,SAAQC,wBAAwB,QAAO,4BAA4B;AAcnE,SACEC,eAAe,EACfC,sBAAsB,EACtBC,oBAAoB,EACpBC,iBAAiB,EACjBC,+BAA+B,EAC/BC,iBAAiB,EACjBC,4BAA4B,EAC5BC,oBAAoB,EACpBC,eAAe,EACfC,+BAA+B,EAC/BC,uBAAuB,EACvBC,WAAW,EACXC,0BAA0B,EAC1BC,wBAAwB,EACxBC,iCAAiC,EACjCC,eAAe,EACfC,wBAAwB,EACxBC,eAAe,EACfC,eAAe,EACfC,oBAAoB,EACpBC,eAAe,QACV,2BAA2B"}
|