fix: more graceful behavior on connection closure/failure
1 files changed, 24 insertions(+), 2 deletions(-)

M src/Connection.php
M src/Connection.php +24 -2
@@ 14,6 14,9 @@ class Connection
     protected string $_lastLine;
     protected Set $watching;
 
+    /**
+     * @throws Exceptions\ConnectionClosed on failure to connect
+     */
     public function __construct(
         string $host = '::1',
         int $port = 11300,

          
@@ 29,7 32,7 @@ class Connection
             $timeout,
         );
         if ($this->connection === false) {
-            throw new \RuntimeException("Failed to connect: {$errstr}", $errno);
+            throw new Exceptions\ConnectionClosed("Failed to connect: {$errstr}", $errno);
         }
 
         stream_set_timeout($this->connection, $timeout);

          
@@ 44,11 47,23 @@ class Connection
 
     public function __destruct()
     {
-        fclose($this->connection);
+        $this->close();
+    }
+
+    public function close(): void
+    {
+        if ($this->connection !== null) {
+            fclose($this->connection);
+            $this->connection = null;
+        }
     }
 
     protected function _write(string ...$args): void
     {
+        if ($this->connection === null) {
+            throw new Exceptions\ConnectionClosed();
+        }
+
         $line = implode(" ", $args);
         fwrite($this->connection, "{$line}\r\n");
     }

          
@@ 66,10 81,15 @@ class Connection
      */
     protected function _read(int $timeout = self::DEFAULT_CONNECTION_TIMEOUT): array
     {
+        if ($this->connection === null) {
+            throw new Exceptions\ConnectionClosed();
+        }
+
         stream_set_timeout($this->connection, $timeout);
         $line = fgets($this->connection);
         if ($line === false) {
             if (feof($this->connection)) {
+                $this->close();
                 throw new Exceptions\ConnectionClosed();
             } else {
                 throw new Exceptions\ConnectionTimeout();

          
@@ 133,6 153,7 @@ class Connection
 
     /**
      * @throws Exceptions\Buried
+     * @throws Exceptions\ConnectionClosed
      * @throws Exceptions\Draining
      * @throws Exceptions\JobTooBig
      * @throws Exceptions\ProtocolError

          
@@ 151,6 172,7 @@ class Connection
             (string) $timeToRun,
             (string) strlen($body),
         );
+        // Assume that $this->connection !== null if the above doesn't fail.
         fwrite($this->connection, $body);
         fwrite($this->connection, "\r\n");
         fflush($this->connection);