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;
|
||||
|
||||
// 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
|
||||
{
|
||||
$sessionId = (string) Str::uuid();
|
||||
@@ -334,7 +339,9 @@ class BrowserTerminalSessionManager
|
||||
|
||||
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) {
|
||||
usleep(100000);
|
||||
@@ -346,28 +353,11 @@ class BrowserTerminalSessionManager
|
||||
}
|
||||
}
|
||||
|
||||
$metadata['status'] = 'failed';
|
||||
$metadata['exit_code'] = 1;
|
||||
$metadata['closed_at'] = now()->toIso8601String();
|
||||
$metadata['error'] = $this->workerBootstrapError($sessionId);
|
||||
$this->writeMetadata($sessionId, $metadata);
|
||||
|
||||
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.';
|
||||
// Still starting after the wait: do NOT fabricate a failure — that also
|
||||
// clobbered workers that were about to come up, which is exactly what made
|
||||
// healthy terminals report "failed to start". Return current metadata; the
|
||||
// browser keeps polling and the worker writes a real error itself if boot
|
||||
// ultimately fails.
|
||||
return $this->readWorkerMetadata($sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user