refactor(ssh): enhance error handling in SSH command execution and improve connection validation logging
This commit is contained in:
		| @@ -1082,6 +1082,7 @@ $schema://$host { | ||||
| 
 | ||||
|     public function validateConnection(bool $justCheckingNewKey = false) | ||||
|     { | ||||
|         ray('validateConnection', $this->id); | ||||
|         $this->disableSshMux(); | ||||
| 
 | ||||
|         if ($this->skipServer()) { | ||||
|   | ||||
| @@ -88,10 +88,6 @@ trait ExecuteRemoteCommand | ||||
|     private function executeCommandWithProcess($command, $hidden, $customType, $append, $ignore_errors) | ||||
|     { | ||||
|         $remote_command = SshMultiplexingHelper::generateSshCommand($this->server, $command); | ||||
|         // Randomly fail the command with a key exchange error for testing
 | ||||
|         // if (random_int(1, 20) === 1) { // 5% chance to fail
 | ||||
|         //     throw new \RuntimeException('SSH key exchange failed: kex_exchange_identification: read: Connection reset by peer');
 | ||||
|         // }
 | ||||
|         $process = Process::timeout(3600)->idleTimeout(3600)->start($remote_command, function (string $type, string $output) use ($command, $hidden, $customType, $append) { | ||||
|             $output = str($output)->trim(); | ||||
|             if ($output->startsWith('╔')) { | ||||
|   | ||||
| @@ -57,9 +57,9 @@ trait SshRetryable | ||||
|      */ | ||||
|     protected function calculateRetryDelay(int $attempt): int | ||||
|     { | ||||
|         $baseDelay = config('constants.ssh.retry_base_delay', 2); | ||||
|         $maxDelay = config('constants.ssh.retry_max_delay', 30); | ||||
|         $multiplier = config('constants.ssh.retry_multiplier', 2); | ||||
|         $baseDelay = config('constants.ssh.retry_base_delay'); | ||||
|         $maxDelay = config('constants.ssh.retry_max_delay'); | ||||
|         $multiplier = config('constants.ssh.retry_multiplier'); | ||||
| 
 | ||||
|         $delay = min($baseDelay * pow($multiplier, $attempt), $maxDelay); | ||||
| 
 | ||||
| @@ -76,23 +76,17 @@ trait SshRetryable | ||||
|      */ | ||||
|     protected function executeWithSshRetry(callable $callback, array $context = [], bool $throwError = true) | ||||
|     { | ||||
|         $maxRetries = config('constants.ssh.max_retries', 3); | ||||
|         $maxRetries = config('constants.ssh.max_retries'); | ||||
|         $lastError = null; | ||||
|         $lastErrorMessage = ''; | ||||
|         // Randomly fail the command with a key exchange error for testing
 | ||||
|         // if (random_int(1, 10) === 1) { // 10% chance to fail
 | ||||
|         //     ray('SSH key exchange failed: kex_exchange_identification: read: Connection reset by peer');
 | ||||
|         //     throw new \RuntimeException('SSH key exchange failed: kex_exchange_identification: read: Connection reset by peer');
 | ||||
|         // }
 | ||||
|         for ($attempt = 0; $attempt < $maxRetries; $attempt++) { | ||||
|             try { | ||||
|                 // Execute the callback
 | ||||
|                 $result = $callback(); | ||||
| 
 | ||||
|                 // If we get here, it succeeded
 | ||||
|                 if ($attempt > 0) { | ||||
|                     Log::info('SSH operation succeeded after retry', array_merge($context, [ | ||||
|                         'attempt' => $attempt + 1, | ||||
|                     ])); | ||||
|                 } | ||||
| 
 | ||||
|                 return $result; | ||||
| 
 | ||||
|                 return $callback(); | ||||
|             } catch (\Throwable $e) { | ||||
|                 $lastError = $e; | ||||
|                 $lastErrorMessage = $e->getMessage(); | ||||
| @@ -125,6 +119,12 @@ trait SshRetryable | ||||
|         } | ||||
| 
 | ||||
|         if ($throwError && $lastError) { | ||||
|             // If the error message is empty, provide a more meaningful one
 | ||||
|             if (empty($lastErrorMessage) || trim($lastErrorMessage) === '') { | ||||
|                 $contextInfo = isset($context['server']) ? " to server {$context['server']}" : ''; | ||||
|                 $attemptInfo = $attempt > 1 ? " after {$attempt} attempts" : ''; | ||||
|                 throw new \RuntimeException("SSH connection failed{$contextInfo}{$attemptInfo}", $lastError->getCode()); | ||||
|             } | ||||
|             throw $lastError; | ||||
|         } | ||||
| 
 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Andras Bacsai
					Andras Bacsai