Skip to content

object_store: retry on response decoding errors#6519

Closed
erratic-pattern wants to merge 1 commit into
apache:mainfrom
erratic-pattern:adam/retry-on-reqwest-decode-error
Closed

object_store: retry on response decoding errors#6519
erratic-pattern wants to merge 1 commit into
apache:mainfrom
erratic-pattern:adam/retry-on-reqwest-decode-error

Conversation

@erratic-pattern

Copy link
Copy Markdown
Contributor

Closes apache/arrow-rs-object-store#53

This PR includes reqwest::Error::Decode as an error case to retry on, which can occur when a server drops a connection in the middle of sending the response body.

Closes https://github.com/apache/arrow-rs/issues/6287

This PR includes `reqwest::Error::Decode` as an error case to retry on,
which can occur when a server drops a connection in the middle of
sending the response body.
@tustvold

tustvold commented Oct 6, 2024

Copy link
Copy Markdown
Contributor

Have you tested this, I ask as the retry logic occurs before the response body processing

@erratic-pattern

Copy link
Copy Markdown
Contributor Author

Have you tested this, I ask as the retry logic occurs before the response body processing

I haven't. My assumption was that this error originates from within the reqwest client, so we should be able to catch it here. Even in the streaming case I thought we should still be polling data from the RetryClient, but I will look more closely at the dataflow here to see what I've missed.

Testing this is a bit annoying without mocking the inner client, which isn't exactly a real world scenario. I am not very familiar with the existing testing harness so if you have any recommendations on where to start I would appreciate it.

@tustvold

tustvold commented Oct 7, 2024

Copy link
Copy Markdown
Contributor

I thought we should still be polling data from the RetryClient

Unfortunately, more broadly speaking this is not generally possible, as discussed on the ticket. Once response streaming has started, a retry would need to somehow resume from where it left off, the semantics of which will depend on the method in question. I do not know of a good way to handle this.

Testing this is a bit annoying without mocking the inner client, which isn't exactly a real world scenario. I am not very familiar with the existing testing harness so if you have any recommendations on where to start I would appreciate it.

We already have a mock HTTP server harness for running these sorts of tests

@erratic-pattern erratic-pattern marked this pull request as draft October 7, 2024 12:43
@erratic-pattern

Copy link
Copy Markdown
Contributor Author

Unfortunately, more broadly speaking this is not generally possible, as discussed on the ticket.

Could you link me to where this is discussed? I'm afraid there's been a lot of comments around this spread across various issues, so it is hard to find specific discussions.

Once response streaming has started, a retry would need to somehow resume from where it left off, the semantics of which will depend on the method in question. I do not know of a good way to handle this.

Is "method" in this context referring to the HTTP method?

Perhaps we need a RetryStream to wrap the response stream in? I am not sure how that would hook up to the existing trait methods exactly, but it seems necessary if we want to transparently re-initiate response streaming.

apache/arrow-rs-object-store#53 suggests having a manual way to re-initiate the request, but I'm not sure what that would look like either.

@tustvold

tustvold commented Oct 7, 2024

Copy link
Copy Markdown
Contributor

Could you link me to where this is discussed?

apache/arrow-rs-object-store#53

Perhaps we need a RetryStream to wrap the response stream in? I am not sure how that would hook up to the existing trait methods exactly, but it seems necessary if we want to transparently re-initiate response streaming.

I think we could add a method to RetryableRequest to return a Result<Bytes> that can be used by non-idempotent, non-streaming requests, such as ObjectStore::list, and which will retry errors during response streaming by retrying the entire request.

However, ObjectStore::get will require retrying at a higher level, as not only will it need to keep track of the current offset, but compute a new range for the retry, and re-sign the resulting request. Perhaps something in GetClientExt might work 🤔

@alamb

alamb commented Oct 8, 2024

Copy link
Copy Markdown
Contributor

In my opinion, to move forward we really need an example/test showing the problem so we can evaluate how the proposed solution fixes it. More discussion here: apache/arrow-rs-object-store#53

@ion-elgreco

Copy link
Copy Markdown

One thing I've noticed is that I also would see failed decoding bytes, when a timeout is set too low.

Could it be that the request still gets processed even though it was incomplete and should have thrown a timeout error instead?

@alamb

alamb commented Jan 29, 2025

Copy link
Copy Markdown
Contributor

One thing I've noticed is that I also would see failed decoding bytes, when a timeout is set too low.

Could it be that the request still gets processed even though it was incomplete and should have thrown a timeout error instead?

From what I understand, if a request fails mid-stream (after we begin to read data) just retrying the request isn't enough -- instead it would need something more complicated like retrying the request just for the bytes that hadn't been already read, or something like that

@alamb

alamb commented Mar 6, 2025

Copy link
Copy Markdown
Contributor

@alamb

alamb commented Mar 20, 2025

Copy link
Copy Markdown
Contributor

Thank you for this PR. We are in the process of moving the object_store code to its own repository. Would it be possible for you to create a PR in that repository instead?

(we will handle moving all existing issues to the new repository)

@alamb

alamb commented May 29, 2025

Copy link
Copy Markdown
Contributor

@alamb alamb closed this May 29, 2025
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.

object_store: Retry on connection duration timeouts (retry / recover after partially reading a streaming response)

4 participants