From 0d82e3898b285e50790df0775583155800f3a85f Mon Sep 17 00:00:00 2001 From: Tales da Aparecida Date: Mon, 3 Aug 2026 12:21:11 -0300 Subject: [PATCH] fix: add timeouts to all production requests calls Without explicit timeouts, any requests.post() or requests.get() call can block indefinitely when a remote server hangs. This caused the ingester on db.kernelci.org to stall for 14 hours on a hung HTTP upload, leaving 543k submission files unprocessed. Fixes: https://github.com/kernelci/dashboard/issues/2041 Assisted-by: Claude Opus 4.6 Signed-off-by: Tales da Aparecida --- backend/kernelCI_app/constants/general.py | 5 +++++ backend/kernelCI_app/helpers/discordWebhook.py | 5 ++++- .../management/commands/helpers/log_excerpt_utils.py | 8 +++++++- backend/kernelCI_app/views/logDownloaderView.py | 3 ++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/backend/kernelCI_app/constants/general.py b/backend/kernelCI_app/constants/general.py index bd4539fe2..54047cef7 100644 --- a/backend/kernelCI_app/constants/general.py +++ b/backend/kernelCI_app/constants/general.py @@ -11,3 +11,8 @@ PRODUCTION_HOST = "https://dashboard.kernelci.org" STAGING_HOST = "https://staging.dashboard.kernelci.org" + +# Timeouts in seconds +REQUESTS_TIMEOUT_UPLOAD_IN_SECONDS = 30 +REQUESTS_TIMEOUT_WEBHOOK_IN_SECONDS = 10 +REQUESTS_TIMEOUT_FETCH_IN_SECONDS = 30 diff --git a/backend/kernelCI_app/helpers/discordWebhook.py b/backend/kernelCI_app/helpers/discordWebhook.py index 01f3af94b..769d3e886 100644 --- a/backend/kernelCI_app/helpers/discordWebhook.py +++ b/backend/kernelCI_app/helpers/discordWebhook.py @@ -8,6 +8,7 @@ get_notification_cache, set_notification_cache, ) +from kernelCI_app.constants.general import REQUESTS_TIMEOUT_WEBHOOK_IN_SECONDS from kernelCI_app.helpers.logger import log_message # For more information on discord webhook structure, visit @@ -97,7 +98,9 @@ def send_discord_notification( data["embeds"] = embeds try: - result = requests.post(url=url, json=data) + result = requests.post( + url=url, json=data, timeout=REQUESTS_TIMEOUT_WEBHOOK_IN_SECONDS + ) result.raise_for_status() except requests.HTTPError as e: log_message(e) diff --git a/backend/kernelCI_app/management/commands/helpers/log_excerpt_utils.py b/backend/kernelCI_app/management/commands/helpers/log_excerpt_utils.py index 07202a8a8..9c2303cee 100644 --- a/backend/kernelCI_app/management/commands/helpers/log_excerpt_utils.py +++ b/backend/kernelCI_app/management/commands/helpers/log_excerpt_utils.py @@ -7,6 +7,7 @@ from typing import Any, Literal, Optional import requests +from kernelCI_app.constants.general import REQUESTS_TIMEOUT_UPLOAD_IN_SECONDS from kernelCI_app.constants.ingester import ( CACHE_LOGS_SIZE_LIMIT, LOGEXCERPT_THRESHOLD, @@ -47,7 +48,12 @@ def upload_logexcerpt(logexcerpt: str, id: str) -> str: } files = {"file0": ("logexcerpt.txt.gz", f), "path": f"logexcerpt/{id}"} try: - r = requests.post(UPLOAD_URL, headers=hdr, files=files) + r = requests.post( + UPLOAD_URL, + headers=hdr, + files=files, + timeout=REQUESTS_TIMEOUT_UPLOAD_IN_SECONDS, + ) except Exception as e: logger.error("Error uploading logexcerpt for %s: %s", id, e) os.remove(logexcerpt_filename) diff --git a/backend/kernelCI_app/views/logDownloaderView.py b/backend/kernelCI_app/views/logDownloaderView.py index 80ec75e22..3e660357f 100644 --- a/backend/kernelCI_app/views/logDownloaderView.py +++ b/backend/kernelCI_app/views/logDownloaderView.py @@ -7,6 +7,7 @@ from rest_framework.views import APIView import requests +from kernelCI_app.constants.general import REQUESTS_TIMEOUT_FETCH_IN_SECONDS from kernelCI_app.constants.localization import ClientStrings from kernelCI_app.helpers.errorHandling import create_api_error_response from kernelCI_app.typeModels.logDownloader import ( @@ -17,7 +18,7 @@ def scrape_log_data(url): try: - response = requests.get(url) + response = requests.get(url, timeout=REQUESTS_TIMEOUT_FETCH_IN_SECONDS) response.raise_for_status() soup = BeautifulSoup(response.content, "html.parser")