Repository navigation
Conversation
SubmitBlocking marks a task done in a deferred waitGroup.Done(), and a failed task reports its error by panicking into the ants pool's panic handler. Go runs the task's own defers while the panic unwinds, so Done() runs before ants recovers and calls the handler. WaitAsync can wake up, find no errors yet and return nil; the error is recorded a moment later. A collector then counts as successful, and StatefulApiCollector saves its incremental state. The API client is shared by all subtasks of a task, so the lost error is reported by the next subtask instead. On our instance a CircleCI token lost access and every request got a 404: on most nights collectPipelines passed and moved its `since` marker forward, the error appeared in collectWorkflows, and two weeks of pipelines were never collected again. Recover the panic inside the task and record it before Done(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Summary
WorkerScheduler.WaitAsynccan returnnilalthough a task failed. The error is then reported by the nextWaitAsynccall on the same client, which is usually the next subtask.A failed task reports its error with a panic, and the ants pool's panic handler records it. But
SubmitBlockingcallswaitGroup.Done()in a defer inside the task. Go runs that defer while the panic unwinds, before ants recovers and calls the handler. SoWaitAsynccan wake up, see no errors and returnnil. The error is recorded a moment later.When this happens to a collector, the subtask counts as successful and
StatefulApiCollectorsaves its incremental state. The data that the failed requests should have collected is never collected again.On our instance the CircleCI token lost access to the project, and every request got
404 Project not foundfor three weeks:collectPipelinespassed and moved itssincemarker forward. The 404 for/v2/project/.../pipelinewas reported bycollectWorkflows, which never calls that URL.collectPipelinesfailed correctly.This PR recovers the panic inside the task and records it before
Done().Sequence
DoAsyncexhausts its retries and returns an error. TheSubmitBlockingtask callspanic(err).s.waitGroup.Done()runs, and the counter reaches 0.WaitAsyncwakes up, readsworkerErrors(empty) and returnsnil.checkErrorappends the error.Does this close any open issues?
No issue filed.
Screenshots
Not applicable (helper-only change).
Tests
helpers/pluginhelper/api/worker_scheduler_test.go:TestWorkerSchedulerWaitAsyncReturnsTaskErrorsubmits a failing task 1000 times and checks thatWaitAsyncreturns the error each time. Without the fix it fails within a few hundred runs. With the fix it passes, also at-count=10.go test ./helpers/pluginhelper/api/ ./plugins/circleci/tasks/ ./plugins/github/tasks/passes.🤖 Generated with Claude Code