Update: 2026-07-30 02:27:45
This commit is contained in:
@@ -47,16 +47,56 @@ try {
|
||||
$processed = 0;
|
||||
$failed = 0;
|
||||
|
||||
// Get ALL pending items (no infinite loop!)
|
||||
// Get pending items whose batch is ready for processing.
|
||||
//
|
||||
// The b.status <> 'uploading' filter is essential: queue rows are inserted as
|
||||
// 'pending' the moment each image lands, while total_images is still growing.
|
||||
// Picking them up mid-upload made the batch look complete after the first
|
||||
// image, which locked the batch and made every later upload fail with
|
||||
// "لا يمكن إضافة صور لدفعة تمت معالجتها".
|
||||
$stmt = $db->prepare("
|
||||
SELECT id FROM invoice_processing_queue
|
||||
WHERE status = 'pending'
|
||||
ORDER BY created_at ASC
|
||||
SELECT q.id
|
||||
FROM invoice_processing_queue q
|
||||
JOIN invoice_batches b ON q.batch_id = b.id
|
||||
WHERE q.status = 'pending'
|
||||
AND q.attempts < COALESCE(q.max_attempts, 3)
|
||||
AND b.status <> 'uploading'
|
||||
ORDER BY q.created_at ASC
|
||||
LIMIT 20
|
||||
");
|
||||
$stmt->execute();
|
||||
$items = $stmt->fetchAll(\PDO::FETCH_COLUMN);
|
||||
|
||||
// Rescue items abandoned in 'processing' by a crashed worker. claimed_at is
|
||||
// set at claim time, so "claimed over 10 minutes ago and still processing"
|
||||
// reliably means the owning process died mid-flight.
|
||||
$rescued = $db->prepare("
|
||||
UPDATE invoice_processing_queue
|
||||
SET status = 'pending',
|
||||
error_message = 'Reclaimed from a stalled worker'
|
||||
WHERE status = 'processing'
|
||||
AND claimed_at IS NOT NULL
|
||||
AND claimed_at < (NOW() - INTERVAL 10 MINUTE)
|
||||
");
|
||||
$rescued->execute();
|
||||
if ($rescued->rowCount() > 0) {
|
||||
workerLog("Reclaimed {$rescued->rowCount()} stalled item(s) back to pending.");
|
||||
}
|
||||
|
||||
// Also close out batches whose images all reached a terminal state but whose
|
||||
// status was never flipped (e.g. the worker died right after the last item).
|
||||
$stuck = $db->query("
|
||||
SELECT id FROM invoice_batches
|
||||
WHERE status = 'processing'
|
||||
AND total_images > 0
|
||||
AND (processed_images + failed_images) >= total_images
|
||||
LIMIT 50
|
||||
")->fetchAll(\PDO::FETCH_COLUMN);
|
||||
foreach ($stuck as $stuckBatchId) {
|
||||
workerLog("Closing stuck batch: $stuckBatchId");
|
||||
InvoiceProcessor::checkBatchCompletion((string)$stuckBatchId);
|
||||
}
|
||||
|
||||
if (empty($items)) {
|
||||
workerLog("No pending items. Exiting.");
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user