8000 fix(inkless:storage): count retried GCS error responses by giuseppelillo · Pull Request #789 · aiven/inkless · GitHub
[go: up one dir, main page]

Skip to content

fix(inkless:storage): count retried GCS error responses - #789

Merged
jeqo merged 2 commits into
mainfrom
fix/inkless-gcs-error-metrics
Sep 9, 2026
Merged

jeqo merged 2 commits into
mainfrom
fix/inkless-gcs-error-metrics

Conversation

@giuseppelillo
@giuseppelillo giuseppelillo commented Sep 8, 2026 •
Copy link
Copy Markdown
Contributor

Background

PR #783 added GCS error counters through an HttpResponseInterceptor. The Google HTTP client invokes that interceptor only after HttpRequest.execute() finishes its internal retry loop. When GCS returns 401, HttpCredentialsAdapter can refresh the token and retry the same request before the interceptor runs, so a successful refresh hides the failed response and repeated authorization failures are undercounted.

The credentials handler also reinstalls itself after a refresh. Wrapping it without restoring the metrics wrapper would therefore count only the first 401 from a request.

Batch requests add a second distinction. The outer POST bypasses the request initializer, but each failed multipart sub-response invokes the unsuccessful-response handler. A 404 delete means the object is already absent, and StorageBatch treats that outcome as a confirmed idempotent delete, so counting it as a provider error creates noise during cleaner retries. GCS still bills and rate-limits every submitted delete sub-request, including refused requests, so the operation counter must include all of them.

Changes

  • Record error statuses through an HttpUnsuccessfulResponseHandler, which runs before the client decides whether to retry each response.
  • Delegate to the existing credentials handler and restore the metrics wrapper after it refreshes a token.
  • Keep the response interceptor for operation counters, which should run once after the internal retry loop.
  • Exclude an already-absent batch delete from other-errors, while continuing to count refused and throttled sub-requests.
  • Count every returned batch delete sub-request as an object-delete operation; confirmed deletions remain available through cleaner metrics.
  • Describe other-errors as non-429 4xx responses, excluding absent batch deletes. Protocol responses such as 308 Resume Incomplete also remain excluded.

Testing

  • ./gradlew :storage:inkless:test --tests io.aiven.inkless.storage_backend.gcs.MetricCollectorTest --tests io.aiven.inkless.storage_backend.gcs.integration.GcsErrorHandlingTest --tests io.aiven.inkless.storage_backend.gcs.integration.GcsStorageMetricsTest
  • ./gradlew :storage:inkless:genInklessMetricsDoc

The Google HTTP client invokes response interceptors after its internal retry loop. A credential refresh can therefore consume a 401 response without advancing the GCS error counters, and the credentials handler reinstalls itself after refreshing a token.

Record unsuccessful responses before the client decides whether to retry. Delegate to the existing credentials handler and restore the metrics wrapper afterward so later failures from the same request are also counted. Keep the response interceptor responsible for operation counters.

Describe other-errors as 4xx responses other than 429. This matches the implementation and excludes protocol responses such as 308 Resume Incomplete.

Co-authored-by: Cursor <cursoragent@cursor.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 handler lifecycle, metric classification, documentation, and targeted retry coverage are consistent.

Pull request overview

Updates GCS metrics to count every failed HTTP response, including retried authorization failures.

Changes:

  • Adds a metrics-aware unsuccessful-response handler.
  • Preserves operation counting after retries.
  • Updates metric documentation and retry tests.
File summaries
File Description
MetricCollector.java Counts errors before retries and preserves credential handling.
MetricRegistry.java Clarifies other-errors classification.
MetricCollectorTest.java Verifies repeated 401 responses are counted.
metrics.rst Updates generated metric documentation.
Review details
  • Files reviewed: 4/4 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@jeqo jeqo 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.

Fix looks good. I left a couple of comments to decide the direction. Otherwise LGTM.

Batch delete sub-responses pass through the unsuccessful-response handler. A missing object is an idempotent delete success, but the handler counts its 404 as an error. The object-delete counter also counts only confirmed results, which omits refused sub-requests even though GCS bills and rate-limits them as operations.

