Skip to content

fix(k8s): re-establish pod watch on server timeout for long-running tasks#1440

Merged
lbeckman314 merged 1 commit into
developfrom
fix/watcher-timeout-long-running-tasks
Jun 26, 2026
Merged

fix(k8s): re-establish pod watch on server timeout for long-running tasks#1440
lbeckman314 merged 1 commit into
developfrom
fix/watcher-timeout-long-running-tasks

Conversation

@lbeckman314

Copy link
Copy Markdown
Contributor

The Kubernetes API server closes long-lived watch connections after a server-configured timeout, which for long-running tasks routinely fires after ~20-30 minutes. When that happened, waitForPodFinish read a zero-value event from the closed result channel and returned "received nil pod object from watcher", marking the task SYSTEM_ERROR even though the pod was healthy and still running.

waitForPodFinish now owns the watch lifecycle: it detects a closed result channel (ok == false) and transparently re-establishes the watch, resuming from the last observed resourceVersion so no events are replayed or missed. An Expired/Gone (HTTP 410) watch error restarts the watch from latest instead of failing the task.

Adds tests covering: re-establishment on watch timeout (resuming from the tracked resourceVersion), the terminated-pod happy path, and restart on an expired resourceVersion.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

Assisted-by: Claude Code:claude [Claude Code]

Description

Motivation and Context

How Has This Been Tested?

Types of Changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • I have updated the documentation accordingly (link here).
  • I have tested that this feature locally.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • Reviewer has tested this feature locally

…asks

The Kubernetes API server closes long-lived watch connections after a
server-configured timeout, which for long-running tasks routinely fires
after ~20-30 minutes. When that happened, waitForPodFinish read a
zero-value event from the closed result channel and returned
"received nil pod object from watcher", marking the task SYSTEM_ERROR
even though the pod was healthy and still running.

waitForPodFinish now owns the watch lifecycle: it detects a closed
result channel (ok == false) and transparently re-establishes the watch,
resuming from the last observed resourceVersion so no events are replayed
or missed. An Expired/Gone (HTTP 410) watch error restarts the watch
from latest instead of failing the task.

Adds tests covering: re-establishment on watch timeout (resuming from
the tracked resourceVersion), the terminated-pod happy path, and restart
on an expired resourceVersion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Assisted-by: Claude Code:claude [Claude Code]
@github-actions

Copy link
Copy Markdown

Gen3 Integration Tests

filepath passed skipped SUBTOTAL
tests/test_gen3_workflow.py 25 4 29
TOTAL 25 4 29

@nss10

nss10 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

This has been tested on a pod that has been running for over an hour.

Found these logs in the funnel-worker as expected

debug                Pod status:                                                                                                                                                                                                      
podPhase             Running                                                                                                                                                                                                          
time                 2026-06-26T02:36:56Z                                                                                                                                                                                             
                                                                                                                                                                                                                                      
debug                pod watch channel closed; re-establishing watch                                                                                                                                                                  
resourceVersion      1502186356                                                                                                                                                                                                       
time                 2026-06-26T03:07:21Z                                                                                                                                                                                             
                                                                                                                                                                                                                                      
debug                pod watch resourceVersion expired; restarting watch from latest                                                                                                                                                  
message              too old resource version: 1502186356 (1502222191)                                                                                                                                                                
time                 2026-06-26T03:07:21Z                                                                                                                                                                                             
                                                                                                                                                                                                                                      
debug                Pod status:                                                                                                                                                                                                      
podPhase             Running                                                                                                                                                                                                          
time                 2026-06-26T03:07:21Z  

This resolves the issue of pods being marked as Failed when podWatcher expires. This PR is good to be merged from Gen3's standpoint.

@lbeckman314
lbeckman314 marked this pull request as ready for review June 26, 2026 18:04
@lbeckman314
lbeckman314 merged commit 7d2cbdd into develop Jun 26, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants