diff --git a/scripts/generate-configs.sh b/scripts/generate-configs.sh index a1546d1..3da2709 100644 --- a/scripts/generate-configs.sh +++ b/scripts/generate-configs.sh @@ -87,10 +87,10 @@ while IFS= read -r line || [ -n "$line" ]; do normalized_ok=$((normalized_ok+1)) dbg " -> NORMALIZED: $dom_norm" - dbg " -> Querying API: ${API_URL}${dom_norm}" + dbg " -> Querying API: ${API_URL}${dom_norm}" # параметры retry - max_attempts=3 + max_attempts=5 attempt=0 resp="" http_code=0 @@ -98,55 +98,48 @@ while IFS= read -r line || [ -n "$line" ]; do while :; do attempt=$((attempt+1)) - # делаем запрос, записываем тело и код отдельно - # --compressed: поддержка gzip - # -sS: показывать ошибки curl в debug (если DEBUG enabled, они попадут в DEBUG_LOG) - # -m: общий timeout - # --connect-timeout: timeout на установление соединения - raw="$(curl -sS --compressed -m 20 --connect-timeout 8 -H 'Accept: application/json' -w '\n%{http_code}\n%{content_type}' "${API_URL}${dom_norm}" 2>>"$DEBUG_LOG" )" || true + raw="$(curl -sS --compressed \ + -m 10 --connect-timeout 5 \ + --retry 3 --retry-delay 1 \ + -H 'Accept: application/json' \ + -w '\n%{http_code}\n%{content_type}' \ + "${API_URL}${dom_norm}" 2>>"$DEBUG_LOG" || true)" - # последний \n%{http_code}\n%{content_type} — отделяем http_code="$(printf '%s' "$raw" | tail -n1)" content_type="$(printf '%s' "$raw" | tail -n2 | head -n1)" - resp="$(printf '%s' "$raw" | sed '$d' | sed '$d')" # всё кроме двух последних строк + resp="$(printf '%s' "$raw" | sed '$d' | sed '$d')" preview="$(printf '%s' "$resp" | tr '\n' ' ' | cut -c1-400)" dbg " -> Attempt #${attempt}: HTTP=${http_code}, Content-Type=${content_type}, preview=${preview}" - # если получили 200 и content-type похож на json — выходим if [ "$http_code" = "200" ] && printf '%s' "$content_type" | grep -qEi 'application/(json|javascript)|^text/json'; then break fi - # если тело выглядит как json (на всякий случай), тоже принимаем if jq -e . >/dev/null 2>&1 <<<"$resp"; then dbg " -> Body is valid JSON despite HTTP=${http_code}, accepting." break fi - # если исчерпали попытки — помечаем как ошибка if [ "$attempt" -ge "$max_attempts" ]; then api_error=$((api_error+1)) ERRORS["$dom_norm"]="http_${http_code}_or_nonjson" dbg " -> Failed after ${attempt} attempts: HTTP=${http_code}, preview=${preview}" - resp="" # явный маркер + resp="" break fi - # backoff: 0.5s, 1s, 2s ... - sleep_time=$(awk "BEGIN {printf \"%.0f\", 0.5 * (2 ^ ($attempt - 1))}") + # backoff: 1s, 2s, 4s, 8s ... + sleep_time=$((2 ** (attempt-1))) dbg " -> Retry after ${sleep_time}s..." sleep "$sleep_time" done - # если нет валидного JSON — пропускаем, с логом if [ -z "$resp" ] || ! jq -e . >/dev/null 2>&1 <<<"$resp"; then dbg " -> non-JSON or empty response, skipping domain: $dom_norm" continue fi - - # error handling if jq -e 'has("error")' <<<"$resp" >/dev/null; then err_msg="$(jq -r '.error' <<<"$resp")" dbg " -> API error: $err_msg" @@ -165,7 +158,6 @@ while IFS= read -r line || [ -n "$line" ]; do continue fi - # default case: treat as service DOM_ROLE["$dom_norm"]="service" SOURCES["$dom_norm"]="base" EXPANDED["$dom_norm"]=1 @@ -173,7 +165,6 @@ while IFS= read -r line || [ -n "$line" ]; do continue fi - # valid JSON without error -> must be site api_success=$((api_success+1)) DOM_ROLE["$dom_norm"]="site" SOURCES["$dom_norm"]="base"