Fix browser terminal falsely reporting 'failed to start'
Deploy Ladill Hosting / deploy (push) Successful in 1m15s
Deploy Ladill Hosting / deploy (push) Successful in 1m15s
createSession only waited 2.5s for the worker to flip starting->running, but the worker cold-boots the framework (php artisan) + opens the shell, which under load exceeds that. On timeout it also overwrote the (healthy) worker's metadata to status=failed, so customers saw 'Terminal worker failed to start' even though the shell was live. Wait up to 8s and return early once status is known; never fabricate a failure — the worker records real boot errors itself. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7e5ca3dce4
commit
ff3959b734
@@ -10,6 +10,11 @@ class BrowserTerminalSessionManager
|
|||||||
{
|
{
|
||||||
private const IDLE_TIMEOUT_SECONDS = 120;
|
private const IDLE_TIMEOUT_SECONDS = 120;
|
||||||
|
|
||||||
|
// How long createSession() waits for the worker to cold-boot the framework
|
||||||
|
// and open the shell before returning. Generous so a slow/loaded boot isn't
|
||||||
|
// mistaken for a failure; the wait returns early once the status is known.
|
||||||
|
private const STARTUP_TIMEOUT_SECONDS = 8.0;
|
||||||
|
|
||||||
public function createSession(HostingAccount $account, int $userId, string $relativePath = '/public_html', int $cols = 120, int $rows = 30): array
|
public function createSession(HostingAccount $account, int $userId, string $relativePath = '/public_html', int $cols = 120, int $rows = 30): array
|
||||||
{
|
{
|
||||||
$sessionId = (string) Str::uuid();
|
$sessionId = (string) Str::uuid();
|
||||||
@@ -334,7 +339,9 @@ class BrowserTerminalSessionManager
|
|||||||
|
|
||||||
private function waitForWorkerStartup(string $sessionId, array $metadata): array
|
private function waitForWorkerStartup(string $sessionId, array $metadata): array
|
||||||
{
|
{
|
||||||
$deadline = microtime(true) + 2.5;
|
// The loop returns the moment status leaves "starting" (running OR a
|
||||||
|
// genuine error the worker recorded), so a fast boot still returns fast.
|
||||||
|
$deadline = microtime(true) + self::STARTUP_TIMEOUT_SECONDS;
|
||||||
|
|
||||||
while (microtime(true) < $deadline) {
|
while (microtime(true) < $deadline) {
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
@@ -346,28 +353,11 @@ class BrowserTerminalSessionManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$metadata['status'] = 'failed';
|
// Still starting after the wait: do NOT fabricate a failure — that also
|
||||||
$metadata['exit_code'] = 1;
|
// clobbered workers that were about to come up, which is exactly what made
|
||||||
$metadata['closed_at'] = now()->toIso8601String();
|
// healthy terminals report "failed to start". Return current metadata; the
|
||||||
$metadata['error'] = $this->workerBootstrapError($sessionId);
|
// browser keeps polling and the worker writes a real error itself if boot
|
||||||
$this->writeMetadata($sessionId, $metadata);
|
// ultimately fails.
|
||||||
|
return $this->readWorkerMetadata($sessionId);
|
||||||
return $metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function workerBootstrapError(string $sessionId): string
|
|
||||||
{
|
|
||||||
$output = trim((string) @file_get_contents($this->outputLogPath($sessionId)));
|
|
||||||
|
|
||||||
if ($output !== '') {
|
|
||||||
$lines = preg_split("/\r\n|\n|\r/", $output) ?: [];
|
|
||||||
$tail = trim((string) end($lines));
|
|
||||||
|
|
||||||
if ($tail !== '') {
|
|
||||||
return 'Terminal worker failed to start: '.$tail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'Terminal worker failed to start.';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user