From 4393087fa715dbfcb81ae201ff0817902d3de91f Mon Sep 17 00:00:00 2001 From: Zareian Date: Sun, 27 Sep 2026 22:14:23 +0330 Subject: [PATCH] wait up to 10 s to reach Kavenegar and 30 s for its reply Iranian network paths can be slow; the owner asked for 30 s. The frontend's requestOtp timeout goes to 45 s in the same change so it outlasts both. Co-Authored-By: Claude Opus 5.5 --- accounts/services.py | 12 ++++++++---- accounts/tests_otp_limits.py | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/accounts/services.py b/accounts/services.py index d55b88a..2adfeb2 100644 --- a/accounts/services.py +++ b/accounts/services.py @@ -103,9 +103,13 @@ def send_verify_lookup(*, phone: str, template: str, token: str) -> None: ) -# کاوه‌نگار گاهی بیش از ۵ ثانیه طول می‌کشد (۵٫۴ ثانیه در ۲۰۲۶-۰۹-۲۷)؛ workerهای -# gunicorn مهلتِ ۱۲۰ ثانیه دارند و gthread است، پس ۱۰ ثانیه کسی را قفل نمی‌کند. -SMS_READ_TIMEOUT_SECONDS = 10 +# کاوه‌نگار گاهی بیش از ۵ ثانیه طول می‌کشد (۵٫۴ ثانیه در ۲۰۲۶-۰۹-۲۷) و شبکه‌ی ایران +# کند می‌شود؛ صاحبِ پروژه ۳۰ ثانیه خواست. جمعِ دو مهلت (۴۰ ثانیه) باید زیرِ مهلتِ +# فرانت برای همین درخواست بماند (`requestOtp` در MathApp_frontend، ۴۵ ثانیه)، وگرنه +# کاربر «ارتباط برقرار نشد» می‌بیند در حالی که پیامک رسیده. gunicorn ۱۲۰ ثانیه و +# gthread است؛ مهلتِ nginx و ArvanCloud برای این مسیر سنجیده نشده. +SMS_CONNECT_TIMEOUT_SECONDS = 10 +SMS_READ_TIMEOUT_SECONDS = 30 def _kavenegar_post(*, phone: str, method: str, payload: dict) -> None: @@ -122,7 +126,7 @@ def _kavenegar_post(*, phone: str, method: str, payload: dict) -> None: f'https://api.kavenegar.com/v1/{settings.KAVENEGAR_API_KEY}/{method}', data=payload, # (اتصال، خواندن). وصل‌نشدن یعنی قطعاً نرفت؛ دیر رسیدنِ جواب یعنی نامعلوم. - timeout=(3.05, SMS_READ_TIMEOUT_SECONDS), + timeout=(SMS_CONNECT_TIMEOUT_SECONDS, SMS_READ_TIMEOUT_SECONDS), ) except requests.ReadTimeout: logger.warning( diff --git a/accounts/tests_otp_limits.py b/accounts/tests_otp_limits.py index dd73364..6b22e3b 100644 --- a/accounts/tests_otp_limits.py +++ b/accounts/tests_otp_limits.py @@ -190,7 +190,7 @@ class SlowProviderTests(TestCase): self.assertEqual(_request('09121114402').status_code, 503) self.assertFalse(OTPCode.objects.filter(phone='09121114402').exists()) - def test_read_timeout_is_ten_seconds(self): + def test_timeouts_leave_room_for_a_slow_iranian_network(self): with patch('accounts.services.requests.post', return_value=_kavenegar_reply()) as post: _request('09121114403') - self.assertEqual(post.call_args.kwargs['timeout'], (3.05, 10)) + self.assertEqual(post.call_args.kwargs['timeout'], (10, 30))