حرس السوكيتات المكرّرة للسائق — سبب «notified 0/0» وتحذيرات null
في لوج الإنتاج ثلاثة اتصالات متزامنة للسائق نفسه (التطبيق يفتح سوكيتاً من
location_controller وآخر من background_service ومحاولات لم تُنظَّف):
✅ Driver Connected: #243ea… (×3)
ومعالج disconnect كان ينفّذ unset($connectedDrivers[$driverId]) بلا تحقّق من
أيّ سوكيت أُغلق. فإغلاق نسخة واحدة كان يُطفئ السائق فعلياً وهو متصل:
1) dispatch_order يراه offline فيضع الطلب في طابور الانتظار بدل إرساله،
ويظهر في اللوج: 🚫 Ride #2569 cancelled — notified 0/0 driver(s).
2) update_location من سوكيت ما زال حياً يجد $driverState[$driverId] محذوفاً،
و &$driverState[...] يُنشئ مدخلاً null فتُقرأ منه كل الحسابات:
Warning: Trying to access array offset on value of type null (860-872)
Warning: Undefined array key "status" (907)
الإصلاحان:
- نحفظ sid (معرّف السوكيت) مع السجلّ، ولا ننظّف في disconnect إلا إذا كان
المُغلَق هو المسجَّل حالياً؛ وإلا نتركه ونسجّل «stale duplicate».
- حرس على $driverState في update_location: يُعاد بناؤه إن غاب لأي سبب
(إغلاق نسخة أخرى، إعادة تشغيل) بدل القراءة من null.
سيرفر فقط — لا يحتاج بناء التطبيقات. يبقى فتح التطبيق لعدة سوكيتات هدراً
في الحركة يستحق إصلاحاً في الطرف الآخر لاحقاً.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e6504acdea
commit
899a18b52d
@@ -743,10 +743,18 @@ $io->on('connection', function ($socket) use ($INTERNAL_KEY) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$socket->join('driver_' . $driverId);
|
$socket->join('driver_' . $driverId);
|
||||||
|
|
||||||
|
// نحفظ معرّف السوكيت مع السجلّ: التطبيق يفتح أكثر من اتصال للسائق نفسه
|
||||||
|
// (location_controller و background_service ومحاولات لم تُنظَّف)، وحين يُغلق
|
||||||
|
// أحدها كان معالج disconnect يمحو السائق من السجلّ كاملاً بينما البقية
|
||||||
|
// متصلة — فيعتبره dispatch_order غير متصل ويضع الطلب في طابور الانتظار،
|
||||||
|
// ويظهر في اللوج «notified 0/0 driver(s)».
|
||||||
|
$socketId = $socket->id;
|
||||||
$connectedDrivers[$driverId] = [
|
$connectedDrivers[$driverId] = [
|
||||||
'conn' => $socket,
|
'conn' => $socket,
|
||||||
'platform' => $platform,
|
'platform' => $platform,
|
||||||
'token' => $fcmToken,
|
'token' => $fcmToken,
|
||||||
|
'sid' => $socketId,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (!isset($driverState[$driverId])) {
|
if (!isset($driverState[$driverId])) {
|
||||||
@@ -837,6 +845,21 @@ $io->on('connection', function ($socket) use ($INTERNAL_KEY) {
|
|||||||
|
|
||||||
if ($lat === null || $lng === null) return;
|
if ($lat === null || $lng === null) return;
|
||||||
|
|
||||||
|
// حرس: لو حُذفت الحالة (إغلاق سوكيت آخر لنفس السائق، أو إعادة تشغيل)
|
||||||
|
// فإن &$driverState[$driverId] يُنشئ مدخلاً null فتقرأ كل الأسطر التالية
|
||||||
|
// من null — وهذا مصدر تحذيرات «array offset on value of type null» في
|
||||||
|
// الأسطر 860‑872 و«Undefined array key status» في 907.
|
||||||
|
if (!isset($driverState[$driverId]) || !is_array($driverState[$driverId])) {
|
||||||
|
$driverState[$driverId] = [
|
||||||
|
'lat' => 0.0,
|
||||||
|
'lng' => 0.0,
|
||||||
|
'speed' => -999.0,
|
||||||
|
'heading' => -999.0,
|
||||||
|
'status' => '',
|
||||||
|
'expire_ts' => 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$state = &$driverState[$driverId];
|
$state = &$driverState[$driverId];
|
||||||
$now = time();
|
$now = time();
|
||||||
|
|
||||||
@@ -996,9 +1019,19 @@ $io->on('connection', function ($socket) use ($INTERNAL_KEY) {
|
|||||||
], $INTERNAL_KEY, $busFwdThrottle);
|
], $INTERNAL_KEY, $busFwdThrottle);
|
||||||
});
|
});
|
||||||
|
|
||||||
$socket->on('disconnect', function () use ($driverId) {
|
$socket->on('disconnect', function () use ($driverId, $socketId) {
|
||||||
global $connectedDrivers, $driverState, $fwdThrottle;
|
global $connectedDrivers, $driverState, $fwdThrottle;
|
||||||
|
|
||||||
|
// لا ننظّف إلا إذا كان المُغلَق هو السوكيت المسجَّل حالياً. الجهاز يفتح
|
||||||
|
// عدة اتصالات للسائق نفسه، وتنظيف السجلّ عند إغلاق نسخة قديمة كان
|
||||||
|
// يُطفئ السائق فعلياً وهو متصل: التوزيع يراه offline، و update_location
|
||||||
|
// من السوكيت الحيّ يجد $driverState محذوفاً فتظهر تحذيرات null.
|
||||||
|
$registeredSid = $connectedDrivers[$driverId]['sid'] ?? null;
|
||||||
|
if ($registeredSid !== null && $registeredSid !== $socketId) {
|
||||||
|
logMsg("↩️ Stale duplicate socket closed for #$driverId — registry kept.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unset($connectedDrivers[$driverId]);
|
unset($connectedDrivers[$driverId]);
|
||||||
unset($driverState[$driverId]);
|
unset($driverState[$driverId]);
|
||||||
unset($fwdThrottle[$driverId]);
|
unset($fwdThrottle[$driverId]);
|
||||||
|
|||||||
Reference in New Issue
Block a user