diff --git a/admin/DashboardController.php b/admin/DashboardController.php index 8697784..817f2a0 100644 --- a/admin/DashboardController.php +++ b/admin/DashboardController.php @@ -202,12 +202,11 @@ HTML; header('X-Accel-Buffering: no'); // disable nginx buffering header('Connection: keep-alive'); - set_time_limit(0); + set_time_limit(35); ignore_user_abort(false); $lastId = max(0, (int)($_GET['after'] ?? 0)); - // Anchor to latest ID if no after param if ($lastId === 0) { try { $row = db()->query('SELECT id FROM webhook_logs ORDER BY id DESC LIMIT 1')->fetch(); @@ -215,7 +214,13 @@ HTML; } catch (\PDOException $e) {} } - while (!connection_aborted()) { + // Tell the client to reconnect after 3s if connection drops + echo "retry: 3000\n\n"; + ob_flush(); flush(); + + $deadline = time() + 28; // release worker after 28s, client auto-reconnects + + while (!connection_aborted() && time() < $deadline) { try { $stmt = db()->prepare( 'SELECT id, event_field, from_number, contact_name, @@ -229,7 +234,7 @@ HTML; $lastId = (int)end($rows)['id']; echo 'data: ' . json_encode($rows, JSON_UNESCAPED_UNICODE) . "\n\n"; } else { - echo ": heartbeat\n\n"; // keep connection alive + echo ": heartbeat\n\n"; } } catch (\PDOException $e) { echo ": db-error\n\n"; @@ -237,7 +242,11 @@ HTML; ob_flush(); flush(); - sleep(2); + + // Sleep in 200ms chunks so connection_aborted() is checked frequently + for ($i = 0; $i < 10 && !connection_aborted(); $i++) { + usleep(200000); + } } exit; }