From 76eb3297cd04f57cc8a647bad59994041e580414 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Fri, 10 Apr 2026 22:43:45 +0530 Subject: [PATCH] refactor: set Retry-After header directly --- frappe/app.py | 6 ------ frappe/concurrency_limiter.py | 4 ++-- frappe/exceptions.py | 7 ------- frappe/tests/test_concurrency_limiter.py | 6 ++---- 4 files changed, 4 insertions(+), 19 deletions(-) diff --git a/frappe/app.py b/frappe/app.py index d9b401cd5a..6a07c9c223 100644 --- a/frappe/app.py +++ b/frappe/app.py @@ -394,12 +394,6 @@ def handle_exception(e): elif http_status_code == 429: response = frappe.rate_limiter.respond() - elif http_status_code == 503: - retry_after = getattr(e, "retry_after", 10) - response = frappe.utils.response.report_error(503) - if response: - response.headers["Retry-After"] = str(retry_after) - else: response = ErrorPage( http_status_code=http_status_code, title=_("Server Error"), message=_("Uncaught Exception") diff --git a/frappe/concurrency_limiter.py b/frappe/concurrency_limiter.py index 04b743b5e4..0fe2e1a534 100644 --- a/frappe/concurrency_limiter.py +++ b/frappe/concurrency_limiter.py @@ -72,9 +72,9 @@ def concurrent_limit(limit: int | None = None, wait_timeout: int | None = None): if not acquired: from frappe.exceptions import ServiceUnavailableError - retry_after = max(1, int(effective_wait)) exc = ServiceUnavailableError(frappe._("Server is busy. Please try again in a few seconds.")) - exc.retry_after = retry_after + retry_after = max(1, int(effective_wait)) + frappe.local.response_headers.set("Retry-After", str(retry_after)) raise exc try: diff --git a/frappe/exceptions.py b/frappe/exceptions.py index 24c8c301ab..4b73db8b9c 100644 --- a/frappe/exceptions.py +++ b/frappe/exceptions.py @@ -87,14 +87,7 @@ class TooManyRequestsError(Exception): class ServiceUnavailableError(Exception): - """Raised when a concurrency limit is exceeded for an endpoint. - - Set :attr:`retry_after` (seconds) before raising so that the response - includes a ``Retry-After`` header. - """ - http_status_code = 503 - retry_after: int = 10 class ImproperDBConfigurationError(Exception): diff --git a/frappe/tests/test_concurrency_limiter.py b/frappe/tests/test_concurrency_limiter.py index fe27d9c3c4..67755c2db5 100644 --- a/frappe/tests/test_concurrency_limiter.py +++ b/frappe/tests/test_concurrency_limiter.py @@ -91,9 +91,8 @@ class TestConcurrentLimit(IntegrationTestCase): del frappe.local.request frappe.cache.delete(key) - def test_service_unavailable_has_correct_http_status_and_retry_after(self): - """The raised exception must carry http_status_code=503 and retry_after - equal to the configured wait_timeout.""" + def test_service_unavailable_has_correct_http_status(self): + """The raised exception must carry http_status_code=503.""" TIMEOUT = 1 @concurrent_limit(limit=1, wait_timeout=TIMEOUT) @@ -110,7 +109,6 @@ class TestConcurrentLimit(IntegrationTestCase): fn() exc = ctx.exception self.assertEqual(exc.http_status_code, 503) - self.assertEqual(exc.retry_after, TIMEOUT) finally: del frappe.local.request frappe.cache.delete(key)