fix: emit EventError once after all retries; skip retries for 4xx errors - #541
Merged
Conversation
When a download failed, RunDownload emitted EventError before returning its error to the scheduler. The scheduler then silently retried up to 3 times, so each retry called RunDownload again and emitted another EventError — resulting in 4 error messages, 4 desktop notifications, and 4 file deletion attempts in the orchestrator for a single download. Two bugs, one fix: 1. EventError emitted on every attempt, not just the final failure RunDownload was sending EventError to ProgressCh before returning. Since the scheduler retries transparently, the TUI and orchestrator both received EventError on every attempt. Now EventError is emitted exclusively by worker() in scheduler.go, after the retry gate — so it fires exactly once when the download has truly failed. 2. Permanent HTTP errors (4xx) were retried like transient failures The retry guard only excluded context.Canceled/DeadlineExceeded. A 403 Forbidden (expired signed URL), 404 Not Found, or 401 Unauthorized is a permanent server rejection; retrying 3 times wastes ~2s and floods the UI. Added ErrPermanentHTTP sentinel and IsPermanentHTTPStatus helper to types/errors.go. The single and concurrent downloaders now wrap 4xx (except 429 Too Many Requests, which is transient) with this sentinel. The scheduler's retry gate checks for it and fails immediately. Affected files: - internal/types/errors.go: ErrPermanentHTTP + IsPermanentHTTPError/Status - internal/strategy/single/downloader.go: wrap 4xx with ErrPermanentHTTP - internal/strategy/concurrent/downloader.go: wrap bootstrap 4xx - internal/scheduler/manager.go: remove EventError send from RunDownload - internal/scheduler/scheduler.go: emit EventError once; gate on permanent errors
…retries and preventing concurrent-to-sequential fallback after partial progress
…and document error handling architecture
…ID_UsesProvidedID to verify custom ID handling
…iting for worker goroutines
…o prevent potential deadlocks
…emature task removal and handle shutdowns correctly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Greptile Summary
This PR revises download failure handling and scheduler shutdown behavior.
Confidence Score: 5/5
The PR appears safe to merge with no blocking failures remaining.
The scheduler-lock, shutdown, and stale-filename error-event failures are addressed without an eligible distinct regression.
What T-Rex did
Important Files Changed
Sequence Diagram
sequenceDiagram participant W as Scheduler worker participant D as Downloader participant P as Progress channel participant S as Graceful shutdown W->>D: RunDownload D-->>W: Return error alt retryable and attempts remain W->>W: Requeue task as in-flight W->>P: Emit queued event outside mutex W->>W: Clear in-flight state and back off else permanent or retries exhausted W->>P: Emit one error event outside mutex W->>W: Complete task accounting end S->>P: Close progressDone S->>W: Wait for completionReviews (5): Last reviewed commit: "fix: keep tasks in-flight during retry p..." | Re-trigger Greptile