115 lines
5.8 KiB
PHP
115 lines
5.8 KiB
PHP
<?php
|
||
/**
|
||
* cron_sms_requests.php — شبكة الأمان لمسار الطلب بالرسائل
|
||
* ─────────────────────────────────────────────────────────────
|
||
* المعالجة الأصلية تتم فورياً داخل webhook_sms/webhook.php، لأن الراكب
|
||
* واقف ينتظر رداً ودقيقة تأخير تعني أنه ظنّ الرقم معطّلاً. هذا الكرون
|
||
* لا يعالج المسار السعيد إذن — وظيفته ما يسقط منه:
|
||
*
|
||
* ١. طلبات بقيت 'pending' (فشل شبكي عابر وقت الإنشاء)
|
||
* ٢. طلبات عَلِقت في 'dispatching' (مات التنفيذ بين القفل والنتيجة)
|
||
* ٣. رحلات لم يقبلها أحد — نخبر الراكب بدل تركه ينتظر بلا خبر
|
||
*
|
||
* الثالثة هي الأهم: راكب التطبيق يرى الخريطة فيعرف أن البحث جارٍ.
|
||
* راكب الرسائل لا يرى شيئاً — صمتنا عنده يساوي عطلاً.
|
||
*
|
||
* جدولة: كل دقيقة.
|
||
* *\/1 * * * * docker compose exec -T php php /var/www/backend/bot/cron_sms_requests.php
|
||
*/
|
||
|
||
require_once __DIR__ . '/../core/bootstrap.php';
|
||
require_once __DIR__ . '/../sms/ride_request.php';
|
||
|
||
// طلب عَلِق في 'dispatching' أطول من هذا يُعتبر ميتاً ويُعاد للطابور.
|
||
const SMS_STUCK_MINUTES = 3;
|
||
|
||
// بعد هذه المدة بلا سائق نخبر الراكب. أقصر من مهلة التطبيق عمداً:
|
||
// من ينتظر بلا شاشة يفقد صبره أسرع.
|
||
const SMS_NO_DRIVER_MINUTES = 6;
|
||
|
||
try {
|
||
$con = Database::get('main');
|
||
} catch (Exception $e) {
|
||
fwrite(STDERR, '[sms-cron] DB unavailable: ' . $e->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";
|