Skip absent batch deletes when recording provider errors, and count every returned batch sub-request as an object-delete operation. Keep failed deletes out of the confirmed-key result so FileCleaner retries them. Cover refused and already-absent batches with exact error and operation totals.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jeqo
jeqo merged commit 72e432f into main Sep 9, 2026
7 checks passed
@jeqo
jeqo deleted the fix/inkless-gcs-error-metrics branch September 9, 2026 10:57
jeqo pushed a commit that referenced this pull request Sep 9, 2026
* fix(inkless:storage): count retried GCS error responses

The Google HTTP client invokes response interceptors after its internal retry loop. A credential refresh can therefore consume a 401 response without advancing the GCS error counters, and the credentials handler reinstalls itself after refreshing a token.

Record unsuccessful responses before the client decides whether to retry. Delegate to the existing credentials handler and restore the metrics wrapper afterward so later failures from the same request are also counted. Keep the response interceptor responsible for operation counters.

Describe other-errors as 4xx responses other than 429. This matches the implementation and excludes protocol responses such as 308 Resume Incomplete.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(inkless:storage): align GCS batch delete metrics

Batch delete sub-responses pass through the unsuccessful-response handler. A missing object is an idempotent delete success, but the handler counts its 404 as an error. The object-delete counter also counts only confirmed results, which omits refused sub-requests even though GCS bills and rate-limits them as operations.

Skip absent batch deletes when recording provider errors, and count every returned batch sub-request as an object-delete operation. Keep failed deletes out of the confirmed-key result so FileCleaner retries them. Cover refused and already-absent batches with exact error and operation totals.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
jeqo pushed a commit that referenced this pull request Sep 9, 2026
* fix(inkless:storage): count retried GCS error responses

The Google HTTP client invokes response interceptors after its internal retry loop. A credential refresh can therefore consume a 401 response without advancing the GCS error counters, and the credentials handler reinstalls itself after refreshing a token.

Record unsuccessful responses before the client decides whether to retry. Delegate to the existing credentials handler 
8000
and restore the metrics wrapper afterward so later failures from the same request are also counted. Keep the response interceptor responsible for operation counters.

Describe other-errors as 4xx responses other than 429. This matches the implementation and excludes protocol responses such as 308 Resume Incomplete.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(inkless:storage): align GCS batch delete metrics

Batch delete sub-responses pass through the unsuccessful-response handler. A missing object is an idempotent delete success, but the handler counts its 404 as an error. The object-delete counter also counts only confirmed results, which omits refused sub-requests even though GCS bills and rate-limits them as operations.

Skip absent batch deletes when recording provider errors, and count every returned batch sub-request as an object-delete operation. Keep failed deletes out of the confirmed-key result so FileCleaner retries them. Cover refused and already-absent batches with exact error and operation totals.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
jeqo pushed a commit that referenced this pull request Sep 9, 2026
* fix(inkless:storage): count retried GCS error responses

The Google HTTP client invokes response interceptors after its internal retry loop. A credential refresh can therefore consume a 401 response without advancing the GCS error counters, and the credentials handler reinstalls itself after refreshing a token.

Record unsuccessful responses before the client decides whether to retry. Delegate to the existing credentials handler and restore the metrics wrapper afterward so later failures from the same request are also counted. Keep the response interceptor responsible for operation counters.

Describe other-errors as 4xx responses other than 429. This matches the implementation and excludes protocol responses such as 308 Resume Incomplete.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(inkless:storage): align GCS batch delete metrics

Batch delete sub-responses pass through the unsuccessful-response handler. A missing object is an idempotent delete success, but the handler counts its 404 as an error. The object-delete counter also counts only confirmed results, which omits refused sub-requests even though GCS bills and rate-limits them as operations.

Skip absent batch deletes when recording provider errors, and count every returned batch sub-request as an object-delete operation. Keep failed deletes out of the confirmed-key result so FileCleaner retries them. Cover refused and already-absent batches with exact error and operation totals.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

3 participants

0