@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
|
@@ -12,12 +12,9 @@ export interface JobClaimedSignalPayload {
|
|
|
12
12
|
}
|
|
13
13
|
export declare const jobClaimedSignal: import("@temporalio/common").SignalDefinition<[JobClaimedSignalPayload], string>;
|
|
14
14
|
export interface JobExecutionOrchestrationInput {
|
|
15
|
-
workspaceId: string;
|
|
16
|
-
workflowRunId: string;
|
|
17
15
|
runAttemptId: string;
|
|
18
16
|
jobId: string;
|
|
19
17
|
jobExecutionId: string;
|
|
20
|
-
projectId: string;
|
|
21
18
|
jobVersion: number;
|
|
22
19
|
executionVersion: number;
|
|
23
20
|
executionTimeoutMs?: number | null | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-execution-orchestration.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/job-execution-orchestration.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"job-execution-orchestration.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/job-execution-orchestration.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,0CAA0C,CAAC;AA4CtF,eAAO,MAAM,iBAAiB;YACL,uBAAuB;qBAAmB,MAAM,GAAG,SAAS;WAElF,CAAC;AACJ,eAAO,MAAM,qBAAqB;qBACA,MAAM,GAAG,SAAS;WAA6B,CAAC;AAClF,MAAM,WAAW,uBAAuB;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AACD,eAAO,MAAM,gBAAgB,kFAA8D,CAAC;AAE5F,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,+BAA+B;IAC9C,MAAM,EAAE,uBAAuB,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB;AAsMD,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,8BAA8B,GACpC,OAAO,CAAC,+BAA+B,CAAC,CA0D1C"}
|
|
@@ -17,9 +17,9 @@ import { remainingMs } from './deadline.js';
|
|
|
17
17
|
* execution pending while it is queued, then performs the versioned pending → running
|
|
18
18
|
* transition after the current claim. One deadline spans both waits; claim never resets
|
|
19
19
|
* it. Signals can arrive in any order, so the precedence is finished > lease expired >
|
|
20
|
-
* claimed > timeout.
|
|
21
|
-
*
|
|
22
|
-
*/ const { setJobStatus, setJobExecutionStatus,
|
|
20
|
+
* claimed > timeout. Workflows commits queue and terminal facts with its state transitions;
|
|
21
|
+
* runners reconciles its local queue, lease, and reservation projections asynchronously.
|
|
22
|
+
*/ const { setJobStatus, setJobExecutionStatus, queueJobExecutionActivity, bulkSetStepStatuses, failJobExecutionAsTimedOutActivity, resolveLeaseExpiredJobExecutionActivity } = proxyActivities({
|
|
23
23
|
startToCloseTimeout: '30s'
|
|
24
24
|
});
|
|
25
25
|
const { resolveJobStatusFromJobExecutionsActivity } = proxyActivities({
|
|
@@ -28,31 +28,10 @@ const { resolveJobStatusFromJobExecutionsActivity } = proxyActivities({
|
|
|
28
28
|
maximumAttempts: 5
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
|
-
// Lease cleanup gets a bounded retry policy of its own: after a few attempts the
|
|
32
|
-
// workflow stops waiting on it (see releaseLeaseBestEffort) rather than blocking
|
|
33
|
-
// the DAG on runners-side availability.
|
|
34
|
-
const { releaseLeaseActivity } = proxyActivities({
|
|
35
|
-
startToCloseTimeout: '30s',
|
|
36
|
-
retry: {
|
|
37
|
-
maximumAttempts: 5
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
31
|
const DEFAULT_EXECUTION_MAX_DURATION_MS = 6 * 60 * 60 * 1000;
|
|
41
32
|
export const jobFinishedSignal = defineSignal(JOB_FINISHED_SIGNAL);
|
|
42
33
|
export const jobLeaseExpiredSignal = defineSignal(JOB_LEASE_EXPIRED_SIGNAL);
|
|
43
34
|
export const jobClaimedSignal = defineSignal(JOB_CLAIMED_SIGNAL);
|
|
44
|
-
async function releaseLeaseBestEffort(jobExecutionId) {
|
|
45
|
-
try {
|
|
46
|
-
await releaseLeaseActivity({
|
|
47
|
-
jobExecutionId
|
|
48
|
-
});
|
|
49
|
-
} catch (err) {
|
|
50
|
-
log.warn('lease release failed; stuck detector will reap the row', {
|
|
51
|
-
jobExecutionId,
|
|
52
|
-
error: String(err)
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
35
|
async function resolveJobStatusOrFailClosed(input) {
|
|
57
36
|
try {
|
|
58
37
|
return await resolveJobStatusFromJobExecutionsActivity({
|
|
@@ -76,19 +55,14 @@ async function resolveJobStatusOrFailClosed(input) {
|
|
|
76
55
|
};
|
|
77
56
|
}
|
|
78
57
|
}
|
|
79
|
-
async function
|
|
58
|
+
async function queueJobExecution(input) {
|
|
80
59
|
if (hasNoRequiredRunnerLabels(input.requiredLabels)) {
|
|
81
60
|
throw ApplicationFailure.nonRetryable(`Job ${input.jobId} has no required runner labels`, 'EmptyRequiredLabelsError');
|
|
82
61
|
}
|
|
83
|
-
await
|
|
84
|
-
workspaceId: input.workspaceId,
|
|
85
|
-
workflowRunId: input.workflowRunId,
|
|
86
|
-
runAttemptId: input.runAttemptId,
|
|
62
|
+
return jobExecutionStartOutcome(await queueJobExecutionActivity({
|
|
87
63
|
jobId: input.jobId,
|
|
88
|
-
jobExecutionId: input.jobExecutionId
|
|
89
|
-
|
|
90
|
-
requiredLabels: input.requiredLabels
|
|
91
|
-
});
|
|
64
|
+
jobExecutionId: input.jobExecutionId
|
|
65
|
+
}));
|
|
92
66
|
}
|
|
93
67
|
async function markJobExecutionRunning(input) {
|
|
94
68
|
const { newVersion: runningVersion, status } = await setJobExecutionStatus({
|
|
@@ -137,7 +111,6 @@ async function resolveFinishedJobExecution({ input, runningVersion, status }) {
|
|
|
137
111
|
terminationReason: 'finished',
|
|
138
112
|
status
|
|
139
113
|
});
|
|
140
|
-
await releaseLeaseBestEffort(input.jobExecutionId);
|
|
141
114
|
return {
|
|
142
115
|
status,
|
|
143
116
|
jobVersion: input.jobVersion
|
|
@@ -150,7 +123,6 @@ async function resolveFinishedJobExecution({ input, runningVersion, status }) {
|
|
|
150
123
|
terminationReason: 'finished',
|
|
151
124
|
status: resolved.status
|
|
152
125
|
});
|
|
153
|
-
await releaseLeaseBestEffort(input.jobExecutionId);
|
|
154
126
|
return resolved;
|
|
155
127
|
}
|
|
156
128
|
function jobExecutionStatusForRuntimeStatus(status) {
|
|
@@ -169,7 +141,6 @@ async function resolveLeaseExpiredJobExecution({ input, runningVersion }) {
|
|
|
169
141
|
terminationReason: 'lease_expired',
|
|
170
142
|
status: leaseExpired.status
|
|
171
143
|
});
|
|
172
|
-
await releaseLeaseBestEffort(input.jobExecutionId);
|
|
173
144
|
return {
|
|
174
145
|
status: leaseExpired.status,
|
|
175
146
|
jobVersion: input.jobVersion
|
|
@@ -182,15 +153,14 @@ async function resolveLeaseExpiredJobExecution({ input, runningVersion }) {
|
|
|
182
153
|
terminationReason: 'lease_expired',
|
|
183
154
|
status
|
|
184
155
|
});
|
|
185
|
-
await releaseLeaseBestEffort(input.jobExecutionId);
|
|
186
156
|
return {
|
|
187
157
|
status,
|
|
188
158
|
jobVersion
|
|
189
159
|
};
|
|
190
160
|
}
|
|
191
|
-
// Timeout backstop. The activity atomically fails the execution, marks
|
|
192
|
-
//
|
|
193
|
-
//
|
|
161
|
+
// Timeout backstop. The activity atomically fails the execution, marks `timed_out_at`, and
|
|
162
|
+
// enqueues the generic terminal execution fact. The runners subscriber then asks the runner to
|
|
163
|
+
// cancel. The lease is intentionally NOT released here.
|
|
194
164
|
async function resolveTimedOutJobExecution({ input, runningVersion }) {
|
|
195
165
|
await failJobExecutionAsTimedOutActivity({
|
|
196
166
|
jobExecutionId: input.jobExecutionId,
|
|
@@ -234,7 +204,13 @@ export async function jobExecutionOrchestration(input) {
|
|
|
234
204
|
// Register every signal before enqueue can block or publish a claim/outcome event. The
|
|
235
205
|
// handlers retain signals that arrive while the enqueue activity is in flight.
|
|
236
206
|
registerJobExecutionSignalHandlers(input.jobExecutionId, signals);
|
|
237
|
-
await
|
|
207
|
+
const queued = await queueJobExecution(input);
|
|
208
|
+
if (queued.kind === 'terminal') {
|
|
209
|
+
return {
|
|
210
|
+
status: queued.result.status,
|
|
211
|
+
jobVersion: input.jobVersion
|
|
212
|
+
};
|
|
213
|
+
}
|
|
238
214
|
const timeoutMs = input.executionTimeoutMs ?? DEFAULT_EXECUTION_MAX_DURATION_MS;
|
|
239
215
|
const deadline = Date.now() + timeoutMs;
|
|
240
216
|
await waitForJobExecutionSignal(signals, deadline, true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/temporal/workflows/job-execution-orchestration.ts"],"sourcesContent":["import {ApplicationFailure} from '@temporalio/common';\nimport {condition, defineSignal, log, proxyActivities, setHandler} from '@temporalio/workflow';\nimport {\n hasNoRequiredRunnerLabels,\n type JobExecutionOutcomeSignals,\n jobExecutionStartOutcome,\n resolveJobExecutionOutcomeSignal,\n} from '#core/job-execution-outcome.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\n\nimport type {createOrchestrationActivities} from '../activities/index.js';\nimport {JOB_CLAIMED_SIGNAL, JOB_FINISHED_SIGNAL, JOB_LEASE_EXPIRED_SIGNAL} from '../constants.js';\nimport {remainingMs} from './deadline.js';\n\n/**\n * Enqueue, wait for the runner claim, then wait for one of the terminal facts:\n *\n * enqueue ──> PENDING ── job-claimed ──> RUNNING\n * │ │\n * │ timeout ├─ job-finished\n * │ ├─ job-lease-expired\n * ▼ └─ timeout\n * TERMINAL\n *\n * The claim signal is the runner-owned lifecycle boundary. The workflow keeps the\n * execution pending while it is queued, then performs the versioned pending → running\n * transition after the current claim. One deadline spans both waits; claim never resets\n * it. Signals can arrive in any order, so the precedence is finished > lease expired >\n * claimed > timeout. Lease cleanup remains best-effort: a runners DB outage must never\n * block the child workflow from returning the job outcome to run-orchestration.\n */\n\nconst {\n setJobStatus,\n setJobExecutionStatus,\n enqueueJobExecutionForRunner,\n bulkSetStepStatuses,\n failJobExecutionAsTimedOutActivity,\n resolveLeaseExpiredJobExecutionActivity,\n} = proxyActivities<ReturnType<typeof createOrchestrationActivities>>({\n startToCloseTimeout: '30s',\n});\n\nconst {resolveJobStatusFromJobExecutionsActivity} = proxyActivities<\n ReturnType<typeof createOrchestrationActivities>\n>({\n startToCloseTimeout: '30s',\n retry: {maximumAttempts: 5},\n});\n\n// Lease cleanup gets a bounded retry policy of its own: after a few attempts the\n// workflow stops waiting on it (see releaseLeaseBestEffort) rather than blocking\n// the DAG on runners-side availability.\nconst {releaseLeaseActivity} = proxyActivities<ReturnType<typeof createOrchestrationActivities>>({\n startToCloseTimeout: '30s',\n retry: {maximumAttempts: 5},\n});\n\nconst DEFAULT_EXECUTION_MAX_DURATION_MS = 6 * 60 * 60 * 1000;\n\nexport const jobFinishedSignal =\n defineSignal<[{status: RuntimeCompletionStatus; jobExecutionId?: string | undefined}]>(\n JOB_FINISHED_SIGNAL,\n );\nexport const jobLeaseExpiredSignal =\n defineSignal<[{jobExecutionId?: string | undefined}]>(JOB_LEASE_EXPIRED_SIGNAL);\nexport interface JobClaimedSignalPayload {\n jobExecutionId: string;\n claimedAt: string;\n}\nexport const jobClaimedSignal = defineSignal<[JobClaimedSignalPayload]>(JOB_CLAIMED_SIGNAL);\n\nexport interface JobExecutionOrchestrationInput {\n workspaceId: string;\n workflowRunId: string;\n runAttemptId: string;\n jobId: string;\n jobExecutionId: string;\n projectId: string;\n jobVersion: number;\n executionVersion: number;\n executionTimeoutMs?: number | null | undefined;\n resolveJobStatus?: boolean | undefined;\n requiredLabels: string[];\n}\n\nexport interface JobExecutionOrchestrationResult {\n status: RuntimeCompletionStatus;\n jobVersion: number;\n}\n\nasync function releaseLeaseBestEffort(jobExecutionId: string): Promise<void> {\n try {\n await releaseLeaseActivity({jobExecutionId});\n } catch (err) {\n log.warn('lease release failed; stuck detector will reap the row', {\n jobExecutionId,\n error: String(err),\n });\n }\n}\n\nasync function resolveJobStatusOrFailClosed(\n input: JobExecutionOrchestrationInput,\n): Promise<{status: RuntimeCompletionStatus; jobVersion: number}> {\n try {\n return await resolveJobStatusFromJobExecutionsActivity({jobId: input.jobId});\n } catch (err) {\n log.error('job status resolution failed; failing job closed', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n error: String(err),\n });\n const {newVersion} = await setJobStatus({\n jobId: input.jobId,\n status: 'failed',\n version: input.jobVersion,\n statusReason: 'step_failed',\n });\n return {status: 'failed', jobVersion: newVersion};\n }\n}\n\nasync function enqueueJobExecution(input: JobExecutionOrchestrationInput): Promise<void> {\n if (hasNoRequiredRunnerLabels(input.requiredLabels)) {\n throw ApplicationFailure.nonRetryable(\n `Job ${input.jobId} has no required runner labels`,\n 'EmptyRequiredLabelsError',\n );\n }\n\n await enqueueJobExecutionForRunner({\n workspaceId: input.workspaceId,\n workflowRunId: input.workflowRunId,\n runAttemptId: input.runAttemptId,\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n projectId: input.projectId,\n requiredLabels: input.requiredLabels,\n });\n}\n\nasync function markJobExecutionRunning(\n input: JobExecutionOrchestrationInput,\n): Promise<\n | {kind: 'running'; runningVersion: number}\n | {kind: 'terminal'; result: JobExecutionOrchestrationResult}\n> {\n const {newVersion: runningVersion, status} = await setJobExecutionStatus({\n jobExecutionId: input.jobExecutionId,\n status: 'running',\n version: input.executionVersion,\n });\n\n const start = jobExecutionStartOutcome({newVersion: runningVersion, status});\n if (start.kind === 'terminal') return start;\n return {kind: 'running', runningVersion};\n}\n\ninterface JobExecutionSignals extends JobExecutionOutcomeSignals {\n claimed: JobClaimedSignalPayload | undefined;\n}\n\nfunction registerJobExecutionSignalHandlers(\n jobExecutionId: string,\n signals: JobExecutionSignals,\n): void {\n setHandler(jobFinishedSignal, (payload) => {\n if (payload.jobExecutionId !== undefined && payload.jobExecutionId !== jobExecutionId) return;\n signals.finished ??= payload;\n });\n setHandler(jobLeaseExpiredSignal, (payload = {}) => {\n if (payload.jobExecutionId !== undefined && payload.jobExecutionId !== jobExecutionId) return;\n signals.leaseExpired = true;\n });\n setHandler(jobClaimedSignal, (payload) => {\n if (payload.jobExecutionId !== jobExecutionId) return;\n signals.claimed ??= payload;\n });\n}\n\nasync function waitForJobExecutionSignal(\n signals: JobExecutionSignals,\n deadline: number,\n includeClaim: boolean,\n): Promise<void> {\n await condition(\n () =>\n signals.finished !== undefined ||\n signals.leaseExpired ||\n (includeClaim && signals.claimed !== undefined),\n remainingMs(deadline) ?? 0,\n );\n}\n\ninterface JobExecutionResolution {\n input: JobExecutionOrchestrationInput;\n runningVersion: number;\n}\n\nasync function resolveFinishedJobExecution({\n input,\n runningVersion,\n status,\n}: JobExecutionResolution & {\n status: RuntimeCompletionStatus;\n}): Promise<JobExecutionOrchestrationResult> {\n await setJobExecutionStatus({\n jobExecutionId: input.jobExecutionId,\n status: jobExecutionStatusForRuntimeStatus(status),\n version: runningVersion,\n statusReason: status === 'failed' ? 'step_failed' : null,\n });\n if (input.resolveJobStatus === false) {\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'finished',\n status,\n });\n await releaseLeaseBestEffort(input.jobExecutionId);\n return {status, jobVersion: input.jobVersion};\n }\n const resolved = await resolveJobStatusOrFailClosed(input);\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'finished',\n status: resolved.status,\n });\n await releaseLeaseBestEffort(input.jobExecutionId);\n return resolved;\n}\n\nfunction jobExecutionStatusForRuntimeStatus(\n status: RuntimeCompletionStatus,\n): 'succeeded' | 'failed' | 'cancelled' {\n if (status === 'succeeded' || status === 'failed' || status === 'cancelled') return status;\n throw ApplicationFailure.nonRetryable(\n `Job execution cannot be marked ${status}`,\n 'InvalidJobExecutionStatusError',\n );\n}\n\nasync function resolveLeaseExpiredJobExecution({\n input,\n runningVersion,\n}: JobExecutionResolution): Promise<JobExecutionOrchestrationResult> {\n const leaseExpired = await resolveLeaseExpiredJobExecutionActivity({\n jobExecutionId: input.jobExecutionId,\n expectedVersion: runningVersion,\n });\n if (input.resolveJobStatus === false) {\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'lease_expired',\n status: leaseExpired.status,\n });\n await releaseLeaseBestEffort(input.jobExecutionId);\n return {status: leaseExpired.status, jobVersion: input.jobVersion};\n }\n const {status, jobVersion} = await resolveJobStatusOrFailClosed(input);\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'lease_expired',\n status,\n });\n await releaseLeaseBestEffort(input.jobExecutionId);\n return {status, jobVersion};\n}\n\n// Timeout backstop. The activity atomically fails the execution, marks\n// `timed_out_at`, and enqueues WORKFLOWS_JOB_EXECUTION_TIMED_OUT; the runners subscriber\n// then asks the runner to cancel. The lease is intentionally NOT released here.\nasync function resolveTimedOutJobExecution({\n input,\n runningVersion,\n}: JobExecutionResolution): Promise<JobExecutionOrchestrationResult> {\n await failJobExecutionAsTimedOutActivity({\n jobExecutionId: input.jobExecutionId,\n runAttemptId: input.runAttemptId,\n expectedVersion: runningVersion,\n });\n await bulkSetStepStatuses({jobExecutionId: input.jobExecutionId, status: 'failed'});\n if (input.resolveJobStatus === false) {\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'max_duration',\n status: 'failed',\n });\n return {status: 'failed', jobVersion: input.jobVersion};\n }\n const {jobVersion} = await resolveJobStatusOrFailClosed(input);\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'max_duration',\n status: 'failed',\n });\n return {status: 'failed', jobVersion};\n}\n\nexport async function jobExecutionOrchestration(\n input: JobExecutionOrchestrationInput,\n): Promise<JobExecutionOrchestrationResult> {\n const signals: JobExecutionSignals = {\n finished: undefined,\n leaseExpired: false,\n claimed: undefined,\n };\n // Register every signal before enqueue can block or publish a claim/outcome event. The\n // handlers retain signals that arrive while the enqueue activity is in flight.\n registerJobExecutionSignalHandlers(input.jobExecutionId, signals);\n await enqueueJobExecution(input);\n\n const timeoutMs = input.executionTimeoutMs ?? DEFAULT_EXECUTION_MAX_DURATION_MS;\n const deadline = Date.now() + timeoutMs;\n await waitForJobExecutionSignal(signals, deadline, true);\n\n // A terminal fact wins over claim even when both signals arrive before the condition\n // resumes. This prevents a late claim from reopening an execution that already finished.\n let resolution = resolveJobExecutionOutcomeSignal(signals);\n if (resolution === 'finished') {\n const {finished} = signals;\n if (finished === undefined) throw new Error('Missing finished signal for finished resolution');\n\n return resolveFinishedJobExecution({\n input,\n runningVersion: input.executionVersion,\n status: finished.status,\n });\n }\n if (resolution === 'lease-expired') {\n return resolveLeaseExpiredJobExecution({input, runningVersion: input.executionVersion});\n }\n if (!signals.claimed) {\n return resolveTimedOutJobExecution({input, runningVersion: input.executionVersion});\n }\n\n const running = await markJobExecutionRunning(input);\n if (running.kind === 'terminal') {\n if (input.resolveJobStatus === false) {\n return {status: running.result.status, jobVersion: input.jobVersion};\n }\n return running.result;\n }\n const {runningVersion} = running;\n\n await waitForJobExecutionSignal(signals, deadline, false);\n resolution = resolveJobExecutionOutcomeSignal(signals);\n if (resolution === 'finished') {\n const {finished} = signals;\n if (finished === undefined) throw new Error('Missing finished signal for finished resolution');\n return resolveFinishedJobExecution({input, runningVersion, status: finished.status});\n }\n if (resolution === 'lease-expired') {\n return resolveLeaseExpiredJobExecution({input, runningVersion});\n }\n return resolveTimedOutJobExecution({input, runningVersion});\n}\n"],"names":["ApplicationFailure","condition","defineSignal","log","proxyActivities","setHandler","hasNoRequiredRunnerLabels","jobExecutionStartOutcome","resolveJobExecutionOutcomeSignal","JOB_CLAIMED_SIGNAL","JOB_FINISHED_SIGNAL","JOB_LEASE_EXPIRED_SIGNAL","remainingMs","setJobStatus","setJobExecutionStatus","enqueueJobExecutionForRunner","bulkSetStepStatuses","failJobExecutionAsTimedOutActivity","resolveLeaseExpiredJobExecutionActivity","startToCloseTimeout","resolveJobStatusFromJobExecutionsActivity","retry","maximumAttempts","releaseLeaseActivity","DEFAULT_EXECUTION_MAX_DURATION_MS","jobFinishedSignal","jobLeaseExpiredSignal","jobClaimedSignal","releaseLeaseBestEffort","jobExecutionId","err","warn","error","String","resolveJobStatusOrFailClosed","input","jobId","newVersion","status","version","jobVersion","statusReason","enqueueJobExecution","requiredLabels","nonRetryable","workspaceId","workflowRunId","runAttemptId","projectId","markJobExecutionRunning","runningVersion","executionVersion","start","kind","registerJobExecutionSignalHandlers","signals","payload","undefined","finished","leaseExpired","claimed","waitForJobExecutionSignal","deadline","includeClaim","resolveFinishedJobExecution","jobExecutionStatusForRuntimeStatus","resolveJobStatus","info","terminationReason","resolved","resolveLeaseExpiredJobExecution","expectedVersion","resolveTimedOutJobExecution","jobExecutionOrchestration","timeoutMs","executionTimeoutMs","Date","now","resolution","Error","running","result"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/workflows/job-execution-orchestration.ts"],"sourcesContent":["import {ApplicationFailure} from '@temporalio/common';\nimport {condition, defineSignal, log, proxyActivities, setHandler} from '@temporalio/workflow';\nimport {\n hasNoRequiredRunnerLabels,\n type JobExecutionOutcomeSignals,\n jobExecutionStartOutcome,\n resolveJobExecutionOutcomeSignal,\n} from '#core/job-execution-outcome.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\n\nimport type {createOrchestrationActivities} from '../activities/index.js';\nimport {JOB_CLAIMED_SIGNAL, JOB_FINISHED_SIGNAL, JOB_LEASE_EXPIRED_SIGNAL} from '../constants.js';\nimport {remainingMs} from './deadline.js';\n\n/**\n * Enqueue, wait for the runner claim, then wait for one of the terminal facts:\n *\n * enqueue ──> PENDING ── job-claimed ──> RUNNING\n * │ │\n * │ timeout ├─ job-finished\n * │ ├─ job-lease-expired\n * ▼ └─ timeout\n * TERMINAL\n *\n * The claim signal is the runner-owned lifecycle boundary. The workflow keeps the\n * execution pending while it is queued, then performs the versioned pending → running\n * transition after the current claim. One deadline spans both waits; claim never resets\n * it. Signals can arrive in any order, so the precedence is finished > lease expired >\n * claimed > timeout. Workflows commits queue and terminal facts with its state transitions;\n * runners reconciles its local queue, lease, and reservation projections asynchronously.\n */\n\nconst {\n setJobStatus,\n setJobExecutionStatus,\n queueJobExecutionActivity,\n bulkSetStepStatuses,\n failJobExecutionAsTimedOutActivity,\n resolveLeaseExpiredJobExecutionActivity,\n} = proxyActivities<ReturnType<typeof createOrchestrationActivities>>({\n startToCloseTimeout: '30s',\n});\n\nconst {resolveJobStatusFromJobExecutionsActivity} = proxyActivities<\n ReturnType<typeof createOrchestrationActivities>\n>({\n startToCloseTimeout: '30s',\n retry: {maximumAttempts: 5},\n});\n\nconst DEFAULT_EXECUTION_MAX_DURATION_MS = 6 * 60 * 60 * 1000;\n\nexport const jobFinishedSignal =\n defineSignal<[{status: RuntimeCompletionStatus; jobExecutionId?: string | undefined}]>(\n JOB_FINISHED_SIGNAL,\n );\nexport const jobLeaseExpiredSignal =\n defineSignal<[{jobExecutionId?: string | undefined}]>(JOB_LEASE_EXPIRED_SIGNAL);\nexport interface JobClaimedSignalPayload {\n jobExecutionId: string;\n claimedAt: string;\n}\nexport const jobClaimedSignal = defineSignal<[JobClaimedSignalPayload]>(JOB_CLAIMED_SIGNAL);\n\nexport interface JobExecutionOrchestrationInput {\n runAttemptId: string;\n jobId: string;\n jobExecutionId: string;\n jobVersion: number;\n executionVersion: number;\n executionTimeoutMs?: number | null | undefined;\n resolveJobStatus?: boolean | undefined;\n requiredLabels: string[];\n}\n\nexport interface JobExecutionOrchestrationResult {\n status: RuntimeCompletionStatus;\n jobVersion: number;\n}\n\nasync function resolveJobStatusOrFailClosed(\n input: JobExecutionOrchestrationInput,\n): Promise<{status: RuntimeCompletionStatus; jobVersion: number}> {\n try {\n return await resolveJobStatusFromJobExecutionsActivity({jobId: input.jobId});\n } catch (err) {\n log.error('job status resolution failed; failing job closed', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n error: String(err),\n });\n const {newVersion} = await setJobStatus({\n jobId: input.jobId,\n status: 'failed',\n version: input.jobVersion,\n statusReason: 'step_failed',\n });\n return {status: 'failed', jobVersion: newVersion};\n }\n}\n\nasync function queueJobExecution(input: JobExecutionOrchestrationInput) {\n if (hasNoRequiredRunnerLabels(input.requiredLabels)) {\n throw ApplicationFailure.nonRetryable(\n `Job ${input.jobId} has no required runner labels`,\n 'EmptyRequiredLabelsError',\n );\n }\n\n return jobExecutionStartOutcome(\n await queueJobExecutionActivity({\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n }),\n );\n}\n\nasync function markJobExecutionRunning(\n input: JobExecutionOrchestrationInput,\n): Promise<\n | {kind: 'running'; runningVersion: number}\n | {kind: 'terminal'; result: JobExecutionOrchestrationResult}\n> {\n const {newVersion: runningVersion, status} = await setJobExecutionStatus({\n jobExecutionId: input.jobExecutionId,\n status: 'running',\n version: input.executionVersion,\n });\n\n const start = jobExecutionStartOutcome({newVersion: runningVersion, status});\n if (start.kind === 'terminal') return start;\n return {kind: 'running', runningVersion};\n}\n\ninterface JobExecutionSignals extends JobExecutionOutcomeSignals {\n claimed: JobClaimedSignalPayload | undefined;\n}\n\nfunction registerJobExecutionSignalHandlers(\n jobExecutionId: string,\n signals: JobExecutionSignals,\n): void {\n setHandler(jobFinishedSignal, (payload) => {\n if (payload.jobExecutionId !== undefined && payload.jobExecutionId !== jobExecutionId) return;\n signals.finished ??= payload;\n });\n setHandler(jobLeaseExpiredSignal, (payload = {}) => {\n if (payload.jobExecutionId !== undefined && payload.jobExecutionId !== jobExecutionId) return;\n signals.leaseExpired = true;\n });\n setHandler(jobClaimedSignal, (payload) => {\n if (payload.jobExecutionId !== jobExecutionId) return;\n signals.claimed ??= payload;\n });\n}\n\nasync function waitForJobExecutionSignal(\n signals: JobExecutionSignals,\n deadline: number,\n includeClaim: boolean,\n): Promise<void> {\n await condition(\n () =>\n signals.finished !== undefined ||\n signals.leaseExpired ||\n (includeClaim && signals.claimed !== undefined),\n remainingMs(deadline) ?? 0,\n );\n}\n\ninterface JobExecutionResolution {\n input: JobExecutionOrchestrationInput;\n runningVersion: number;\n}\n\nasync function resolveFinishedJobExecution({\n input,\n runningVersion,\n status,\n}: JobExecutionResolution & {\n status: RuntimeCompletionStatus;\n}): Promise<JobExecutionOrchestrationResult> {\n await setJobExecutionStatus({\n jobExecutionId: input.jobExecutionId,\n status: jobExecutionStatusForRuntimeStatus(status),\n version: runningVersion,\n statusReason: status === 'failed' ? 'step_failed' : null,\n });\n if (input.resolveJobStatus === false) {\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'finished',\n status,\n });\n return {status, jobVersion: input.jobVersion};\n }\n const resolved = await resolveJobStatusOrFailClosed(input);\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'finished',\n status: resolved.status,\n });\n return resolved;\n}\n\nfunction jobExecutionStatusForRuntimeStatus(\n status: RuntimeCompletionStatus,\n): 'succeeded' | 'failed' | 'cancelled' {\n if (status === 'succeeded' || status === 'failed' || status === 'cancelled') return status;\n throw ApplicationFailure.nonRetryable(\n `Job execution cannot be marked ${status}`,\n 'InvalidJobExecutionStatusError',\n );\n}\n\nasync function resolveLeaseExpiredJobExecution({\n input,\n runningVersion,\n}: JobExecutionResolution): Promise<JobExecutionOrchestrationResult> {\n const leaseExpired = await resolveLeaseExpiredJobExecutionActivity({\n jobExecutionId: input.jobExecutionId,\n expectedVersion: runningVersion,\n });\n if (input.resolveJobStatus === false) {\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'lease_expired',\n status: leaseExpired.status,\n });\n return {status: leaseExpired.status, jobVersion: input.jobVersion};\n }\n const {status, jobVersion} = await resolveJobStatusOrFailClosed(input);\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'lease_expired',\n status,\n });\n return {status, jobVersion};\n}\n\n// Timeout backstop. The activity atomically fails the execution, marks `timed_out_at`, and\n// enqueues the generic terminal execution fact. The runners subscriber then asks the runner to\n// cancel. The lease is intentionally NOT released here.\nasync function resolveTimedOutJobExecution({\n input,\n runningVersion,\n}: JobExecutionResolution): Promise<JobExecutionOrchestrationResult> {\n await failJobExecutionAsTimedOutActivity({\n jobExecutionId: input.jobExecutionId,\n runAttemptId: input.runAttemptId,\n expectedVersion: runningVersion,\n });\n await bulkSetStepStatuses({jobExecutionId: input.jobExecutionId, status: 'failed'});\n if (input.resolveJobStatus === false) {\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'max_duration',\n status: 'failed',\n });\n return {status: 'failed', jobVersion: input.jobVersion};\n }\n const {jobVersion} = await resolveJobStatusOrFailClosed(input);\n log.info('job execution terminated', {\n jobId: input.jobId,\n jobExecutionId: input.jobExecutionId,\n terminationReason: 'max_duration',\n status: 'failed',\n });\n return {status: 'failed', jobVersion};\n}\n\nexport async function jobExecutionOrchestration(\n input: JobExecutionOrchestrationInput,\n): Promise<JobExecutionOrchestrationResult> {\n const signals: JobExecutionSignals = {\n finished: undefined,\n leaseExpired: false,\n claimed: undefined,\n };\n // Register every signal before enqueue can block or publish a claim/outcome event. The\n // handlers retain signals that arrive while the enqueue activity is in flight.\n registerJobExecutionSignalHandlers(input.jobExecutionId, signals);\n const queued = await queueJobExecution(input);\n if (queued.kind === 'terminal') {\n return {status: queued.result.status, jobVersion: input.jobVersion};\n }\n\n const timeoutMs = input.executionTimeoutMs ?? DEFAULT_EXECUTION_MAX_DURATION_MS;\n const deadline = Date.now() + timeoutMs;\n await waitForJobExecutionSignal(signals, deadline, true);\n\n // A terminal fact wins over claim even when both signals arrive before the condition\n // resumes. This prevents a late claim from reopening an execution that already finished.\n let resolution = resolveJobExecutionOutcomeSignal(signals);\n if (resolution === 'finished') {\n const {finished} = signals;\n if (finished === undefined) throw new Error('Missing finished signal for finished resolution');\n\n return resolveFinishedJobExecution({\n input,\n runningVersion: input.executionVersion,\n status: finished.status,\n });\n }\n if (resolution === 'lease-expired') {\n return resolveLeaseExpiredJobExecution({input, runningVersion: input.executionVersion});\n }\n if (!signals.claimed) {\n return resolveTimedOutJobExecution({input, runningVersion: input.executionVersion});\n }\n\n const running = await markJobExecutionRunning(input);\n if (running.kind === 'terminal') {\n if (input.resolveJobStatus === false) {\n return {status: running.result.status, jobVersion: input.jobVersion};\n }\n return running.result;\n }\n const {runningVersion} = running;\n\n await waitForJobExecutionSignal(signals, deadline, false);\n resolution = resolveJobExecutionOutcomeSignal(signals);\n if (resolution === 'finished') {\n const {finished} = signals;\n if (finished === undefined) throw new Error('Missing finished signal for finished resolution');\n return resolveFinishedJobExecution({input, runningVersion, status: finished.status});\n }\n if (resolution === 'lease-expired') {\n return resolveLeaseExpiredJobExecution({input, runningVersion});\n }\n return resolveTimedOutJobExecution({input, runningVersion});\n}\n"],"names":["ApplicationFailure","condition","defineSignal","log","proxyActivities","setHandler","hasNoRequiredRunnerLabels","jobExecutionStartOutcome","resolveJobExecutionOutcomeSignal","JOB_CLAIMED_SIGNAL","JOB_FINISHED_SIGNAL","JOB_LEASE_EXPIRED_SIGNAL","remainingMs","setJobStatus","setJobExecutionStatus","queueJobExecutionActivity","bulkSetStepStatuses","failJobExecutionAsTimedOutActivity","resolveLeaseExpiredJobExecutionActivity","startToCloseTimeout","resolveJobStatusFromJobExecutionsActivity","retry","maximumAttempts","DEFAULT_EXECUTION_MAX_DURATION_MS","jobFinishedSignal","jobLeaseExpiredSignal","jobClaimedSignal","resolveJobStatusOrFailClosed","input","jobId","err","error","jobExecutionId","String","newVersion","status","version","jobVersion","statusReason","queueJobExecution","requiredLabels","nonRetryable","markJobExecutionRunning","runningVersion","executionVersion","start","kind","registerJobExecutionSignalHandlers","signals","payload","undefined","finished","leaseExpired","claimed","waitForJobExecutionSignal","deadline","includeClaim","resolveFinishedJobExecution","jobExecutionStatusForRuntimeStatus","resolveJobStatus","info","terminationReason","resolved","resolveLeaseExpiredJobExecution","expectedVersion","resolveTimedOutJobExecution","runAttemptId","jobExecutionOrchestration","queued","result","timeoutMs","executionTimeoutMs","Date","now","resolution","Error","running"],"mappings":"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"}
|
|
@@ -3,9 +3,6 @@ import type { RuntimeCompletionStatus } from '#core/workflow-scheduling/runtime-
|
|
|
3
3
|
export declare const listenerEventsAvailableSignal: import("@temporalio/workflow").SignalDefinition<[], string>;
|
|
4
4
|
export declare const listenerResolveSignal: import("@temporalio/workflow").SignalDefinition<[], string>;
|
|
5
5
|
export interface JobListenerOrchestrationInput {
|
|
6
|
-
workspaceId: string;
|
|
7
|
-
workflowRunId: string;
|
|
8
|
-
projectId: string;
|
|
9
6
|
runAttemptId: string;
|
|
10
7
|
jobId: string;
|
|
11
8
|
jobVersion: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-listener-orchestration.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/job-listener-orchestration.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"job-listener-orchestration.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/job-listener-orchestration.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,uBAAuB,CAAC;AAE5D,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,0CAA0C,CAAC;AAiBtF,eAAO,MAAM,6BAA6B,6DAAqD,CAAC;AAChG,eAAO,MAAM,qBAAqB,6DAA4C,CAAC;AAE/E,MAAM,WAAW,6BAA6B;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/C,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,SAAS,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,CAAC;IACnD,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACzC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3C,YAAY,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAC;CACtD;AAED,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,uBAAuB,CAAC;IAChC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,KAAK,eAAe,GAAG,OAAO,CAAC,gBAAgB,EAAE,WAAW,CAAC,GAAG,SAAS,CAAC;AAG1E,MAAM,WAAW,yBAAyB;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,eAAO,MAAM,qCAAqC,MAAM,CAAC;AAwBzD,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,6BAA6B,GACnC,OAAO,CAAC,8BAA8B,CAAC,CAuIzC;AAiCD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,sBAAsB,EAAE,OAAO,CAAC;CACjC,GAAG,OAAO,CAKV;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,6BAA6B,EACpC,YAAY,EAAE,yBAAyB,GACtC,6BAA6B,CAE/B"}
|
|
@@ -3,7 +3,7 @@ import { runtimeStatusForTerminalJobExecutionStatus } from '#core/job-execution-
|
|
|
3
3
|
import { LISTENER_EVENTS_AVAILABLE_SIGNAL, LISTENER_RESOLVE_SIGNAL } from '../constants.js';
|
|
4
4
|
import { deadlineReached, remainingMs } from './deadline.js';
|
|
5
5
|
import { jobExecutionOrchestration } from './job-execution-orchestration.js';
|
|
6
|
-
const { activateJobListenerActivity, drainListenerEventsActivity, peekListenerBufferActivity, resolveJobListenerActivity, settleListenerJobExecutionActivity, recordListenerFiringOutcomeActivity
|
|
6
|
+
const { activateJobListenerActivity, drainListenerEventsActivity, peekListenerBufferActivity, resolveJobListenerActivity, settleListenerJobExecutionActivity, recordListenerFiringOutcomeActivity } = proxyActivities({
|
|
7
7
|
startToCloseTimeout: '30s'
|
|
8
8
|
});
|
|
9
9
|
export const listenerEventsAvailableSignal = defineSignal(LISTENER_EVENTS_AVAILABLE_SIGNAL);
|
|
@@ -256,9 +256,6 @@ async function runListenerExecution(params) {
|
|
|
256
256
|
workflowIdReusePolicy: 'ALLOW_DUPLICATE',
|
|
257
257
|
args: [
|
|
258
258
|
{
|
|
259
|
-
workspaceId: params.input.workspaceId,
|
|
260
|
-
workflowRunId: params.input.workflowRunId,
|
|
261
|
-
projectId: params.input.projectId,
|
|
262
259
|
jobId: params.input.jobId,
|
|
263
260
|
jobExecutionId: params.jobExecutionId,
|
|
264
261
|
runAttemptId: params.input.runAttemptId,
|
|
@@ -287,11 +284,6 @@ async function runListenerExecution(params) {
|
|
|
287
284
|
await recordListenerFiringOutcomeActivity({
|
|
288
285
|
outcome: 'cancelled'
|
|
289
286
|
});
|
|
290
|
-
await cancelRunnerJobsActivity({
|
|
291
|
-
jobIds: [
|
|
292
|
-
params.input.jobId
|
|
293
|
-
]
|
|
294
|
-
});
|
|
295
287
|
return;
|
|
296
288
|
}
|
|
297
289
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/temporal/workflows/job-listener-orchestration.ts"],"sourcesContent":["import {\n CancellationScope,\n condition,\n continueAsNew,\n defineSignal,\n executeChild,\n log,\n ParentClosePolicy,\n proxyActivities,\n setHandler,\n workflowInfo,\n} from '@temporalio/workflow';\nimport type {ResolutionReason} from '#core/entities/job.js';\nimport {runtimeStatusForTerminalJobExecutionStatus} from '#core/job-execution-outcome.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\nimport type {createOrchestrationActivities} from '../activities/index.js';\nimport {LISTENER_EVENTS_AVAILABLE_SIGNAL, LISTENER_RESOLVE_SIGNAL} from '../constants.js';\nimport {deadlineReached, remainingMs} from './deadline.js';\nimport {jobExecutionOrchestration} from './job-execution-orchestration.js';\n\nconst {\n activateJobListenerActivity,\n drainListenerEventsActivity,\n peekListenerBufferActivity,\n resolveJobListenerActivity,\n settleListenerJobExecutionActivity,\n recordListenerFiringOutcomeActivity,\n cancelRunnerJobsActivity,\n} = proxyActivities<ReturnType<typeof createOrchestrationActivities>>({\n startToCloseTimeout: '30s',\n});\n\nexport const listenerEventsAvailableSignal = defineSignal<[]>(LISTENER_EVENTS_AVAILABLE_SIGNAL);\nexport const listenerResolveSignal = defineSignal<[]>(LISTENER_RESOLVE_SIGNAL);\n\nexport interface JobListenerOrchestrationInput {\n workspaceId: string;\n workflowRunId: string;\n projectId: string;\n runAttemptId: string;\n jobId: string;\n jobVersion: number;\n requiredLabels: string[];\n executionTimeoutMs?: number | null | undefined;\n listeningTimeoutMs?: number | null | undefined;\n maxExecutions?: number | null | undefined;\n onResolve?: 'finish' | 'cancel' | null | undefined;\n batchDebounceMs?: number | null | undefined;\n batchMaxSize?: number | null | undefined;\n batchMaxWaitMs?: number | null | undefined;\n continuation?: ListenerContinuationState | undefined;\n}\n\nexport interface JobListenerOrchestrationResult {\n status: RuntimeCompletionStatus;\n jobVersion: number;\n}\n\ntype ResolutionLatch = Exclude<ResolutionReason, 'cancelled'> | undefined;\ntype BatchFiringDecision = 'fire' | 'resolve' | 'deadline';\n\nexport interface ListenerContinuationState {\n nextSequence: number;\n latchedReason?: ResolutionLatch;\n listenerDeadline?: number | undefined;\n}\n\nexport const LISTENER_CONTINUE_AS_NEW_FIRING_LIMIT = 500;\n\ninterface ListenerBatchConfig {\n debounceMs?: number | undefined;\n maxSizeEvents?: number | undefined;\n maxWaitMs?: number | undefined;\n}\n\ninterface BatchFiringWindowParams {\n jobId: string;\n batchConfig: ListenerBatchConfig;\n listenerDeadline: number | undefined;\n hasEventsHint: () => boolean;\n clearEventsHint: () => void;\n hasResolutionHint: () => boolean;\n}\n\ninterface ListenerBufferPeek {\n fireCount: number;\n resolvePending: boolean;\n oldestAgeMs: number;\n newestAgeMs: number;\n}\n\nexport async function jobListenerOrchestration(\n input: JobListenerOrchestrationInput,\n): Promise<JobListenerOrchestrationResult> {\n let eventsAvailable = false;\n let latchedReason = input.continuation?.latchedReason;\n\n setHandler(listenerEventsAvailableSignal, () => {\n eventsAvailable = true;\n });\n setHandler(listenerResolveSignal, () => {\n latchedReason = 'until';\n });\n\n const listenerDeadline = input.continuation?.listenerDeadline ?? initialListenerDeadline(input);\n\n let nextSequence: number;\n if (input.continuation) {\n nextSequence = input.continuation.nextSequence;\n } else {\n const activated = await activateJobListenerActivity({\n jobId: input.jobId,\n expectedVersion: input.jobVersion,\n });\n if (activated.status === 'terminal') {\n return {\n status: runtimeStatusForTerminalJobExecutionStatus(activated.jobStatus),\n jobVersion: activated.jobVersion,\n };\n }\n nextSequence = activated.executionCount + 1;\n }\n\n let firingsInCurrentRun = 0;\n const maxExecutions = input.maxExecutions ?? undefined;\n const batchConfig = listenerBatchConfig(input);\n while (true) {\n if (deadlineReached(listenerDeadline)) latchedReason ??= 'timeout';\n await continueListenerAsNewIfNeeded({\n input,\n nextSequence,\n latchedReason,\n listenerDeadline,\n firingsInCurrentRun,\n });\n if (latchedReason !== undefined) break;\n if (maxExecutions !== undefined) {\n if (nextSequence > maxExecutions) {\n latchedReason = 'max_executions';\n await continueListenerAsNewIfNeeded({\n input,\n nextSequence,\n latchedReason,\n listenerDeadline,\n firingsInCurrentRun,\n });\n break;\n }\n }\n\n if (batchConfig !== undefined) {\n const decision = await awaitBatchFiringWindow({\n jobId: input.jobId,\n batchConfig,\n listenerDeadline,\n hasEventsHint: () => eventsAvailable,\n clearEventsHint: () => {\n eventsAvailable = false;\n },\n hasResolutionHint: () => latchedReason !== undefined,\n });\n if (decision === 'resolve') {\n latchedReason ??= 'until';\n break;\n }\n if (decision === 'deadline') {\n latchedReason ??= 'timeout';\n break;\n }\n }\n\n eventsAvailable = false;\n const drained = await drainListenerEventsActivity({\n jobId: input.jobId,\n expectedSequence: nextSequence,\n ...(batchConfig?.maxSizeEvents === undefined ? {} : {maxSize: batchConfig.maxSizeEvents}),\n });\n\n if (drained.kind === 'resolve-requested') {\n latchedReason = 'until';\n break;\n }\n\n if (drained.kind === 'empty') {\n const woke = await waitForListenerWakeup(\n () => eventsAvailable || latchedReason !== undefined,\n {deadline: listenerDeadline},\n );\n if (!woke && deadlineReached(listenerDeadline)) latchedReason = 'timeout';\n continue;\n }\n\n if (drained.status === 'failed') {\n await recordListenerFiringOutcomeActivity({outcome: 'failed'});\n nextSequence = drained.sequence + 1;\n firingsInCurrentRun += 1;\n if (maxExecutions !== undefined && drained.sequence >= maxExecutions) {\n latchedReason = 'max_executions';\n }\n continue;\n }\n\n await runListenerExecution({\n input,\n jobExecutionId: drained.jobExecutionId,\n executionVersion: drained.executionVersion,\n requiredLabels: drained.requiredLabels,\n shouldCancelForResolution: () =>\n input.onResolve === 'cancel' &&\n (latchedReason !== undefined || deadlineReached(listenerDeadline)),\n waitForResolution: () =>\n waitForListenerWakeup(\n () => latchedReason !== undefined || deadlineReached(listenerDeadline),\n {deadline: listenerDeadline},\n ),\n });\n\n if (deadlineReached(listenerDeadline)) latchedReason ??= 'timeout';\n nextSequence = drained.sequence + 1;\n firingsInCurrentRun += 1;\n if (maxExecutions !== undefined && drained.sequence >= maxExecutions) {\n latchedReason = 'max_executions';\n }\n }\n\n const reason = latchedReason ?? 'timeout';\n const resolved = await resolveJobListenerActivity({jobId: input.jobId, reason});\n return {status: resolved.status, jobVersion: resolved.jobVersion};\n}\n\nfunction initialListenerDeadline(input: JobListenerOrchestrationInput): number | undefined {\n return input.listeningTimeoutMs === undefined || input.listeningTimeoutMs === null\n ? undefined\n : Date.now() + input.listeningTimeoutMs;\n}\n\nasync function continueListenerAsNewIfNeeded(params: {\n input: JobListenerOrchestrationInput;\n nextSequence: number;\n latchedReason: ResolutionLatch;\n listenerDeadline: number | undefined;\n firingsInCurrentRun: number;\n}): Promise<void> {\n if (\n !shouldContinueListenerAsNew({\n firingsInCurrentRun: params.firingsInCurrentRun,\n continueAsNewSuggested: workflowInfo().continueAsNewSuggested,\n })\n ) {\n return;\n }\n\n await continueAsNew<typeof jobListenerOrchestration>(\n listenerContinuationInput(params.input, {\n nextSequence: params.nextSequence,\n latchedReason: params.latchedReason,\n listenerDeadline: params.listenerDeadline,\n }),\n );\n}\n\nexport function shouldContinueListenerAsNew(params: {\n firingsInCurrentRun: number;\n continueAsNewSuggested: boolean;\n}): boolean {\n return (\n params.continueAsNewSuggested ||\n params.firingsInCurrentRun >= LISTENER_CONTINUE_AS_NEW_FIRING_LIMIT\n );\n}\n\nexport function listenerContinuationInput(\n input: JobListenerOrchestrationInput,\n continuation: ListenerContinuationState,\n): JobListenerOrchestrationInput {\n return {...input, continuation};\n}\n\nfunction listenerBatchConfig(\n input: JobListenerOrchestrationInput,\n): ListenerBatchConfig | undefined {\n const debounceMs = positiveNumber(input.batchDebounceMs);\n const maxSizeEvents = positiveNumber(input.batchMaxSize);\n const maxWaitMs = positiveNumber(input.batchMaxWaitMs);\n if (debounceMs === undefined && maxSizeEvents === undefined && maxWaitMs === undefined) {\n return undefined;\n }\n return {debounceMs, maxSizeEvents, maxWaitMs};\n}\n\nasync function awaitBatchFiringWindow(\n params: BatchFiringWindowParams,\n): Promise<BatchFiringDecision> {\n while (true) {\n const prePeekDecision = resolutionOrDeadlineDecision(params);\n if (prePeekDecision !== undefined) return prePeekDecision;\n\n const peek = await peekBatchBuffer(params);\n const peekDecision = bufferedResolveOrDeadlineDecision(params, peek);\n if (peekDecision !== undefined) return peekDecision;\n\n if (peek.fireCount === 0) {\n const waitDecision = await waitForAnyBatchWakeup(params);\n if (waitDecision !== undefined) return waitDecision;\n continue;\n }\n\n if (batchIsReadyToFire(params.batchConfig, peek)) return 'fire';\n\n const sleepMs = nextBatchWindowMs(params.batchConfig, peek);\n if (sleepMs === undefined) {\n const waitDecision = await waitForAnyBatchWakeup(params);\n if (waitDecision !== undefined) return waitDecision;\n continue;\n }\n\n const waitDecision = await waitForBatchWindow(params, sleepMs);\n if (waitDecision !== undefined) return waitDecision;\n }\n}\n\nfunction resolutionOrDeadlineDecision(\n params: BatchFiringWindowParams,\n): Exclude<BatchFiringDecision, 'fire'> | undefined {\n if (params.hasResolutionHint()) return 'resolve';\n if (deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nasync function peekBatchBuffer(params: BatchFiringWindowParams): Promise<ListenerBufferPeek> {\n params.clearEventsHint();\n return await peekListenerBufferActivity({jobId: params.jobId});\n}\n\nfunction bufferedResolveOrDeadlineDecision(\n params: BatchFiringWindowParams,\n peek: ListenerBufferPeek,\n): Exclude<BatchFiringDecision, 'fire'> | undefined {\n if (peek.resolvePending || params.hasResolutionHint()) return 'resolve';\n if (deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nfunction batchIsReadyToFire(config: ListenerBatchConfig, peek: ListenerBufferPeek): boolean {\n const sizeReached = config.maxSizeEvents !== undefined && peek.fireCount >= config.maxSizeEvents;\n const debounceQuiet = config.debounceMs !== undefined && peek.newestAgeMs >= config.debounceMs;\n const maxWaitReached = config.maxWaitMs !== undefined && peek.oldestAgeMs >= config.maxWaitMs;\n return sizeReached || debounceQuiet || maxWaitReached;\n}\n\nfunction nextBatchWindowMs(\n config: ListenerBatchConfig,\n peek: ListenerBufferPeek,\n): number | undefined {\n const timeWindows = [\n remainingWindowMs(config.debounceMs, peek.newestAgeMs),\n remainingWindowMs(config.maxWaitMs, peek.oldestAgeMs),\n ].filter((value): value is number => value !== undefined);\n return timeWindows.length === 0 ? undefined : Math.min(...timeWindows);\n}\n\nasync function waitForAnyBatchWakeup(\n params: BatchFiringWindowParams,\n): Promise<Exclude<BatchFiringDecision, 'fire'> | undefined> {\n const woke = await waitForListenerWakeup(\n () => params.hasEventsHint() || params.hasResolutionHint(),\n {deadline: params.listenerDeadline},\n );\n if (!woke && deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nasync function waitForBatchWindow(\n params: BatchFiringWindowParams,\n sleepMs: number,\n): Promise<Exclude<BatchFiringDecision, 'fire'> | undefined> {\n const deadlineRemaining = remainingMs(params.listenerDeadline);\n const boundedSleepMs =\n deadlineRemaining === undefined ? sleepMs : Math.min(sleepMs, deadlineRemaining);\n const wakesOnEvents =\n params.batchConfig.debounceMs !== undefined || params.batchConfig.maxSizeEvents !== undefined;\n const woke = await condition(\n () =>\n params.hasResolutionHint() ||\n (wakesOnEvents && params.hasEventsHint()) ||\n deadlineReached(params.listenerDeadline),\n boundedSleepMs,\n );\n if (!woke && deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nfunction positiveNumber(value: number | null | undefined): number | undefined {\n return value === undefined || value === null || value <= 0 ? undefined : value;\n}\n\nfunction remainingWindowMs(limitMs: number | undefined, ageMs: number): number | undefined {\n return limitMs === undefined ? undefined : Math.max(0, limitMs - ageMs);\n}\n\nasync function runListenerExecution(params: {\n input: JobListenerOrchestrationInput;\n jobExecutionId: string;\n executionVersion: number;\n requiredLabels: string[];\n shouldCancelForResolution: () => boolean;\n waitForResolution: () => Promise<boolean>;\n}): Promise<void> {\n const scope = new CancellationScope();\n const child = scope.run(() =>\n executeChild(jobExecutionOrchestration, {\n workflowId: `job:${params.input.jobId}`,\n workflowIdReusePolicy: 'ALLOW_DUPLICATE',\n args: [\n {\n workspaceId: params.input.workspaceId,\n workflowRunId: params.input.workflowRunId,\n projectId: params.input.projectId,\n jobId: params.input.jobId,\n jobExecutionId: params.jobExecutionId,\n runAttemptId: params.input.runAttemptId,\n jobVersion: params.input.jobVersion,\n executionVersion: params.executionVersion,\n ...(params.input.executionTimeoutMs === undefined\n ? {}\n : {executionTimeoutMs: params.input.executionTimeoutMs}),\n resolveJobStatus: false,\n requiredLabels: params.requiredLabels,\n },\n ],\n parentClosePolicy: ParentClosePolicy.TERMINATE,\n }),\n );\n\n if (params.input.onResolve === 'cancel') {\n const winner = await Promise.race([\n child.then(\n () => 'child' as const,\n () => 'child-failed' as const,\n ),\n params.waitForResolution().then(() => 'resolution' as const),\n ]);\n if (winner === 'resolution' && params.shouldCancelForResolution()) {\n scope.cancel();\n await settleListenerJobExecutionActivity({\n jobExecutionId: params.jobExecutionId,\n status: 'cancelled',\n });\n await recordListenerFiringOutcomeActivity({outcome: 'cancelled'});\n await cancelRunnerJobsActivity({jobIds: [params.input.jobId]});\n return;\n }\n }\n\n try {\n const result = await child;\n await recordListenerFiringOutcomeActivity({outcome: listenerFiringOutcome(result.status)});\n } catch (error) {\n log.warn('listener execution child failed; recording failed firing and continuing', {\n jobId: params.input.jobId,\n jobExecutionId: params.jobExecutionId,\n error: String(error),\n });\n await settleListenerJobExecutionActivity({\n jobExecutionId: params.jobExecutionId,\n status: 'failed',\n });\n await recordListenerFiringOutcomeActivity({outcome: 'failed'});\n }\n}\n\nfunction listenerFiringOutcome(\n status: RuntimeCompletionStatus,\n): 'succeeded' | 'failed' | 'cancelled' {\n if (status === 'succeeded' || status === 'failed' || status === 'cancelled') return status;\n throw new Error(`Listener execution cannot finish with status: ${status}`);\n}\n\nasync function waitForListenerWakeup(\n predicate: () => boolean,\n options: {deadline: number | undefined},\n): Promise<boolean> {\n const remaining = remainingMs(options.deadline);\n if (remaining !== undefined && remaining <= 0) return false;\n if (remaining === undefined) {\n await condition(predicate);\n return true;\n }\n return await condition(predicate, remaining);\n}\n"],"names":["CancellationScope","condition","continueAsNew","defineSignal","executeChild","log","ParentClosePolicy","proxyActivities","setHandler","workflowInfo","runtimeStatusForTerminalJobExecutionStatus","LISTENER_EVENTS_AVAILABLE_SIGNAL","LISTENER_RESOLVE_SIGNAL","deadlineReached","remainingMs","jobExecutionOrchestration","activateJobListenerActivity","drainListenerEventsActivity","peekListenerBufferActivity","resolveJobListenerActivity","settleListenerJobExecutionActivity","recordListenerFiringOutcomeActivity","cancelRunnerJobsActivity","startToCloseTimeout","listenerEventsAvailableSignal","listenerResolveSignal","LISTENER_CONTINUE_AS_NEW_FIRING_LIMIT","jobListenerOrchestration","input","eventsAvailable","latchedReason","continuation","listenerDeadline","initialListenerDeadline","nextSequence","activated","jobId","expectedVersion","jobVersion","status","jobStatus","executionCount","firingsInCurrentRun","maxExecutions","undefined","batchConfig","listenerBatchConfig","continueListenerAsNewIfNeeded","decision","awaitBatchFiringWindow","hasEventsHint","clearEventsHint","hasResolutionHint","drained","expectedSequence","maxSizeEvents","maxSize","kind","woke","waitForListenerWakeup","deadline","outcome","sequence","runListenerExecution","jobExecutionId","executionVersion","requiredLabels","shouldCancelForResolution","onResolve","waitForResolution","reason","resolved","listeningTimeoutMs","Date","now","params","shouldContinueListenerAsNew","continueAsNewSuggested","listenerContinuationInput","debounceMs","positiveNumber","batchDebounceMs","batchMaxSize","maxWaitMs","batchMaxWaitMs","prePeekDecision","resolutionOrDeadlineDecision","peek","peekBatchBuffer","peekDecision","bufferedResolveOrDeadlineDecision","fireCount","waitDecision","waitForAnyBatchWakeup","batchIsReadyToFire","sleepMs","nextBatchWindowMs","waitForBatchWindow","resolvePending","config","sizeReached","debounceQuiet","newestAgeMs","maxWaitReached","oldestAgeMs","timeWindows","remainingWindowMs","filter","value","length","Math","min","deadlineRemaining","boundedSleepMs","wakesOnEvents","limitMs","ageMs","max","scope","child","run","workflowId","workflowIdReusePolicy","args","workspaceId","workflowRunId","projectId","runAttemptId","executionTimeoutMs","resolveJobStatus","parentClosePolicy","TERMINATE","winner","Promise","race","then","cancel","jobIds","result","listenerFiringOutcome","error","warn","String","Error","predicate","options","remaining"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/workflows/job-listener-orchestration.ts"],"sourcesContent":["import {\n CancellationScope,\n condition,\n continueAsNew,\n defineSignal,\n executeChild,\n log,\n ParentClosePolicy,\n proxyActivities,\n setHandler,\n workflowInfo,\n} from '@temporalio/workflow';\nimport type {ResolutionReason} from '#core/entities/job.js';\nimport {runtimeStatusForTerminalJobExecutionStatus} from '#core/job-execution-outcome.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\nimport type {createOrchestrationActivities} from '../activities/index.js';\nimport {LISTENER_EVENTS_AVAILABLE_SIGNAL, LISTENER_RESOLVE_SIGNAL} from '../constants.js';\nimport {deadlineReached, remainingMs} from './deadline.js';\nimport {jobExecutionOrchestration} from './job-execution-orchestration.js';\n\nconst {\n activateJobListenerActivity,\n drainListenerEventsActivity,\n peekListenerBufferActivity,\n resolveJobListenerActivity,\n settleListenerJobExecutionActivity,\n recordListenerFiringOutcomeActivity,\n} = proxyActivities<ReturnType<typeof createOrchestrationActivities>>({\n startToCloseTimeout: '30s',\n});\n\nexport const listenerEventsAvailableSignal = defineSignal<[]>(LISTENER_EVENTS_AVAILABLE_SIGNAL);\nexport const listenerResolveSignal = defineSignal<[]>(LISTENER_RESOLVE_SIGNAL);\n\nexport interface JobListenerOrchestrationInput {\n runAttemptId: string;\n jobId: string;\n jobVersion: number;\n requiredLabels: string[];\n executionTimeoutMs?: number | null | undefined;\n listeningTimeoutMs?: number | null | undefined;\n maxExecutions?: number | null | undefined;\n onResolve?: 'finish' | 'cancel' | null | undefined;\n batchDebounceMs?: number | null | undefined;\n batchMaxSize?: number | null | undefined;\n batchMaxWaitMs?: number | null | undefined;\n continuation?: ListenerContinuationState | undefined;\n}\n\nexport interface JobListenerOrchestrationResult {\n status: RuntimeCompletionStatus;\n jobVersion: number;\n}\n\ntype ResolutionLatch = Exclude<ResolutionReason, 'cancelled'> | undefined;\ntype BatchFiringDecision = 'fire' | 'resolve' | 'deadline';\n\nexport interface ListenerContinuationState {\n nextSequence: number;\n latchedReason?: ResolutionLatch;\n listenerDeadline?: number | undefined;\n}\n\nexport const LISTENER_CONTINUE_AS_NEW_FIRING_LIMIT = 500;\n\ninterface ListenerBatchConfig {\n debounceMs?: number | undefined;\n maxSizeEvents?: number | undefined;\n maxWaitMs?: number | undefined;\n}\n\ninterface BatchFiringWindowParams {\n jobId: string;\n batchConfig: ListenerBatchConfig;\n listenerDeadline: number | undefined;\n hasEventsHint: () => boolean;\n clearEventsHint: () => void;\n hasResolutionHint: () => boolean;\n}\n\ninterface ListenerBufferPeek {\n fireCount: number;\n resolvePending: boolean;\n oldestAgeMs: number;\n newestAgeMs: number;\n}\n\nexport async function jobListenerOrchestration(\n input: JobListenerOrchestrationInput,\n): Promise<JobListenerOrchestrationResult> {\n let eventsAvailable = false;\n let latchedReason = input.continuation?.latchedReason;\n\n setHandler(listenerEventsAvailableSignal, () => {\n eventsAvailable = true;\n });\n setHandler(listenerResolveSignal, () => {\n latchedReason = 'until';\n });\n\n const listenerDeadline = input.continuation?.listenerDeadline ?? initialListenerDeadline(input);\n\n let nextSequence: number;\n if (input.continuation) {\n nextSequence = input.continuation.nextSequence;\n } else {\n const activated = await activateJobListenerActivity({\n jobId: input.jobId,\n expectedVersion: input.jobVersion,\n });\n if (activated.status === 'terminal') {\n return {\n status: runtimeStatusForTerminalJobExecutionStatus(activated.jobStatus),\n jobVersion: activated.jobVersion,\n };\n }\n nextSequence = activated.executionCount + 1;\n }\n\n let firingsInCurrentRun = 0;\n const maxExecutions = input.maxExecutions ?? undefined;\n const batchConfig = listenerBatchConfig(input);\n while (true) {\n if (deadlineReached(listenerDeadline)) latchedReason ??= 'timeout';\n await continueListenerAsNewIfNeeded({\n input,\n nextSequence,\n latchedReason,\n listenerDeadline,\n firingsInCurrentRun,\n });\n if (latchedReason !== undefined) break;\n if (maxExecutions !== undefined) {\n if (nextSequence > maxExecutions) {\n latchedReason = 'max_executions';\n await continueListenerAsNewIfNeeded({\n input,\n nextSequence,\n latchedReason,\n listenerDeadline,\n firingsInCurrentRun,\n });\n break;\n }\n }\n\n if (batchConfig !== undefined) {\n const decision = await awaitBatchFiringWindow({\n jobId: input.jobId,\n batchConfig,\n listenerDeadline,\n hasEventsHint: () => eventsAvailable,\n clearEventsHint: () => {\n eventsAvailable = false;\n },\n hasResolutionHint: () => latchedReason !== undefined,\n });\n if (decision === 'resolve') {\n latchedReason ??= 'until';\n break;\n }\n if (decision === 'deadline') {\n latchedReason ??= 'timeout';\n break;\n }\n }\n\n eventsAvailable = false;\n const drained = await drainListenerEventsActivity({\n jobId: input.jobId,\n expectedSequence: nextSequence,\n ...(batchConfig?.maxSizeEvents === undefined ? {} : {maxSize: batchConfig.maxSizeEvents}),\n });\n\n if (drained.kind === 'resolve-requested') {\n latchedReason = 'until';\n break;\n }\n\n if (drained.kind === 'empty') {\n const woke = await waitForListenerWakeup(\n () => eventsAvailable || latchedReason !== undefined,\n {deadline: listenerDeadline},\n );\n if (!woke && deadlineReached(listenerDeadline)) latchedReason = 'timeout';\n continue;\n }\n\n if (drained.status === 'failed') {\n await recordListenerFiringOutcomeActivity({outcome: 'failed'});\n nextSequence = drained.sequence + 1;\n firingsInCurrentRun += 1;\n if (maxExecutions !== undefined && drained.sequence >= maxExecutions) {\n latchedReason = 'max_executions';\n }\n continue;\n }\n\n await runListenerExecution({\n input,\n jobExecutionId: drained.jobExecutionId,\n executionVersion: drained.executionVersion,\n requiredLabels: drained.requiredLabels,\n shouldCancelForResolution: () =>\n input.onResolve === 'cancel' &&\n (latchedReason !== undefined || deadlineReached(listenerDeadline)),\n waitForResolution: () =>\n waitForListenerWakeup(\n () => latchedReason !== undefined || deadlineReached(listenerDeadline),\n {deadline: listenerDeadline},\n ),\n });\n\n if (deadlineReached(listenerDeadline)) latchedReason ??= 'timeout';\n nextSequence = drained.sequence + 1;\n firingsInCurrentRun += 1;\n if (maxExecutions !== undefined && drained.sequence >= maxExecutions) {\n latchedReason = 'max_executions';\n }\n }\n\n const reason = latchedReason ?? 'timeout';\n const resolved = await resolveJobListenerActivity({jobId: input.jobId, reason});\n return {status: resolved.status, jobVersion: resolved.jobVersion};\n}\n\nfunction initialListenerDeadline(input: JobListenerOrchestrationInput): number | undefined {\n return input.listeningTimeoutMs === undefined || input.listeningTimeoutMs === null\n ? undefined\n : Date.now() + input.listeningTimeoutMs;\n}\n\nasync function continueListenerAsNewIfNeeded(params: {\n input: JobListenerOrchestrationInput;\n nextSequence: number;\n latchedReason: ResolutionLatch;\n listenerDeadline: number | undefined;\n firingsInCurrentRun: number;\n}): Promise<void> {\n if (\n !shouldContinueListenerAsNew({\n firingsInCurrentRun: params.firingsInCurrentRun,\n continueAsNewSuggested: workflowInfo().continueAsNewSuggested,\n })\n ) {\n return;\n }\n\n await continueAsNew<typeof jobListenerOrchestration>(\n listenerContinuationInput(params.input, {\n nextSequence: params.nextSequence,\n latchedReason: params.latchedReason,\n listenerDeadline: params.listenerDeadline,\n }),\n );\n}\n\nexport function shouldContinueListenerAsNew(params: {\n firingsInCurrentRun: number;\n continueAsNewSuggested: boolean;\n}): boolean {\n return (\n params.continueAsNewSuggested ||\n params.firingsInCurrentRun >= LISTENER_CONTINUE_AS_NEW_FIRING_LIMIT\n );\n}\n\nexport function listenerContinuationInput(\n input: JobListenerOrchestrationInput,\n continuation: ListenerContinuationState,\n): JobListenerOrchestrationInput {\n return {...input, continuation};\n}\n\nfunction listenerBatchConfig(\n input: JobListenerOrchestrationInput,\n): ListenerBatchConfig | undefined {\n const debounceMs = positiveNumber(input.batchDebounceMs);\n const maxSizeEvents = positiveNumber(input.batchMaxSize);\n const maxWaitMs = positiveNumber(input.batchMaxWaitMs);\n if (debounceMs === undefined && maxSizeEvents === undefined && maxWaitMs === undefined) {\n return undefined;\n }\n return {debounceMs, maxSizeEvents, maxWaitMs};\n}\n\nasync function awaitBatchFiringWindow(\n params: BatchFiringWindowParams,\n): Promise<BatchFiringDecision> {\n while (true) {\n const prePeekDecision = resolutionOrDeadlineDecision(params);\n if (prePeekDecision !== undefined) return prePeekDecision;\n\n const peek = await peekBatchBuffer(params);\n const peekDecision = bufferedResolveOrDeadlineDecision(params, peek);\n if (peekDecision !== undefined) return peekDecision;\n\n if (peek.fireCount === 0) {\n const waitDecision = await waitForAnyBatchWakeup(params);\n if (waitDecision !== undefined) return waitDecision;\n continue;\n }\n\n if (batchIsReadyToFire(params.batchConfig, peek)) return 'fire';\n\n const sleepMs = nextBatchWindowMs(params.batchConfig, peek);\n if (sleepMs === undefined) {\n const waitDecision = await waitForAnyBatchWakeup(params);\n if (waitDecision !== undefined) return waitDecision;\n continue;\n }\n\n const waitDecision = await waitForBatchWindow(params, sleepMs);\n if (waitDecision !== undefined) return waitDecision;\n }\n}\n\nfunction resolutionOrDeadlineDecision(\n params: BatchFiringWindowParams,\n): Exclude<BatchFiringDecision, 'fire'> | undefined {\n if (params.hasResolutionHint()) return 'resolve';\n if (deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nasync function peekBatchBuffer(params: BatchFiringWindowParams): Promise<ListenerBufferPeek> {\n params.clearEventsHint();\n return await peekListenerBufferActivity({jobId: params.jobId});\n}\n\nfunction bufferedResolveOrDeadlineDecision(\n params: BatchFiringWindowParams,\n peek: ListenerBufferPeek,\n): Exclude<BatchFiringDecision, 'fire'> | undefined {\n if (peek.resolvePending || params.hasResolutionHint()) return 'resolve';\n if (deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nfunction batchIsReadyToFire(config: ListenerBatchConfig, peek: ListenerBufferPeek): boolean {\n const sizeReached = config.maxSizeEvents !== undefined && peek.fireCount >= config.maxSizeEvents;\n const debounceQuiet = config.debounceMs !== undefined && peek.newestAgeMs >= config.debounceMs;\n const maxWaitReached = config.maxWaitMs !== undefined && peek.oldestAgeMs >= config.maxWaitMs;\n return sizeReached || debounceQuiet || maxWaitReached;\n}\n\nfunction nextBatchWindowMs(\n config: ListenerBatchConfig,\n peek: ListenerBufferPeek,\n): number | undefined {\n const timeWindows = [\n remainingWindowMs(config.debounceMs, peek.newestAgeMs),\n remainingWindowMs(config.maxWaitMs, peek.oldestAgeMs),\n ].filter((value): value is number => value !== undefined);\n return timeWindows.length === 0 ? undefined : Math.min(...timeWindows);\n}\n\nasync function waitForAnyBatchWakeup(\n params: BatchFiringWindowParams,\n): Promise<Exclude<BatchFiringDecision, 'fire'> | undefined> {\n const woke = await waitForListenerWakeup(\n () => params.hasEventsHint() || params.hasResolutionHint(),\n {deadline: params.listenerDeadline},\n );\n if (!woke && deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nasync function waitForBatchWindow(\n params: BatchFiringWindowParams,\n sleepMs: number,\n): Promise<Exclude<BatchFiringDecision, 'fire'> | undefined> {\n const deadlineRemaining = remainingMs(params.listenerDeadline);\n const boundedSleepMs =\n deadlineRemaining === undefined ? sleepMs : Math.min(sleepMs, deadlineRemaining);\n const wakesOnEvents =\n params.batchConfig.debounceMs !== undefined || params.batchConfig.maxSizeEvents !== undefined;\n const woke = await condition(\n () =>\n params.hasResolutionHint() ||\n (wakesOnEvents && params.hasEventsHint()) ||\n deadlineReached(params.listenerDeadline),\n boundedSleepMs,\n );\n if (!woke && deadlineReached(params.listenerDeadline)) return 'deadline';\n return undefined;\n}\n\nfunction positiveNumber(value: number | null | undefined): number | undefined {\n return value === undefined || value === null || value <= 0 ? undefined : value;\n}\n\nfunction remainingWindowMs(limitMs: number | undefined, ageMs: number): number | undefined {\n return limitMs === undefined ? undefined : Math.max(0, limitMs - ageMs);\n}\n\nasync function runListenerExecution(params: {\n input: JobListenerOrchestrationInput;\n jobExecutionId: string;\n executionVersion: number;\n requiredLabels: string[];\n shouldCancelForResolution: () => boolean;\n waitForResolution: () => Promise<boolean>;\n}): Promise<void> {\n const scope = new CancellationScope();\n const child = scope.run(() =>\n executeChild(jobExecutionOrchestration, {\n workflowId: `job:${params.input.jobId}`,\n workflowIdReusePolicy: 'ALLOW_DUPLICATE',\n args: [\n {\n jobId: params.input.jobId,\n jobExecutionId: params.jobExecutionId,\n runAttemptId: params.input.runAttemptId,\n jobVersion: params.input.jobVersion,\n executionVersion: params.executionVersion,\n ...(params.input.executionTimeoutMs === undefined\n ? {}\n : {executionTimeoutMs: params.input.executionTimeoutMs}),\n resolveJobStatus: false,\n requiredLabels: params.requiredLabels,\n },\n ],\n parentClosePolicy: ParentClosePolicy.TERMINATE,\n }),\n );\n\n if (params.input.onResolve === 'cancel') {\n const winner = await Promise.race([\n child.then(\n () => 'child' as const,\n () => 'child-failed' as const,\n ),\n params.waitForResolution().then(() => 'resolution' as const),\n ]);\n if (winner === 'resolution' && params.shouldCancelForResolution()) {\n scope.cancel();\n await settleListenerJobExecutionActivity({\n jobExecutionId: params.jobExecutionId,\n status: 'cancelled',\n });\n await recordListenerFiringOutcomeActivity({outcome: 'cancelled'});\n return;\n }\n }\n\n try {\n const result = await child;\n await recordListenerFiringOutcomeActivity({outcome: listenerFiringOutcome(result.status)});\n } catch (error) {\n log.warn('listener execution child failed; recording failed firing and continuing', {\n jobId: params.input.jobId,\n jobExecutionId: params.jobExecutionId,\n error: String(error),\n });\n await settleListenerJobExecutionActivity({\n jobExecutionId: params.jobExecutionId,\n status: 'failed',\n });\n await recordListenerFiringOutcomeActivity({outcome: 'failed'});\n }\n}\n\nfunction listenerFiringOutcome(\n status: RuntimeCompletionStatus,\n): 'succeeded' | 'failed' | 'cancelled' {\n if (status === 'succeeded' || status === 'failed' || status === 'cancelled') return status;\n throw new Error(`Listener execution cannot finish with status: ${status}`);\n}\n\nasync function waitForListenerWakeup(\n predicate: () => boolean,\n options: {deadline: number | undefined},\n): Promise<boolean> {\n const remaining = remainingMs(options.deadline);\n if (remaining !== undefined && remaining <= 0) return false;\n if (remaining === undefined) {\n await condition(predicate);\n return true;\n }\n return await condition(predicate, remaining);\n}\n"],"names":["CancellationScope","condition","continueAsNew","defineSignal","executeChild","log","ParentClosePolicy","proxyActivities","setHandler","workflowInfo","runtimeStatusForTerminalJobExecutionStatus","LISTENER_EVENTS_AVAILABLE_SIGNAL","LISTENER_RESOLVE_SIGNAL","deadlineReached","remainingMs","jobExecutionOrchestration","activateJobListenerActivity","drainListenerEventsActivity","peekListenerBufferActivity","resolveJobListenerActivity","settleListenerJobExecutionActivity","recordListenerFiringOutcomeActivity","startToCloseTimeout","listenerEventsAvailableSignal","listenerResolveSignal","LISTENER_CONTINUE_AS_NEW_FIRING_LIMIT","jobListenerOrchestration","input","eventsAvailable","latchedReason","continuation","listenerDeadline","initialListenerDeadline","nextSequence","activated","jobId","expectedVersion","jobVersion","status","jobStatus","executionCount","firingsInCurrentRun","maxExecutions","undefined","batchConfig","listenerBatchConfig","continueListenerAsNewIfNeeded","decision","awaitBatchFiringWindow","hasEventsHint","clearEventsHint","hasResolutionHint","drained","expectedSequence","maxSizeEvents","maxSize","kind","woke","waitForListenerWakeup","deadline","outcome","sequence","runListenerExecution","jobExecutionId","executionVersion","requiredLabels","shouldCancelForResolution","onResolve","waitForResolution","reason","resolved","listeningTimeoutMs","Date","now","params","shouldContinueListenerAsNew","continueAsNewSuggested","listenerContinuationInput","debounceMs","positiveNumber","batchDebounceMs","batchMaxSize","maxWaitMs","batchMaxWaitMs","prePeekDecision","resolutionOrDeadlineDecision","peek","peekBatchBuffer","peekDecision","bufferedResolveOrDeadlineDecision","fireCount","waitDecision","waitForAnyBatchWakeup","batchIsReadyToFire","sleepMs","nextBatchWindowMs","waitForBatchWindow","resolvePending","config","sizeReached","debounceQuiet","newestAgeMs","maxWaitReached","oldestAgeMs","timeWindows","remainingWindowMs","filter","value","length","Math","min","deadlineRemaining","boundedSleepMs","wakesOnEvents","limitMs","ageMs","max","scope","child","run","workflowId","workflowIdReusePolicy","args","runAttemptId","executionTimeoutMs","resolveJobStatus","parentClosePolicy","TERMINATE","winner","Promise","race","then","cancel","result","listenerFiringOutcome","error","warn","String","Error","predicate","options","remaining"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-orchestration.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/run-orchestration.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-orchestration.d.ts","sourceRoot":"","sources":["../../../src/temporal/workflows/run-orchestration.ts"],"names":[],"mappings":"AAuCA,eAAO,MAAM,eAAe,6DAAsC,CAAC;AAEnE,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoGlF"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { condition, defineSignal, executeChild, log, ParentClosePolicy, proxyActivities, setHandler } from '@temporalio/workflow';
|
|
2
|
-
import { createRuntimeRunProgress,
|
|
2
|
+
import { createRuntimeRunProgress, recordRuntimeJobResult, recordSkippedRuntimeJob, runtimeJobVersion, shouldContinueStartedRun } from '#core/workflow-scheduling/run-progress.js';
|
|
3
3
|
import { scheduleRuntimeDag } from '#core/workflow-scheduling/schedule-runtime-dag.js';
|
|
4
4
|
import { RUN_CANCEL_SIGNAL } from '../constants.js';
|
|
5
5
|
import { deadlineReached, remainingMs } from './deadline.js';
|
|
6
6
|
import { jobExecutionOrchestration } from './job-execution-orchestration.js';
|
|
7
7
|
import { jobListenerOrchestration } from './job-listener-orchestration.js';
|
|
8
|
-
const { loadRunAttemptDag, evaluateJobActivationsActivity, setRunAttemptStatus, setJobStatus
|
|
8
|
+
const { loadRunAttemptDag, evaluateJobActivationsActivity, setRunAttemptStatus, setJobStatus } = proxyActivities({
|
|
9
9
|
startToCloseTimeout: '30s'
|
|
10
10
|
});
|
|
11
11
|
const { failRunAsTimedOutActivity } = proxyActivities({
|
|
@@ -34,14 +34,12 @@ export async function runOrchestration(input) {
|
|
|
34
34
|
const inFlight = new Map();
|
|
35
35
|
while(true){
|
|
36
36
|
if (cancelRequested) {
|
|
37
|
-
await cancelNonCompletedRunnerJobs(dag, progress);
|
|
38
37
|
return;
|
|
39
38
|
}
|
|
40
39
|
if (deadlineReached(runDeadline)) {
|
|
41
40
|
await failRunAsTimedOutActivity({
|
|
42
41
|
runAttemptId: input.runAttemptId
|
|
43
42
|
});
|
|
44
|
-
await cancelNonCompletedRunnerJobs(dag, progress);
|
|
45
43
|
return;
|
|
46
44
|
}
|
|
47
45
|
const commands = scheduleRuntimeDag({
|
|
@@ -101,14 +99,12 @@ export async function runOrchestration(input) {
|
|
|
101
99
|
if (startJobs.size === 0 && inFlight.size === 0) continue;
|
|
102
100
|
const settled = await waitForNextSettlement(inFlight, ()=>cancelRequested, runDeadline);
|
|
103
101
|
if (settled.kind === 'cancelled') {
|
|
104
|
-
await cancelNonCompletedRunnerJobs(dag, progress);
|
|
105
102
|
return;
|
|
106
103
|
}
|
|
107
104
|
if (settled.kind === 'timed-out') {
|
|
108
105
|
await failRunAsTimedOutActivity({
|
|
109
106
|
runAttemptId: input.runAttemptId
|
|
110
107
|
});
|
|
111
|
-
await cancelNonCompletedRunnerJobs(dag, progress);
|
|
112
108
|
return;
|
|
113
109
|
}
|
|
114
110
|
inFlight.delete(settled.job.key);
|
|
@@ -131,9 +127,6 @@ function launchJob(job, run, progress) {
|
|
|
131
127
|
workflowId: `job-listener:${job.id}`,
|
|
132
128
|
args: [
|
|
133
129
|
{
|
|
134
|
-
workspaceId: run.workspaceId,
|
|
135
|
-
workflowRunId: run.workflowRunId,
|
|
136
|
-
projectId: run.projectId,
|
|
137
130
|
jobId: job.id,
|
|
138
131
|
runAttemptId: run.runAttemptId,
|
|
139
132
|
jobVersion: runtimeJobVersion(job, progress),
|
|
@@ -192,9 +185,6 @@ function launchJob(job, run, progress) {
|
|
|
192
185
|
workflowId: `job:${job.id}`,
|
|
193
186
|
args: [
|
|
194
187
|
{
|
|
195
|
-
workspaceId: run.workspaceId,
|
|
196
|
-
workflowRunId: run.workflowRunId,
|
|
197
|
-
projectId: run.projectId,
|
|
198
188
|
jobId: job.id,
|
|
199
189
|
jobExecutionId: job.jobExecutionId,
|
|
200
190
|
runAttemptId: run.runAttemptId,
|
|
@@ -233,11 +223,5 @@ async function waitForNextSettlement(inFlight, isCancelRequested, runDeadline) {
|
|
|
233
223
|
cancel
|
|
234
224
|
]);
|
|
235
225
|
}
|
|
236
|
-
async function cancelNonCompletedRunnerJobs(dag, progress) {
|
|
237
|
-
const jobIds = nonCompletedRuntimeJobIds(dag.jobs, progress);
|
|
238
|
-
await cancelRunnerJobsActivity({
|
|
239
|
-
jobIds
|
|
240
|
-
});
|
|
241
|
-
}
|
|
242
226
|
|
|
243
227
|
//# sourceMappingURL=run-orchestration.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/temporal/workflows/run-orchestration.ts"],"sourcesContent":["import {\n condition,\n defineSignal,\n executeChild,\n log,\n ParentClosePolicy,\n proxyActivities,\n setHandler,\n} from '@temporalio/workflow';\nimport {\n createRuntimeRunProgress,\n nonCompletedRuntimeJobIds,\n type RuntimeRunProgress,\n recordRuntimeJobResult,\n recordSkippedRuntimeJob,\n runtimeJobVersion,\n shouldContinueStartedRun,\n} from '#core/workflow-scheduling/run-progress.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\nimport {scheduleRuntimeDag} from '#core/workflow-scheduling/schedule-runtime-dag.js';\n\nimport type {createOrchestrationActivities} from '../activities/index.js';\nimport type {DagJob, RunDag} from '../activities/orchestration-activities.js';\nimport {RUN_CANCEL_SIGNAL} from '../constants.js';\nimport {deadlineReached, remainingMs} from './deadline.js';\nimport {jobExecutionOrchestration} from './job-execution-orchestration.js';\nimport {jobListenerOrchestration} from './job-listener-orchestration.js';\n\nconst {\n loadRunAttemptDag,\n evaluateJobActivationsActivity,\n setRunAttemptStatus,\n setJobStatus,\n cancelRunnerJobsActivity,\n} = proxyActivities<ReturnType<typeof createOrchestrationActivities>>({\n startToCloseTimeout: '30s',\n});\n\nconst {failRunAsTimedOutActivity} = proxyActivities<\n ReturnType<typeof createOrchestrationActivities>\n>({\n startToCloseTimeout: '30s',\n retry: {maximumAttempts: 5},\n});\n\nexport const runCancelSignal = defineSignal<[]>(RUN_CANCEL_SIGNAL);\n\nexport interface RunOrchestrationInput {\n workflowRunId: string;\n runAttemptId: string;\n workspaceId: string;\n}\n\nexport async function runOrchestration(input: RunOrchestrationInput): Promise<void> {\n let cancelRequested = false;\n setHandler(runCancelSignal, () => {\n cancelRequested = true;\n });\n\n const dag = await loadRunAttemptDag(input.runAttemptId);\n const runDeadline = Date.now() + dag.runTimeoutMs;\n\n let runVersion = dag.runVersion;\n const {newVersion, status} = await setRunAttemptStatus({\n runAttemptId: input.runAttemptId,\n status: 'running',\n version: runVersion,\n });\n runVersion = newVersion;\n if (!shouldContinueStartedRun(status)) return;\n\n const progress = createRuntimeRunProgress(dag.jobs);\n const inFlight = new Map<string, Promise<{job: DagJob; result: LaunchResult}>>();\n\n while (true) {\n if (cancelRequested) {\n await cancelNonCompletedRunnerJobs(dag, progress);\n return;\n }\n if (deadlineReached(runDeadline)) {\n await failRunAsTimedOutActivity({runAttemptId: input.runAttemptId});\n await cancelNonCompletedRunnerJobs(dag, progress);\n return;\n }\n\n const commands = scheduleRuntimeDag({\n jobs: dag.jobs,\n completed: progress.completed,\n running: new Set(inFlight.keys()),\n });\n const completeRun = commands.find((command) => command.kind === 'complete-run');\n const startJobs = new Map<string, DagJob>();\n\n for (const command of commands) {\n if (command.kind !== 'skip-job') continue;\n await skipJob(command.job, progress, command.statusReason);\n }\n\n for (const command of commands) {\n if (command.kind !== 'evaluate-job-activation') continue;\n const activationJobsById = new Map(command.jobs.map((job) => [job.id, job]));\n const decisions = await evaluateJobActivationsActivity({\n runAttemptId: input.runAttemptId,\n jobs: command.jobs.map((job) => ({\n jobId: job.id,\n expectedVersion: runtimeJobVersion(job, progress),\n })),\n });\n for (const decision of decisions) {\n const job = activationJobsById.get(decision.jobId);\n if (!job) continue;\n if (decision.kind === 'start-job') {\n startJobs.set(job.key, job);\n continue;\n }\n recordRuntimeJobResult(job, progress, {\n status: decision.status,\n jobVersion: decision.jobVersion,\n });\n }\n }\n\n for (const command of commands) {\n if (command.kind !== 'start-job') continue;\n startJobs.set(command.job.key, command.job);\n }\n\n for (const job of startJobs.values()) {\n if (!inFlight.has(job.key)) {\n inFlight.set(job.key, launchJob(job, dag, progress));\n }\n }\n\n if (completeRun) {\n await setRunAttemptStatus({\n runAttemptId: input.runAttemptId,\n status: completeRun.status,\n version: runVersion,\n });\n return;\n }\n\n if (startJobs.size === 0 && inFlight.size === 0) continue;\n\n const settled = await waitForNextSettlement(inFlight, () => cancelRequested, runDeadline);\n if (settled.kind === 'cancelled') {\n await cancelNonCompletedRunnerJobs(dag, progress);\n return;\n }\n if (settled.kind === 'timed-out') {\n await failRunAsTimedOutActivity({runAttemptId: input.runAttemptId});\n await cancelNonCompletedRunnerJobs(dag, progress);\n return;\n }\n inFlight.delete(settled.job.key);\n recordRuntimeJobResult(settled.job, progress, settled.result);\n }\n}\n\nasync function skipJob(\n job: DagJob,\n progress: RuntimeRunProgress,\n statusReason: 'default_gate_rejected',\n): Promise<void> {\n const version = runtimeJobVersion(job, progress);\n const {newVersion} = await setJobStatus({\n jobId: job.id,\n status: 'skipped',\n version,\n statusReason,\n });\n recordSkippedRuntimeJob(job, progress, newVersion);\n}\n\ninterface LaunchResult {\n status: RuntimeCompletionStatus;\n jobVersion: number;\n}\n\nfunction launchJob(\n job: DagJob,\n run: RunDag,\n progress: RuntimeRunProgress,\n): Promise<{job: DagJob; result: LaunchResult}> {\n if (job.mode === 'listening') {\n return executeChild(jobListenerOrchestration, {\n workflowId: `job-listener:${job.id}`,\n args: [\n {\n workspaceId: run.workspaceId,\n workflowRunId: run.workflowRunId,\n projectId: run.projectId,\n jobId: job.id,\n runAttemptId: run.runAttemptId,\n jobVersion: runtimeJobVersion(job, progress),\n ...(job.executionTimeoutMs === undefined\n ? {}\n : {executionTimeoutMs: job.executionTimeoutMs}),\n ...(job.listeningTimeoutMs === undefined\n ? {}\n : {listeningTimeoutMs: job.listeningTimeoutMs}),\n ...(job.maxExecutions === undefined ? {} : {maxExecutions: job.maxExecutions}),\n ...(job.onResolve === undefined ? {} : {onResolve: job.onResolve}),\n ...(job.batchDebounceMs === undefined ? {} : {batchDebounceMs: job.batchDebounceMs}),\n ...(job.batchMaxSize === undefined ? {} : {batchMaxSize: job.batchMaxSize}),\n ...(job.batchMaxWaitMs === undefined ? {} : {batchMaxWaitMs: job.batchMaxWaitMs}),\n requiredLabels: job.runner,\n },\n ],\n parentClosePolicy: ParentClosePolicy.TERMINATE,\n })\n .then((result) => ({job, result}))\n .catch(async (error) => {\n log.warn('listener child failed; marking runtime job failed', {\n jobId: job.id,\n error: String(error),\n });\n const failed = await setJobStatus({\n jobId: job.id,\n status: 'failed',\n version: runtimeJobVersion(job, progress),\n statusReason: 'unknown',\n });\n return {\n job,\n result: {status: 'failed' as const, jobVersion: failed.newVersion},\n };\n });\n }\n\n if (job.jobExecutionId === undefined) {\n throw new Error(`Cannot start job without an execution: ${job.id}`);\n }\n return executeChild(jobExecutionOrchestration, {\n workflowId: `job:${job.id}`,\n args: [\n {\n workspaceId: run.workspaceId,\n workflowRunId: run.workflowRunId,\n projectId: run.projectId,\n jobId: job.id,\n jobExecutionId: job.jobExecutionId,\n runAttemptId: run.runAttemptId,\n jobVersion: runtimeJobVersion(job, progress),\n executionVersion: job.executionVersion ?? runtimeJobVersion(job, progress),\n ...(job.executionTimeoutMs === undefined\n ? {}\n : {executionTimeoutMs: job.executionTimeoutMs}),\n requiredLabels: job.runner,\n },\n ],\n parentClosePolicy: ParentClosePolicy.TERMINATE,\n }).then((result) => ({\n job,\n result: {status: result.status, jobVersion: result.jobVersion},\n }));\n}\n\nasync function waitForNextSettlement(\n inFlight: ReadonlyMap<string, Promise<{job: DagJob; result: LaunchResult}>>,\n isCancelRequested: () => boolean,\n runDeadline: number,\n): Promise<\n {kind: 'settled'; job: DagJob; result: LaunchResult} | {kind: 'cancelled'} | {kind: 'timed-out'}\n> {\n const remaining = remainingMs(runDeadline) ?? 0;\n const childSettled = Promise.race([...inFlight.values()]).then((settled) => ({\n kind: 'settled' as const,\n ...settled,\n }));\n const cancel = condition(isCancelRequested, remaining).then((woke) =>\n woke ? {kind: 'cancelled' as const} : {kind: 'timed-out' as const},\n );\n return await Promise.race([childSettled, cancel]);\n}\n\nasync function cancelNonCompletedRunnerJobs(\n dag: RunDag,\n progress: RuntimeRunProgress,\n): Promise<void> {\n const jobIds = nonCompletedRuntimeJobIds(dag.jobs, progress);\n await cancelRunnerJobsActivity({jobIds});\n}\n"],"names":["condition","defineSignal","executeChild","log","ParentClosePolicy","proxyActivities","setHandler","createRuntimeRunProgress","nonCompletedRuntimeJobIds","recordRuntimeJobResult","recordSkippedRuntimeJob","runtimeJobVersion","shouldContinueStartedRun","scheduleRuntimeDag","RUN_CANCEL_SIGNAL","deadlineReached","remainingMs","jobExecutionOrchestration","jobListenerOrchestration","loadRunAttemptDag","evaluateJobActivationsActivity","setRunAttemptStatus","setJobStatus","cancelRunnerJobsActivity","startToCloseTimeout","failRunAsTimedOutActivity","retry","maximumAttempts","runCancelSignal","runOrchestration","input","cancelRequested","dag","runAttemptId","runDeadline","Date","now","runTimeoutMs","runVersion","newVersion","status","version","progress","jobs","inFlight","Map","cancelNonCompletedRunnerJobs","commands","completed","running","Set","keys","completeRun","find","command","kind","startJobs","skipJob","job","statusReason","activationJobsById","map","id","decisions","jobId","expectedVersion","decision","get","set","key","jobVersion","values","has","launchJob","size","settled","waitForNextSettlement","delete","result","run","mode","workflowId","args","workspaceId","workflowRunId","projectId","executionTimeoutMs","undefined","listeningTimeoutMs","maxExecutions","onResolve","batchDebounceMs","batchMaxSize","batchMaxWaitMs","requiredLabels","runner","parentClosePolicy","TERMINATE","then","catch","error","warn","String","failed","jobExecutionId","Error","executionVersion","isCancelRequested","remaining","childSettled","Promise","race","cancel","woke","jobIds"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/temporal/workflows/run-orchestration.ts"],"sourcesContent":["import {\n condition,\n defineSignal,\n executeChild,\n log,\n ParentClosePolicy,\n proxyActivities,\n setHandler,\n} from '@temporalio/workflow';\nimport {\n createRuntimeRunProgress,\n type RuntimeRunProgress,\n recordRuntimeJobResult,\n recordSkippedRuntimeJob,\n runtimeJobVersion,\n shouldContinueStartedRun,\n} from '#core/workflow-scheduling/run-progress.js';\nimport type {RuntimeCompletionStatus} from '#core/workflow-scheduling/runtime-dag.js';\nimport {scheduleRuntimeDag} from '#core/workflow-scheduling/schedule-runtime-dag.js';\n\nimport type {createOrchestrationActivities} from '../activities/index.js';\nimport type {DagJob, RunDag} from '../activities/orchestration-activities.js';\nimport {RUN_CANCEL_SIGNAL} from '../constants.js';\nimport {deadlineReached, remainingMs} from './deadline.js';\nimport {jobExecutionOrchestration} from './job-execution-orchestration.js';\nimport {jobListenerOrchestration} from './job-listener-orchestration.js';\n\nconst {loadRunAttemptDag, evaluateJobActivationsActivity, setRunAttemptStatus, setJobStatus} =\n proxyActivities<ReturnType<typeof createOrchestrationActivities>>({\n startToCloseTimeout: '30s',\n });\n\nconst {failRunAsTimedOutActivity} = proxyActivities<\n ReturnType<typeof createOrchestrationActivities>\n>({\n startToCloseTimeout: '30s',\n retry: {maximumAttempts: 5},\n});\n\nexport const runCancelSignal = defineSignal<[]>(RUN_CANCEL_SIGNAL);\n\nexport interface RunOrchestrationInput {\n workflowRunId: string;\n runAttemptId: string;\n workspaceId: string;\n}\n\nexport async function runOrchestration(input: RunOrchestrationInput): Promise<void> {\n let cancelRequested = false;\n setHandler(runCancelSignal, () => {\n cancelRequested = true;\n });\n\n const dag = await loadRunAttemptDag(input.runAttemptId);\n const runDeadline = Date.now() + dag.runTimeoutMs;\n\n let runVersion = dag.runVersion;\n const {newVersion, status} = await setRunAttemptStatus({\n runAttemptId: input.runAttemptId,\n status: 'running',\n version: runVersion,\n });\n runVersion = newVersion;\n if (!shouldContinueStartedRun(status)) return;\n\n const progress = createRuntimeRunProgress(dag.jobs);\n const inFlight = new Map<string, Promise<{job: DagJob; result: LaunchResult}>>();\n\n while (true) {\n if (cancelRequested) {\n return;\n }\n if (deadlineReached(runDeadline)) {\n await failRunAsTimedOutActivity({runAttemptId: input.runAttemptId});\n return;\n }\n\n const commands = scheduleRuntimeDag({\n jobs: dag.jobs,\n completed: progress.completed,\n running: new Set(inFlight.keys()),\n });\n const completeRun = commands.find((command) => command.kind === 'complete-run');\n const startJobs = new Map<string, DagJob>();\n\n for (const command of commands) {\n if (command.kind !== 'skip-job') continue;\n await skipJob(command.job, progress, command.statusReason);\n }\n\n for (const command of commands) {\n if (command.kind !== 'evaluate-job-activation') continue;\n const activationJobsById = new Map(command.jobs.map((job) => [job.id, job]));\n const decisions = await evaluateJobActivationsActivity({\n runAttemptId: input.runAttemptId,\n jobs: command.jobs.map((job) => ({\n jobId: job.id,\n expectedVersion: runtimeJobVersion(job, progress),\n })),\n });\n for (const decision of decisions) {\n const job = activationJobsById.get(decision.jobId);\n if (!job) continue;\n if (decision.kind === 'start-job') {\n startJobs.set(job.key, job);\n continue;\n }\n recordRuntimeJobResult(job, progress, {\n status: decision.status,\n jobVersion: decision.jobVersion,\n });\n }\n }\n\n for (const command of commands) {\n if (command.kind !== 'start-job') continue;\n startJobs.set(command.job.key, command.job);\n }\n\n for (const job of startJobs.values()) {\n if (!inFlight.has(job.key)) {\n inFlight.set(job.key, launchJob(job, dag, progress));\n }\n }\n\n if (completeRun) {\n await setRunAttemptStatus({\n runAttemptId: input.runAttemptId,\n status: completeRun.status,\n version: runVersion,\n });\n return;\n }\n\n if (startJobs.size === 0 && inFlight.size === 0) continue;\n\n const settled = await waitForNextSettlement(inFlight, () => cancelRequested, runDeadline);\n if (settled.kind === 'cancelled') {\n return;\n }\n if (settled.kind === 'timed-out') {\n await failRunAsTimedOutActivity({runAttemptId: input.runAttemptId});\n return;\n }\n inFlight.delete(settled.job.key);\n recordRuntimeJobResult(settled.job, progress, settled.result);\n }\n}\n\nasync function skipJob(\n job: DagJob,\n progress: RuntimeRunProgress,\n statusReason: 'default_gate_rejected',\n): Promise<void> {\n const version = runtimeJobVersion(job, progress);\n const {newVersion} = await setJobStatus({\n jobId: job.id,\n status: 'skipped',\n version,\n statusReason,\n });\n recordSkippedRuntimeJob(job, progress, newVersion);\n}\n\ninterface LaunchResult {\n status: RuntimeCompletionStatus;\n jobVersion: number;\n}\n\nfunction launchJob(\n job: DagJob,\n run: RunDag,\n progress: RuntimeRunProgress,\n): Promise<{job: DagJob; result: LaunchResult}> {\n if (job.mode === 'listening') {\n return executeChild(jobListenerOrchestration, {\n workflowId: `job-listener:${job.id}`,\n args: [\n {\n jobId: job.id,\n runAttemptId: run.runAttemptId,\n jobVersion: runtimeJobVersion(job, progress),\n ...(job.executionTimeoutMs === undefined\n ? {}\n : {executionTimeoutMs: job.executionTimeoutMs}),\n ...(job.listeningTimeoutMs === undefined\n ? {}\n : {listeningTimeoutMs: job.listeningTimeoutMs}),\n ...(job.maxExecutions === undefined ? {} : {maxExecutions: job.maxExecutions}),\n ...(job.onResolve === undefined ? {} : {onResolve: job.onResolve}),\n ...(job.batchDebounceMs === undefined ? {} : {batchDebounceMs: job.batchDebounceMs}),\n ...(job.batchMaxSize === undefined ? {} : {batchMaxSize: job.batchMaxSize}),\n ...(job.batchMaxWaitMs === undefined ? {} : {batchMaxWaitMs: job.batchMaxWaitMs}),\n requiredLabels: job.runner,\n },\n ],\n parentClosePolicy: ParentClosePolicy.TERMINATE,\n })\n .then((result) => ({job, result}))\n .catch(async (error) => {\n log.warn('listener child failed; marking runtime job failed', {\n jobId: job.id,\n error: String(error),\n });\n const failed = await setJobStatus({\n jobId: job.id,\n status: 'failed',\n version: runtimeJobVersion(job, progress),\n statusReason: 'unknown',\n });\n return {\n job,\n result: {status: 'failed' as const, jobVersion: failed.newVersion},\n };\n });\n }\n\n if (job.jobExecutionId === undefined) {\n throw new Error(`Cannot start job without an execution: ${job.id}`);\n }\n return executeChild(jobExecutionOrchestration, {\n workflowId: `job:${job.id}`,\n args: [\n {\n jobId: job.id,\n jobExecutionId: job.jobExecutionId,\n runAttemptId: run.runAttemptId,\n jobVersion: runtimeJobVersion(job, progress),\n executionVersion: job.executionVersion ?? runtimeJobVersion(job, progress),\n ...(job.executionTimeoutMs === undefined\n ? {}\n : {executionTimeoutMs: job.executionTimeoutMs}),\n requiredLabels: job.runner,\n },\n ],\n parentClosePolicy: ParentClosePolicy.TERMINATE,\n }).then((result) => ({\n job,\n result: {status: result.status, jobVersion: result.jobVersion},\n }));\n}\n\nasync function waitForNextSettlement(\n inFlight: ReadonlyMap<string, Promise<{job: DagJob; result: LaunchResult}>>,\n isCancelRequested: () => boolean,\n runDeadline: number,\n): Promise<\n {kind: 'settled'; job: DagJob; result: LaunchResult} | {kind: 'cancelled'} | {kind: 'timed-out'}\n> {\n const remaining = remainingMs(runDeadline) ?? 0;\n const childSettled = Promise.race([...inFlight.values()]).then((settled) => ({\n kind: 'settled' as const,\n ...settled,\n }));\n const cancel = condition(isCancelRequested, remaining).then((woke) =>\n woke ? {kind: 'cancelled' as const} : {kind: 'timed-out' as const},\n );\n return await Promise.race([childSettled, cancel]);\n}\n"],"names":["condition","defineSignal","executeChild","log","ParentClosePolicy","proxyActivities","setHandler","createRuntimeRunProgress","recordRuntimeJobResult","recordSkippedRuntimeJob","runtimeJobVersion","shouldContinueStartedRun","scheduleRuntimeDag","RUN_CANCEL_SIGNAL","deadlineReached","remainingMs","jobExecutionOrchestration","jobListenerOrchestration","loadRunAttemptDag","evaluateJobActivationsActivity","setRunAttemptStatus","setJobStatus","startToCloseTimeout","failRunAsTimedOutActivity","retry","maximumAttempts","runCancelSignal","runOrchestration","input","cancelRequested","dag","runAttemptId","runDeadline","Date","now","runTimeoutMs","runVersion","newVersion","status","version","progress","jobs","inFlight","Map","commands","completed","running","Set","keys","completeRun","find","command","kind","startJobs","skipJob","job","statusReason","activationJobsById","map","id","decisions","jobId","expectedVersion","decision","get","set","key","jobVersion","values","has","launchJob","size","settled","waitForNextSettlement","delete","result","run","mode","workflowId","args","executionTimeoutMs","undefined","listeningTimeoutMs","maxExecutions","onResolve","batchDebounceMs","batchMaxSize","batchMaxWaitMs","requiredLabels","runner","parentClosePolicy","TERMINATE","then","catch","error","warn","String","failed","jobExecutionId","Error","executionVersion","isCancelRequested","remaining","childSettled","Promise","race","cancel","woke"],"mappings":"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"}
|