getMessage() . "\n"); exit(1); } // ═══════════════════════════════════════════════════════════════ // ١) تحرير العالق // ═══════════════════════════════════════════════════════════════ $freed = 0; try { $st = $con->prepare(" UPDATE sms_ride_requests SET status = 'pending' WHERE status = 'dispatching' AND updated_at < NOW() - INTERVAL " . SMS_STUCK_MINUTES . " MINUTE "); $st->execute(); $freed = $st->rowCount(); } catch (PDOException $e) { fwrite(STDERR, '[sms-cron] تعذّر تحرير العالق: ' . $e->getMessage() . "\n"); } // ═══════════════════════════════════════════════════════════════ // ٢) إعادة محاولة المعلّق // ═══════════════════════════════════════════════════════════════ $retried = 0; $created = 0; try { $st = $con->query(" SELECT id, sender_norm, passenger_id, start_location, end_location, start_name, end_name, distance, duration, attempts FROM sms_ride_requests WHERE status = 'pending' AND passenger_id IS NOT NULL ORDER BY id ASC LIMIT 50 "); foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $req) { $retried++; if (smsProcessRequest($con, $req)) $created++; } } catch (PDOException $e) { fwrite(STDERR, '[sms-cron] فشل إعادة المحاولة: ' . $e->getMessage() . "\n"); } // ═══════════════════════════════════════════════════════════════ // ٣) إبلاغ من لم يجد سائقاً // // ‏نعتمد على حالة الرحلة نفسها لا على مؤقّت منفصل: ما دامت 'waiting' // ‏فلا سائق قَبِل. والوسم في fail_reason يمنع تكرار الإبلاغ كل دقيقة. // ═══════════════════════════════════════════════════════════════ $notified = 0; try { $st = $con->prepare(" SELECT s.id, s.sender_norm, s.ride_id FROM sms_ride_requests s JOIN ride r ON r.id = s.ride_id WHERE s.status = 'dispatched' AND (s.fail_reason IS NULL OR s.fail_reason <> 'no_driver_notified') AND r.status IN ('waiting', 'wait') AND s.updated_at < NOW() - INTERVAL " . SMS_NO_DRIVER_MINUTES . " MINUTE LIMIT 50 "); $st->execute(); foreach ($st->fetchAll(PDO::FETCH_ASSOC) as $row) { // ‏الوسم أولاً ثم الإرسال: لو انقطع التنفيذ بينهما، أسوأ نتيجة // ‏رسالة لم تصل — لا رسالة تصل كل دقيقة. $con->prepare("UPDATE sms_ride_requests SET fail_reason='no_driver_notified' WHERE id=?") ->execute([$row['id']]); smsEnqueue($con, $row['sender_norm'], 'سيرو: ما زلنا نبحث عن سائق قريب منك. سنرسل لك رسالة فور قبول أحدهم،' . ' أو أعد إرسال طلبك بعد قليل.', 'no_driver_yet', (string) $row['ride_id']); $notified++; } } catch (PDOException $e) { fwrite(STDERR, '[sms-cron] تعذّر إبلاغ من بلا سائق: ' . $e->getMessage() . "\n"); } echo "[sms-cron] حُرِّر {$freed}، أُعيدت محاولة {$retried}، أُنشئ {$created}،" . " أُبلغ {$notified}\n";