Update: 2026-07-09 03:41:48

This commit is contained in:
Hamza-Ayed
2026-07-09 03:41:48 +03:00
parent 7dff7b6973
commit 70718946f5
10 changed files with 295 additions and 639 deletions
+70 -39
View File
@@ -1,53 +1,85 @@
<?php
// cron_cleanup_waiting.php
// مسار الاتصال بقاعدة البيانات
require_once __DIR__ . '/../../get_connect.php';
// cron_ride_timeout.php
// 🔥 أُعيدت كتابته بالكامل: كان يعتمد على جدول waitingRides الذي لم يعد
// يُملأ من تدفق add_ride.php الحقيقي (addWaitingRide.php لا يُستدعى من هناك)،
// فكانت الرحلات العالقة بحالة 'waiting' لا تُصفَّر أبداً. الآن يعمل مباشرة
// على جدول ride باستخدام أعمدة date/time المكتوبة فعلياً عند الإنشاء.
require_once __DIR__ . '/../../core/bootstrap.php';
require_once __DIR__ . '/../../functions.php';
// تسجيل في اللوج لبداية العملية
error_log("⏰ [Cleanup Cron] Started cleaning old waiting rides...");
$minutesLimit = 15;
try {
// المدة المسموحة بالدقائق
$minutesLimit = 15;
$con = Database::get('main');
// =========================================================
// الخطوة 1: تحديث الحالة في الجدول الرئيسي (الأرشيف)
// الخطوة 1: جلب الرحلات العالقة (status='waiting' منذ أكثر من 15 دقيقة)
// =========================================================
// نقوم بتحديث حالة الرحلات التي ستُحذف ليعلم الراكب أنها انتهت (Time Out)
// بدلاً من أن تبقى 'waiting' للأبد في سجلات الراكب
$sqlUpdate = "UPDATE ride
SET status = 'timeout'
WHERE id IN (
SELECT id FROM waitingRides
WHERE created_at < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)
) AND status = 'waiting'"; // نتأكد أننا نحدث ما هو معلق فقط
$sqlSelect = "SELECT id, passenger_id FROM ride
WHERE status = 'waiting'
AND TIMESTAMP(`date`, `time`) < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)";
$stmtSelect = $con->prepare($sqlSelect);
$stmtSelect->execute();
$staleRides = $stmtSelect->fetchAll(PDO::FETCH_ASSOC);
$stmtUpdate = $con->prepare($sqlUpdate);
$stmtUpdate->execute();
$updatedCount = $stmtUpdate->rowCount();
$updatedCount = 0;
if (!empty($staleRides)) {
$sqlUpdate = "UPDATE ride SET status = 'timeout', updated_at = NOW() WHERE id = ? AND status = 'waiting'";
$stmtUpdate = $con->prepare($sqlUpdate);
// نسخة أرشيفية (best-effort)
$con_ride = null;
try {
$con_ride = Database::get('ride');
} catch (Exception $e) {
error_log("[cron_ride_timeout] Secondary ride DB unavailable: " . $e->getMessage());
}
$stmtUpdate2 = $con_ride ? $con_ride->prepare(
"UPDATE ride SET status = 'timeout', updated_at = NOW() WHERE id = ? AND status = 'waiting'"
) : null;
foreach ($staleRides as $ride) {
$rideId = $ride['id'];
$stmtUpdate->execute([$rideId]);
$updatedCount += $stmtUpdate->rowCount();
if ($stmtUpdate2) {
try {
$stmtUpdate2->execute([$rideId]);
} catch (PDOException $e) {
error_log("[cron_ride_timeout] Secondary DB update failed for #$rideId: " . $e->getMessage());
}
}
// 🆕 تنظيف Redis + إعلام أي سائقين ما زالوا يرون هذا الطلب على أنه ملغى
sendToLocationServer('cancel_ride', [
'ride_id' => $rideId,
'driver_id' => 0,
'reason' => 'timeout',
]);
}
}
// =========================================================
// الخطوة 2: الحذف من جدول الانتظار (تنظيف Hot Data)
// الخطوة 2: تنظيف جدول waitingRides القديم (إن وُجدت صفوف فيه من مسار قديم)
// =========================================================
$sqlDelete = "DELETE FROM waitingRides
WHERE created_at < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)";
$deletedCount = 0;
try {
$sqlDelete = "DELETE FROM waitingRides WHERE created_at < DATE_SUB(NOW(), INTERVAL $minutesLimit MINUTE)";
$stmtDelete = $con->prepare($sqlDelete);
$stmtDelete->execute();
$deletedCount = $stmtDelete->rowCount();
} catch (PDOException $e) {
error_log("[cron_ride_timeout] waitingRides cleanup skipped: " . $e->getMessage());
}
$stmtDelete = $con->prepare($sqlDelete);
$stmtDelete->execute();
$deletedCount = $stmtDelete->rowCount();
// =========================================================
// الخطوة 3: (اختياري) تنظيف الريدز
// =========================================================
// بما أنك تستخدم Redis، المفترض أن تحذفها منه أيضاً.
// لكن بما أن الريدز يعتمد على TTL (Expire) أو سيتم تحديثه عند الطلب القادم،
// فالحذف من الـ MySQL يكفي لأن getRideWaiting سيفحص MySQL ولن يجدها.
// تقرير العملية
if ($deletedCount > 0) {
$msg = "✅ [Cleanup Cron] Success: Timed out $updatedCount rides in Main DB, and Deleted $deletedCount rides from Waiting DB.";
if ($updatedCount > 0 || $deletedCount > 0) {
$msg = "✅ [Cleanup Cron] Success: Timed out $updatedCount ride(s) in ride table, and cleaned $deletedCount legacy waitingRides row(s).";
error_log($msg);
echo json_encode(["status" => "success", "message" => $msg]);
} else {
@@ -59,7 +91,6 @@ try {
} catch (PDOException $e) {
$errorMsg = "❌ [Cleanup Cron] Error: " . $e->getMessage();
error_log($errorMsg);
error_log("[cron_ride_timeout] Error: " . $e->getMessage());
echo json_encode(["status" => "failure", "message" => "An internal error occurred."]);
}
?>
?>