Skip to content

fix: make async scanner polling resilient to transient errors - #2307

Merged
netomi merged 6 commits into
mainfrom
fix/argus-poll-resilience
Oct 8, 2026
Merged

netomi merged 6 commits into
mainfrom
fix/argus-poll-resilience

Conversation

@netomi

@netomi netomi commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Some Argus scans were recorded as External scan failed (no details from scanner) although Argus completed them successfully. Two causes in the poll path:

  • One poll response with status: error (mapped to FAILED) was terminal. A scanner that reports a transient error and then recovers still failed the scan.
  • HttpClientExecutor returns the body of any 4xx response as a success, so a 4xx JSON error body could be read as a scan status.
  • A poll that threw (for example a 502) was only retried by JobRunr's short backoff. The next poll is scheduled only after a successful poll, so a longer outage ended the polling chain until the scanner timeout failed the job.

The "no details" text comes from fetchErrorDetail calling the result endpoint, which is the same URL as poll and returns a body with no matches.

Changes

  • HttpClientExecutor: every non-2xx response (including 3xx) is an error, for start, poll and result calls. The 4xx body pass-through is removed, since it is no longer needed and let an error body be read as a scan status.
  • ScannerPollHandler: a ScannerException during polling is recorded on the job and the next poll is scheduled. It counts towards max-attempts.
  • ScanAPI: a scanner job exposes errorMessage only once terminal, so the transient marker is not shown.
  • ScannerPollHandler: FAILED must be seen on two consecutive polls before the job fails. The first sighting is stored as a marker in ScannerJob.errorMessage, which avoids a schema change. Any other status clears it.
  • RemoteScanner: the truncated raw response is logged at WARN when a poll maps to FAILED.

Tests

  • ScannerPollHandlerTest: first error not final, second consecutive error final, recovery clears the marker, poll exception reschedules.
  • HttpClientExecutorTest: 4xx and 3xx responses with a body throw.
  • ./gradlew test --tests 'org.eclipse.openvsx.scanning.*' passes except 4 recovery-lock tests that need Testcontainers, which could not start here. spotlessCheck is clean.

Notes

A real failure is now detected one poll interval later (15s for Argus).

🤖 Generated with Claude Code

A single poll response with an error status ended the scan job, and a
failed poll call could end the polling chain. Scans that Argus later
completed were recorded as failed.

- Poll requests now throw on any non-2xx response, so a 4xx error body is
  no longer read as a scan status.
- A poll that throws is recorded and the next poll is scheduled, bounded
  by max-attempts.
- An error status must be seen on two consecutive polls before the job
  fails.
- The raw response is logged when a poll maps to FAILED.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Strict mode misses 3xx responses, and the internal failure marker leaks through the admin API.

2 open findings
What changed in this PR

Improves resilience of asynchronous scanner polling during transient failures.

Changes:

  • Adds strict HTTP status handling for polling.
  • Retries poll exceptions and confirms consecutive failure statuses.
  • Adds regression tests for polling and HTTP behavior.
File Description
ScannerPollHandler.java Reschedules failed polls and confirms scanner failures.
RemoteScanner.java Uses strict polling requests and logs failed responses.
HttpClientExecutor.java Adds configurable strict response handling.
ScannerPollHandlerTest.java Tests polling recovery and failure confirmation.
HttpClientExecutorTest.java Tests strict and lenient 4xx handling.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread server/src/main/java/org/eclipse/openvsx/scanning/HttpClientExecutor.java Outdated
netomi and others added 3 commits October 8, 2026 08:32
- Strict HTTP execution now rejects 3xx responses, which RestTemplate
  does not throw for.
- The admin API only exposes a scanner job's error message once the job
  is terminal, so transient poll errors on active jobs are not shown.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The previously identified issues are resolved with focused regression coverage.

0 open findings

2 resolved since last review

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

The 4xx pass-through is no longer needed, so the strict mode added for
polling is dropped and all scanner HTTP calls fail on non-2xx.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Redirect-following remains enabled, allowing some 3xx scanner responses to bypass the new validation.

1 open finding

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread server/src/main/java/org/eclipse/openvsx/scanning/HttpClientExecutor.java Outdated
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The changes address the reported failure modes with focused regression coverage and no unresolved issues.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

@netomi
netomi merged commit a70fc27 into main Oct 8, 2026
6 checks passed
@netomi
netomi deleted the fix/argus-poll-resilience branch October 8, 2026 17:45
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