From 6fec88251c1c780400f4335fb4f6e4f84b6156ba Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Mon, 27 Jul 2026 00:51:18 +0300 Subject: [PATCH] =?UTF-8?q?=D8=A5=D8=B5=D9=84=D8=A7=D8=AD=20=D8=A3=D8=AE?= =?UTF-8?q?=D8=B7=D8=A7=D8=A1=20=D8=B4=D8=A7=D8=B4=D8=A9=20=D8=A7=D9=84?= =?UTF-8?q?=D9=83=D8=A8=D8=A7=D8=AA=D9=86=20=D9=85=D9=86=20=D8=AA=D8=AD?= =?UTF-8?q?=D8=AF=D9=8A=D8=AB=20=D8=A7=D9=84=D8=B0=D9=83=D8=A7=D8=A1=20?= =?UTF-8?q?=D8=A7=D9=84=D8=A7=D8=B5=D8=B7=D9=86=D8=A7=D8=B9=D9=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit استرجاع شبكة أمان موقع السائق (انحدارة من الالتزام ab3be7e2): - كان شرط "Smart Mode" يتخطّى _startDriverLocationPollingWithTimer كلياً إذا جاء القبول من السوكيت. قبل إصلاح ترتيب الاتصال كان السوكيت يخسر دائماً فالـ polling يعمل ويحمل الموقع؛ وبعد أن صار يفوز تعطّلت شبكة الأمان. - وصول حدث القبول لا يعني أن تدفّق المواقع يعمل: التدفّق له شرط مستقل — تطبيق السائق يحقن passenger_id في update_location فقط إذا كان rideStatus نشطاً و BoxName.passengerID مكتوباً، وهو لا يُكتب إلا بعد فتح صفحة خريطة السائق (map_driver_controller.dart:2444). - الآن الـ polling يعمل دائماً، و handleDriverLocationUpdate يوقفه تلقائياً بعد 3 تحديثات ناجحة من السوكيت — وهذا المنطق كان موجوداً أصلاً وهو التصميم المقصود. السوكيت يبقى المسار السريع بلا فقدان شبكة الأمان. عدم تعطيل إنشاء الرحلة بانتظار سوكيت غير قابل للوصول: - ensureConnectedBeforeRide كانت تنتظر 4 ثوانٍ قبل كل طلب. سوكيتات Workerman تستمع نصّاً صريحاً على 2020/3030 بينما التطبيقان يستخدمان https:// عليها (nginx لا يمرّرها — انظر docker/nginx/default.conf)، فمصافحة TLS ضد منفذ غير TLS تتجمّد حتى المهلة ⇒ 4 ثوانٍ مهدورة في كل رحلة. - المهلة صارت 2ث، وأُضيف cooldown دقيقتين: بعد فشل قريب لا ننتظر إطلاقاً بل نحاول الاتصال في الخلفية ونكمل الطلب فوراً. Co-Authored-By: Claude Opus 5 --- .../home/map/map_socket_controller.dart | 21 +++++++++++++++++-- .../home/map/ride_lifecycle_controller.dart | 21 ++++++++++++------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/siro_rider/lib/controller/home/map/map_socket_controller.dart b/siro_rider/lib/controller/home/map/map_socket_controller.dart index 2f7a20fd..837be14a 100644 --- a/siro_rider/lib/controller/home/map/map_socket_controller.dart +++ b/siro_rider/lib/controller/home/map/map_socket_controller.dart @@ -225,11 +225,26 @@ class MapSocketController extends GetxController { /// (الحدث يُفقد نهائياً في تلك الحالة — لا طابور في غرف Socket.IO). /// لا يُفشل إنشاء الرحلة أبداً: عند انتهاء المهلة نكمل ونتّكل على /// الـ FCM/polling كشبكة احتياطية. + /// آخر مرة فشل فيها الاتصال — حتى لا نُبطئ كل طلب رحلة بانتظارٍ عقيم إذا كان + /// السوكيت غير قابل للوصول أصلاً (منفذ مغلق/TLS غير مُنهى/سيرفر واقف). + static DateTime? _lastConnectFailure; + static const Duration _failureCooldown = Duration(minutes: 2); + Future ensureConnectedBeforeRide({ - Duration timeout = const Duration(seconds: 4), + Duration timeout = const Duration(seconds: 2), }) async { if (isReadyForEvents) return true; + final lastFail = _lastConnectFailure; + if (lastFail != null && + DateTime.now().difference(lastFail) < _failureCooldown) { + // فشل قريباً — نبدأ محاولة الاتصال في الخلفية ولا نُعطّل الطلب إطلاقاً + initConnectionWithSocket(); + Log.print( + "⏭️ Skipping socket wait (recent failure). Ride proceeds on FCM/polling."); + return false; + } + await initConnectionWithSocket(); final deadline = DateTime.now().add(timeout); @@ -238,11 +253,13 @@ class MapSocketController extends GetxController { } if (isSocketConnected) { + _lastConnectFailure = null; Log.print("✅ Socket ready before ride creation."); return true; } + _lastConnectFailure = DateTime.now(); Log.print( - "⚠️ Socket not ready within ${timeout.inSeconds}s — continuing; FCM/polling will cover."); + "⚠️ Socket not ready within ${timeout.inMilliseconds}ms — continuing; FCM/polling will cover."); return false; } diff --git a/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart b/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart index 0fd1a236..46761780 100644 --- a/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart +++ b/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart @@ -3917,13 +3917,20 @@ class RideLifecycleController extends GetxController { PipService.enablePip(); - if (source == "Socket" && mapSocket.isSocketConnected) { - Log.print( - "🧠 Smart Mode: Socket accepted ride. Skipping polling, relying on WebSocket."); - } else { - Log.print("🔄 Fallback Mode: $source accepted ride. Starting polling."); - _startDriverLocationPollingWithTimer(); - } + // ⚠️ لا نثق بالسوكيت قبل أن **يُثبت** أنه يوصّل المواقع فعلاً. + // كان هنا شرط "Smart Mode" يتخطّى الـ polling كلياً إذا جاء القبول من + // السوكيت — وهو خطأ: وصول حدث القبول لا يعني أن تدفّق المواقع يعمل. + // تدفّق المواقع له شرط مستقل تماماً: تطبيق السائق يحقن passenger_id في + // update_location فقط إذا كان rideStatus نشطاً و BoxName.passengerID + // مكتوباً — وهو لا يُكتب إلا بعد فتح صفحة خريطة السائق. فبين القبول وفتح + // الصفحة لا يوجّه driver_socket أي موقع، وبلا polling لا يظهر الماركر أبداً. + // + // نشغّل الـ polling دائماً، و handleDriverLocationUpdate يوقفه تلقائياً + // بعد 3 تحديثات ناجحة من السوكيت (المنطق موجود هناك أصلاً). هكذا يبقى + // السوكيت هو المسار السريع بلا أن نفقد شبكة الأمان. + Log.print("🔄 Starting driver-location polling (source: $source). " + "Socket will take over and stop it once it proves delivery."); + _startDriverLocationPollingWithTimer(); } void _fillDriverDataLocally(Map data) {