diff --git a/docs/client/connecting.md b/docs/client/connecting.md index 14f6ea7a..c4e5a15a 100644 --- a/docs/client/connecting.md +++ b/docs/client/connecting.md @@ -214,6 +214,8 @@ speaks revision `2026-07-28`, the connection is ready. If it doesn't, the client `initialize` handshake and offers `2025-11-25`, or the revision set with `setFallbackProtocolVersion()`. A server process that exits fails the connection instead. +Calling `connect()` again on the same client closes its current transport before opening the new one. + With `setFallbackProtocolVersion(null)`, `connect()` fails instead. See [How the client settles on an era](../protocol-versions.md#how-the-client-settles-on-an-era). diff --git a/src/Client.php b/src/Client.php index f70fdeee..993511de 100644 --- a/src/Client.php +++ b/src/Client.php @@ -92,6 +92,8 @@ public static function builder(): Builder */ public function connect(TransportInterface $transport): void { + $this->disconnect(); + $this->transport = $transport; $this->protocol->connect($transport, $this->config); diff --git a/tests/Unit/Client/ClientTest.php b/tests/Unit/Client/ClientTest.php index 29d23ffe..3c6da9a2 100644 --- a/tests/Unit/Client/ClientTest.php +++ b/tests/Unit/Client/ClientTest.php @@ -21,6 +21,29 @@ final class ClientTest extends TestCase { + public function testReconnectClosesPreviousTransport(): void + { + $client = Client::builder()->build(); + $firstTransport = $this->createMock(TransportInterface::class); + $firstTransport->expects($this->once())->method('close'); + $firstTransport->method('setState')->willReturnCallback(static function (ClientStateInterface $state): void { + $state->setInitialized(true); + }); + + $secondTransport = $this->createMock(TransportInterface::class); + $secondTransport->expects($this->once())->method('close'); + $secondTransport->method('setState')->willReturnCallback(static function (ClientStateInterface $state): void { + $state->setInitialized(true); + }); + + $client->connect($firstTransport); + $client->connect($secondTransport); + + $this->assertTrue($client->isConnected()); + + $client->disconnect(); + } + public function testSendRootsListChangedSendsNotificationWhenCapabilityDeclared(): void { $sent = [];