curl: Also map HTTP errors for retries
authorColin Walters <walters@verbum.org>
Fri, 15 Mar 2024 22:41:02 +0000 (18:41 -0400)
committerColin Walters <walters@verbum.org>
Fri, 15 Mar 2024 22:45:22 +0000 (18:45 -0400)
When we added the retry logic, the intention here was definitely
to do it not just for network errors but also e.g. HTTP 500s and
the like.

xref https://pagure.io/releng/issue/11439
where we rather painfully debugged that this was missing.

src/libostree/ostree-fetcher-curl.c
src/libostree/ostree-fetcher-soup.c
src/libostree/ostree-fetcher-soup3.c
src/libostree/ostree-fetcher-util.c
src/libostree/ostree-fetcher-util.h

index e9b9672b0286f3701803bf07cc8f459c8dd48e27..d6902893ff1dc162876b1d26fdd6453fac281007 100644 (file)
@@ -322,6 +322,8 @@ check_multi_info (OstreeFetcher *fetcher)
 
       req = g_task_get_task_data (task);
 
+      gboolean retry_all = (!is_file && req->fetcher->opt_retry_all);
+
       if (req->caught_write_error)
         g_task_return_error (task, g_steal_pointer (&req->caught_write_error));
       else if (curlres != CURLE_OK)
@@ -337,12 +339,9 @@ check_multi_info (OstreeFetcher *fetcher)
               /* When it is not a file, we want to retry the request.
                * We accomplish that by using G_IO_ERROR_TIMED_OUT.
                */
-              gboolean opt_retry_all = req->fetcher->opt_retry_all;
-              int g_io_error_code
-                  = (is_file || !opt_retry_all) ? G_IO_ERROR_FAILED : G_IO_ERROR_TIMED_OUT;
-              g_task_return_new_error (task, G_IO_ERROR, g_io_error_code,
-                                       "While fetching %s: [%u] %s", eff_url, curlres,
-                                       curl_easy_strerror (curlres));
+              g_task_return_new_error (
+                  task, G_IO_ERROR, retry_all ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR,
+                  "While fetching %s: [%u] %s", eff_url, curlres, curl_easy_strerror (curlres));
               _ostree_fetcher_journal_failure (req->fetcher->remote_name, eff_url,
                                                curl_easy_strerror (curlres));
             }
@@ -362,12 +361,13 @@ check_multi_info (OstreeFetcher *fetcher)
 
           if (!is_file && !(response >= 200 && response < 300) && response != 304)
             {
-              GIOErrorEnum giocode = _ostree_fetcher_http_status_code_to_io_error (response);
+              GIOErrorEnum giocode
+                  = _ostree_fetcher_http_status_code_to_io_error (response, retry_all);
 
               if (req->idx + 1 == req->mirrorlist->len)
                 {
-                  g_autofree char *response_msg
-                      = g_strdup_printf ("Server returned HTTP %lu", response);
+                  g_autofree char *response_msg = g_strdup_printf (
+                      "While fetching %s: Server returned HTTP %lu", eff_url, response);
                   g_task_return_new_error (task, G_IO_ERROR, giocode, "%s", response_msg);
                   if (req->fetcher->remote_name
                       && !((req->flags & OSTREE_FETCHER_REQUEST_OPTIONAL_CONTENT) > 0
index e75e72bf7d995c2b14d2349ac7bb89790dc79ae3..b68c4fd1246fdf333b55782b4da2816f6e68a113 100644 (file)
@@ -1094,7 +1094,7 @@ on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data)
 #endif
                   break;
                 default:
-                  code = _ostree_fetcher_http_status_code_to_io_error (msg->status_code);
+                  code = _ostree_fetcher_http_status_code_to_io_error (msg->status_code, FALSE);
                   break;
                 }
 
index 6de5c1edb57d5e1b26978f45f4ca9ab17befd690..fa71b363b5ed3ef0064f8d3528c6b7d23d3ef0da 100644 (file)
@@ -621,7 +621,7 @@ on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data)
             {
               g_autofree char *uristring
                   = g_uri_to_string (soup_message_get_uri (request->message));
-              GIOErrorEnum code = _ostree_fetcher_http_status_code_to_io_error (status);
+              GIOErrorEnum code = _ostree_fetcher_http_status_code_to_io_error (status, FALSE);
               {
                 g_autofree char *errmsg = g_strdup_printf ("Server returned status %u: %s", status,
                                                            soup_status_get_phrase (status));
index b797bee753a7ce084ad9712cd1de13254b866c14..7ca9f07d6dfa75244e6137f5fe8732fc571a1ff6 100644 (file)
@@ -224,7 +224,7 @@ _ostree_fetcher_should_retry_request (const GError *error, guint n_retries_remai
  * a #GIOErrorEnum. This will return %G_IO_ERROR_FAILED if the status code is
  * unknown or otherwise unhandled. */
 GIOErrorEnum
-_ostree_fetcher_http_status_code_to_io_error (guint status_code)
+_ostree_fetcher_http_status_code_to_io_error (guint status_code, gboolean should_retry)
 {
   switch (status_code)
     {
@@ -235,8 +235,9 @@ _ostree_fetcher_http_status_code_to_io_error (guint status_code)
     case 408: /* SOUP_STATUS_REQUEST_TIMEOUT */
       return G_IO_ERROR_TIMED_OUT;
     case 500: /* SOUP_STATUS_INTERNAL_SERVER_ERROR */
-      return G_IO_ERROR_BUSY;
+      /* retries are always mapped to timeouts, see similar logic in the curl error handling */
+      return should_retry ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR_BUSY;
     default:
-      return G_IO_ERROR_FAILED;
+      return should_retry ? G_IO_ERROR_TIMED_OUT : G_IO_ERROR_FAILED;
     }
 }
index 97233e1f337707c4ff16bf99eb5b685bfe79c645..ef5ad657a56f81dec94ea5d7caa9ca580449cb7e 100644 (file)
@@ -57,7 +57,7 @@ void _ostree_fetcher_journal_failure (const char *remote_name, const char *url,
 
 gboolean _ostree_fetcher_should_retry_request (const GError *error, guint n_retries_remaining);
 
-GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code);
+GIOErrorEnum _ostree_fetcher_http_status_code_to_io_error (guint status_code, gboolean retry_all);
 
 G_END_DECLS