Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(rest): support rewinds in libcurl #11703

Merged
merged 1 commit into from
May 23, 2023

Conversation

coryan
Copy link
Contributor

@coryan coryan commented May 23, 2023

We configure libcurl to get the data for PUT and POST requests using callbacks. Sometimes libcurl may have sent part of the data and needs to resend it. The documentation mentions "multi-pass authentication methods", as well as reusing connections where libcurl detects they were closed after some data is sent. There are cases on the Internet about chasing HTTP redirects (3xx responses) too. In any case, we have seen these as flakes in the tests.

I took the belt and suspenders approach. Try to handle the rewind requests, but if unhandled treat the error as retryable, because they are.

Fixes #11167


This change is Reviewable

We configure libcurl to get the data for PUT and POST requests using
callbacks. Sometimes libcurl may have sent part of the data and needs to
resend it. The documentation mentions "multi-pass authentication
methods", as well as reusing connections where libcurl detects they were
closed after some data is sent. There are cases on the Internet about
chasing HTTP redirects (3xx responses) too. In any case, we have seen
these as flakes in the tests.

I took the belt and suspenders approach. Try to handle the rewind
requests, but if unhandled treat the error as retryable, because they
are.
@codecov
Copy link

codecov bot commented May 23, 2023

Codecov Report

Patch coverage: 52.38% and project coverage change: -0.02 ⚠️

Comparison is base (a54d679) 83.03% compared to head (1f7924c) 83.02%.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #11703      +/-   ##
==========================================
- Coverage   83.03%   83.02%   -0.02%     
==========================================
  Files        1827     1827              
  Lines      164704   164734      +30     
==========================================
+ Hits       136763   136770       +7     
- Misses      27941    27964      +23     
Impacted Files Coverage Δ
google/cloud/internal/curl_handle.cc 76.88% <50.00%> (-2.24%) ⬇️
google/cloud/internal/curl_impl.cc 87.27% <52.63%> (-3.36%) ⬇️

... and 4 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@coryan coryan marked this pull request as ready for review May 23, 2023 13:26
@coryan coryan requested a review from a team as a code owner May 23, 2023 13:26
@coryan coryan merged commit 508e398 into googleapis:main May 23, 2023
@coryan coryan deleted the fix-rest-support-rewinds-in-libcurl branch May 23, 2023 15:31
Comment on lines +128 to +130
writev_.assign(original_.begin(), original_.end());
// Reverse the vector so the first chunk is at the end.
std::reverse(writev_.begin(), writev_.end());
Copy link
Contributor

Choose a reason for hiding this comment

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

We lost the std::reverse() in the initialization of writev_, but we do one here in its re-initialization. That seems inconsistent.

Copy link
Member

@dbolduc dbolduc May 23, 2023

Choose a reason for hiding this comment

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

I assumed it was better to not reverse in the case of read. 🤷

Copy link
Contributor

Choose a reason for hiding this comment

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

The reverse was originally so that vector::pop_back() was used to consume data, but with the move to deque that is less of a consideration. Still, it seems (without looking deeply) that it should be all or none.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ooops I will send a fix in a few minutes.

};

extern "C" { // libcurl callbacks
Copy link
Contributor

Choose a reason for hiding this comment

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

Aside: I wasn't sure exactly how extern "C"-within-namespace {} was defined, so I put it outside, but I guess if it works (with our compilers) then all is fine.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it works, but effectively makes the symbols have external linkage:

https://stackoverflow.com/questions/35288838/external-linkage-for-name-inside-unnamed-namespace

I will revert that change too.

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.

storage: Send failed since rewinding of the data stream failed
3 participants