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

Re: [PATCH v2 1/3] remote-curl: add testing for intelligent retry for HTTP

From
Junio C Hamano <gitster@pobox.com>
Date
Oct 13, 2020, 20:40 UTC
Message-ID
<xmqqblh5kggd.fsf@gitster.c.googlers.com>
In-Reply-To
<20201013191729.2524700-1-smcallis@google.com>
Sean McAllister <smcallis@google.com> writes:
Show 6 quoted lines
> +# generate a process unique one-up value
> +global_counter_for_nonce=0
> +gen_nonce () {
> +	global_counter_for_nonce=$((global_counter_for_nonce + 1)) &&
> +	echo "$global_counter_for_nonce"
> +}

This must not be called in a subprocess if the caller truly wants uniqueness. May want to be described in a comment.

Show 25 quoted lines
> diff --git a/t/lib-httpd/error-ntime.sh b/t/lib-httpd/error-ntime.sh
> new file mode 100755
> index 0000000000..64dc878746
> --- /dev/null
> +++ b/t/lib-httpd/error-ntime.sh
> @@ -0,0 +1,80 @@
> +#!/bin/sh
> +
> +# Script to simulate a transient error code with Retry-After header set.
> +#
> +# PATH_INFO must be of the form /<nonce>/<times>/<retcode>/<retry-after>/<path>
> +#   (eg: /dc724af1/3/429/10/some/url)
> +#
> +# The <nonce> value uniquely identifies the URL, since we're simulating
> +# a stateful operation using a stateless protocol, we need a way to "namespace"
> +# URLs so that they don't step on each other.
> +#
> +# The first <times> times this endpoint is called, it will return the given
> +# <retcode>, and if the <retry-after> is non-negative, it will set the
> +# Retry-After head to that value.
> +#
> +# Subsequent calls will return a 302 redirect to <path>.
> +#
> +# Supported error codes are 429,502,503, and 504
> +

I thought "error codes" were rephrased after the first round's review to some other term (which I do not recall--was it status?)?

Show 16 quoted lines
> +print_status() {
> +	if [ "$1" -eq "302" ]; then
> +		printf "Status: 302 Found\n"
> +	elif [ "$1" -eq "429" ]; then
> +		printf "Status: 429 Too Many Requests\n"
> +	elif [ "$1" -eq "502" ]; then
> +		printf "Status: 502 Bad Gateway\n"
> +	elif [ "$1" -eq "503" ]; then
> +		printf "Status: 503 Service Unavailable\n"
> +	elif [ "$1" -eq "504" ]; then
> +		printf "Status: 504 Gateway Timeout\n"
> +	else
> +		printf "Status: 500 Internal Server Error\n"
> +	fi
> +	printf "Content-Type: text/plain\n"
> +}
Style (Documentation/CodingGuidelines).
	print_status () {
		if test "$1" = "302"
		then
			printf "...";
		...
	}

but in this particular case, I do not see why we want if/else cascade. Perhaps

	print_status () {
		case "$1" in
		302)	printf "Status: 302 Found\n" ;;
		429)	... ;;
		...
		*)	printf "Status: 500 Internal Server Error\n" ;;
		esac
		printf "Content-Type: text/plain\n";
	}
would be more standard?

Also I am not sure why we want "printf ...\n" not "echo" here. If we want to talk HTTP ourselves strictly, I would understand avoiding "echo" and doing "printf ...\r\n", though. If we fear DOS line endings coming out of localized "echo", and ensure we use LF line ending even on Windows and Cygwin, it is sort of understandable but if that is what is going on, that does not explain a lone "echo" at the end of the caller.

Puzzled.
  +oIFS="$IFS"
> +IFS='/'
> +set -f
> +set -- $PATH_INFO
> +set +f
  +IFS="$oIFS"
Show 15 quoted lines
> +
> +# pull out first four path components
> +shift
> +nonce=$1
> +times=$2
> +code=$3
> +retry=$4
> +shift 4
> +
> +# glue the rest back together as redirect path
> +path=""
> +while [ "$#" -gt "0" ]; do
> +	path="${path}/$1"
> +	shift
> +done
Hmph.  Would this work better, I wonder?
	path=${PATH_INFO#*/}	;# discard leading '/'
	nonce=${path%%/*}	path=${path#*/}
	times=${path%%/*}	path=${path#*/}
	code=${path%%/*}	path=${path#*/}
	retry=${path%%/*}	path=${path#*/}
At least it is shorter and easier to read.
Show 6 quoted lines
> +# leave a cookie for this request/retry count
> +state_file="request_${REMOTE_ADDR}_${nonce}_${times}_${code}_${retry}"
> +
> +if [ ! -f "$state_file" ]; then
> +	echo 0 > "$state_file"
> +fi

Style (Documentation/CodingGuidelines, look for "For shell scripts specifically").

 - use "test" not "[]";
 - don't write ";then" on the same line (rule of thumb. you should
   be able to write your shell scripts without semicolon except for
   double-semicolons in case/esac statements)
 - don't leave SP between redirection operator '>' and its target
   file, i.e. write 'echo 0 >"$state_file"'.
Show 16 quoted lines
> +read -r cnt < "$state_file"
> +if [ "$cnt" -lt "$times" ]; then
> +	echo $((cnt+1)) > "$state_file"
> +
> +	# return error
> +	print_status "$code"
> +	if [ "$retry" -ge "0" ]; then
> +		printf "Retry-After: %s\n" "$retry"
> +	fi
> +else
> +	# redirect
> +	print_status 302
> +	printf "Location: %s?%s\n" "$path" "${QUERY_STRING}"
> +fi
> +
> +echo

This "echo" to the client also puzzles me further, after seeing puzzling use of "printf ...\n" earlier.

Show 13 quoted lines
> diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
> index 7df3c5373a..72aaed5a93 100755
> --- a/t/t5601-clone.sh
> +++ b/t/t5601-clone.sh
> @@ -756,6 +756,15 @@ test_expect_success 'partial clone using HTTP' '
>  	partial_clone "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server"
>  '
>  
> +test_expect_success 'partial clone using HTTP with redirect' '
> +	_NONCE=`gen_nonce` && export _NONCE &&
> +	curl "$HTTPD_URL/error_ntime/${_NONCE}/3/502/10/smart/server" &&
> +	curl "$HTTPD_URL/error_ntime/${_NONCE}/3/502/10/smart/server" &&
> +	curl "$HTTPD_URL/error_ntime/${_NONCE}/3/502/10/smart/server" &&

Why do we need to test "curl" here? Is this remnant of debugging of the server side?

Show 6 quoted lines
> +	partial_clone "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/error_ntime/${_NONCE}/3/502/10/smart/server"
> +'
> +
> +
>  # DO NOT add non-httpd-specific tests here, because the last part of this
>  # test script is only executed when httpd is available and enabled.
Previous: Sean McAllisterNext: Sean McAllister
Message 27 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.