perf(agent): exponential backoff in polling to prevent forking storm (#41222)

This commit is contained in:
Yunlu Wen authored and GitHub committed 2026-08-25 04:36:46 +00:00
1 parent 9643dcacce
commit 679514d40a
2 files changed
+10 -1

No files matched your search

@@ -24,6 +24,7 @@ const (
DefaultGCIntervalSeconds = 60.0
DefaultGCFinishedJobRetentionSeconds = 300.0
DefaultPollInterval = 5 * time.Millisecond
DefaultMaxPollInterval = 50 * time.Millisecond
DefaultPipeMonitorInterval = 1 * time.Second
DefaultPipeReadyTimeout = 10 * time.Second
DefaultSQLiteBusyTimeoutMs = 5000
@@ -53,6 +54,7 @@ type Config struct {
MaxOutputLimitBytes int
DefaultTerminateGraceSeconds float64
PollInterval time.Duration
MaxPollInterval time.Duration
PipeMonitorInterval time.Duration
PipeReadyTimeout time.Duration
SQLiteBusyTimeoutMs int
@@ -90,6 +92,7 @@ func DefaultConfig() (*Config, error) {
MaxOutputLimitBytes: MaxOutputLimitBytes,
DefaultTerminateGraceSeconds: DefaultTerminateGraceSeconds,
PollInterval: DefaultPollInterval,
MaxPollInterval: DefaultMaxPollInterval,
PipeMonitorInterval: DefaultPipeMonitorInterval,
PipeReadyTimeout: DefaultPipeReadyTimeout,
SQLiteBusyTimeoutMs: DefaultSQLiteBusyTimeoutMs,
@@ -349,6 +349,11 @@ func (s *Service) WaitJob(jobID string, req *WaitJobRequest) (*JobResult, error)
lastGrowthAt = &now
}
// Poll with exponential backoff: start tight so short jobs return with low
// latency, then grow the interval up to MaxPollInterval so long/idle waits
// stop spawning a tmux liveness probe (fork) every few milliseconds.
pollInterval := s.config.PollInterval
for {
view, err := s.GetJobStatus(jobID)
if err != nil {
@@ -411,7 +416,8 @@ func (s *Service) WaitJob(jobID string, req *WaitJobRequest) (*JobResult, error)
return s.jobResultFromView(view, row, window), nil
}
time.Sleep(s.config.PollInterval)
time.Sleep(pollInterval)
pollInterval = min(pollInterval*2, s.config.MaxPollInterval)
}
}