Skip to content

fix(executor): enforce TaskMetadata.timeout as a per-attempt max runtime - #7910

Open
shaon-chowdhury-euc wants to merge 2 commits into
flyteorg:mainfrom
shaon-chowdhury-euc:fix/flyte2-max-runtime-enforcement
Open

fix(executor): enforce TaskMetadata.timeout as a per-attempt max runtime#7910
shaon-chowdhury-euc wants to merge 2 commits into
flyteorg:mainfrom
shaon-chowdhury-euc:fix/flyte2-max-runtime-enforcement

Conversation

@shaon-chowdhury-euc

@shaon-chowdhury-euc shaon-chowdhury-euc commented Aug 25, 2026

Copy link
Copy Markdown

Summary

  • Enforce TaskMetadata.timeout (max_runtime) in the TaskAction executor: persist AttemptStartedAt / TimeoutAt, abort and finalize the plugin at the deadline, emit TIMED_OUT, and retry only within the existing attempt budget.
  • Fixes #7901. The SDK already serializes the bound; v2.0.42 ignored it, so a 30s task could run for minutes and finish SUCCEEDED.
  • Do not use activeDeadlineSeconds as a substitute — on current builds the kubelet kill leaves the Pod object behind and the executor recreates it without consuming an attempt.

The bound is enforced against the controller clock. A terminal transition observed before the deadline wins whatever timestamp it carries; from the deadline onward it wins only if TaskInfo.OccurredAt proves it finished in time. A terminal report with no usable timestamp is indistinguishable from an overrun, so the bound takes precedence.

TIMED_OUT was already terminal for condition actions but rare in practice. Two places that special-cased ACTION_PHASE_FAILED are updated to keep behaviour consistent now that tasks reach it: action-detail error resolution and task-group fail rate.

Test plan

Verified:

  • go test -race across ./executor/..., ./actions/..., ./runs/...
  • Controller envtest specs covering: attempt-clock anchoring (plugin-reported start, history bootstrap after an upgrade mid-attempt, rejection of a start time predating the attempt); requeue landing on the exact deadline; terminal-vs-deadline races in both directions; per-attempt clock reset across retries with the full event sequence asserted; retry exhaustion becoming terminal failure; resumption after Abort, Finalize, event-publish and status-write failures; unbounded and zero timeouts left unlimited; invalid durations rejected as InvalidSpec; ordinary failures not misclassified as timeouts; system retries not consuming a user attempt; serialized cache reservations held until terminal.
  • make manifests generate produces no drift; all four CRD copies carry the new status fields.

Not yet verified on a live cluster:

  • A flyte.Timeout(max_runtime=30s) task sleeping 300s, end to end through the SDK.

The SDK already serializes max_runtime onto the TaskAction, but the
executor never read it, so hung tasks ran to success. Abort and finalize
the plugin at the deadline, emit TIMED_OUT, and retry only within the
existing attempt budget.

Closes flyteorg#7901

Signed-off-by: shaon-chowdhury-euc <shaon.chowdhury@eucalyptus.vc>
Anchor the attempt clock on the plugin's reported start rather than
inferring it from PhaseHistory, ignoring reports that predate the
attempt. Collapse three deadline predicates into one, and persist the
resume marker before cleanup.

Fix DeepEqual on *metav1.Time, and resolve error info and fail rate
for TIMED_OUT actions.

Signed-off-by: shaon-chowdhury-euc <shaon.chowdhury@eucalyptus.vc>
@shaon-chowdhury-euc
shaon-chowdhury-euc force-pushed the fix/flyte2-max-runtime-enforcement branch from a13073e to 43a77c7 Compare August 25, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flyte2] TaskMetadata.timeout (max_runtime) is serialised but never enforced

1 participant