git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 3/3] http: automatically retry some requests

From
Jeff King <peff@peff.net>
Date
Oct 14, 2020, 19:55 UTC
Message-ID
<20201014195544.GA365911@coredump.intra.peff.net>
In-Reply-To
<20201013191729.2524700-3-smcallis@google.com>
On Tue, Oct 13, 2020 at 01:17:29PM -0600, Sean McAllister wrote:
Show 15 quoted lines
> +/*
> + * check for a retry-after header in the given headers string, if found, then
> + * honor it, otherwise do an exponential backoff up to the max on the current
> + * delay
> +*/
> +static int http_retry_after(const struct strbuf headers, int cur_delay_sec)
> +{
> +	int delay_sec;
> +	char *end;
> +	char* value = http_header_value(headers, "retry-after");
> +
> +	if (value) {
> +		delay_sec = strtol(value, &end, 0);
> +		free(value);
> +		if (*value && *end == '\0' && delay_sec >= 0) {
This looks at the contents of the just-freed "value" memory block.
Show 8 quoted lines
> +			if (delay_sec > http_max_delay_sec) {
> +				die(Q_("server requested retry after %d second,"
> +					   " which is longer than max allowed\n",
> +					   "server requested retry after %d seconds,"
> +					   " which is longer than max allowed\n", delay_sec),
> +					delay_sec);
> +			}
> +			return delay_sec;

I guess there's no point in being gentle here. We could shrink the retry time to our maximum allowed, but the server just told us not to bother. But would this die() mask the actual http error we encountered, which is surely the more interesting thing for the user?

I wonder if it needs to be returning a "do not bother retrying" value, which presumably would cause the caller to propagate the real failure in the usual way.

Show 10 quoted lines
>  static int http_request(const char *url,
>  			void *result, int target,
>  			const struct http_get_options *options)
>  {
>  	struct active_request_slot *slot;
>  	struct slot_results results;
> -	struct curl_slist *headers = http_copy_default_headers();
> +	struct curl_slist *headers;
>  	struct strbuf buf = STRBUF_INIT;
> +	struct strbuf result_headers = STRBUF_INIT;

This new result_headers strbuf is filled in for every request, but I don't think us ever releasing it (whether we retry or not). So I think it's leaking for each request.

It sounds like you're going to rework this to put the retry loop outside of http_request(), so it may naturally get fixed there. But I thought it worth mentioning.

> +	curl_easy_setopt(slot->curl, CURLOPT_HEADERDATA, &result_headers);
> +	curl_easy_setopt(slot->curl, CURLOPT_HEADERFUNCTION, fwrite_buffer);

After looking at your parsing code, I wondered if there was a way to just get a single header out of curl. But according to the documentation for CURLOPT_HEADERFUNCTION, it will pass back individual lines anyway. Perhaps it would be simpler to have the callback function understand that we only care about getting "Retry-After".

The documentation says it doesn't support header folding, but that's probably OK for our purposes. It's deprecated, and your custom parsing doesn't handle it either. :) And most importantly, we won't misbehave terribly if we see it in the wild (we'll just ignore that header).

-Peff
Previous: Junio C HamanoNext: Sean McAllister
Message 23 of 30 in “remote-curl: add testing for intelligent retry for HTTP”
  1. 1/3 remote-curl: add testing for intelligent retry for HTTPSean McAllister, Oct 13, 2020
  2. 2/3 replace CURLOPT_FILE With CURLOPT_WRITEDATASean McAllister, Oct 13, 2020
  3. Junio C HamanoOct 13, 2020
  4. Jeff KingOct 13, 2020
  5. Daniel StenbergOct 13, 2020
  6. Jeff KingOct 14, 2020
  7. Sean McAllisterOct 14, 2020
  8. Sean McAllisterOct 14, 2020
  9. 3/3 http: automatically retry some requestsSean McAllister, Oct 13, 2020
  10. Junio C HamanoOct 13, 2020
  11. Sean McAllisterOct 14, 2020
  12. Junio C HamanoOct 14, 2020
  13. Jeff KingOct 13, 2020
  14. brian m. carlsonOct 13, 2020
  15. Jeff KingOct 14, 2020
  16. Sean McAllisterOct 14, 2020
  17. Sean McAllisterOct 14, 2020
  18. Jeff KingOct 14, 2020
  19. Sean McAllisterOct 14, 2020
  20. Jonathan NiederOct 15, 2020
  21. Jeff KingOct 15, 2020
  22. Junio C HamanoOct 15, 2020
  23. Jeff KingOct 14, 2020
  24. Sean McAllisterOct 14, 2020
  25. Jeff KingOct 15, 2020
  26. Sean McAllisterOct 15, 2020
  27. Junio C HamanoOct 13, 2020
  28. Sean McAllisterOct 14, 2020
  29. Junio C HamanoOct 14, 2020
  30. Sean McAllisterOct 14, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.