Ostico / PhpOrient

PhpOrient - Official Php driver based on the binary protocol of OrientDB.
Other
68 stars 37 forks source link

Warning: socket_write(): unable to write to socket #57

Open lgoix opened 8 years ago

lgoix commented 8 years ago

Hello

I have a consumer that consume message from RabbitMQ. It means the php file is executed as long the supervisor don't stop it, or it die by itself.

The consumer select and insert into OrientDB. Sometime there is a problem with the socket connection with OrientDB and it will produce many exception:

Warning: socket_write(): unable to write to socket [32]: Broken pipe in \/home\/web1\/myApplication\/application\/vendor\/ostico\/phporient\/src\/PhpOrient\/Protocols\/Binary\/OrientSocket.php line 164"

The PhpOrient class is instanciated in Symfony2 with the service configurator.

I want to know if there is a way to reset the connection ? Is reseting the transport interface is a way to do it ?

$this->orientDBClient->setTransport(null);

Thanks

andreyvk commented 8 years ago

Is your DB located on a remote server?

lgoix commented 8 years ago

@andreyvk : Yes

andreyvk commented 8 years ago

Is your connection to the remote server unstable?

Have you tried catching a SocketException and re-establishing a connection again by instantiating a new PhpOrient client?

andreyvk commented 8 years ago

What I mean is something like this. Of course this code below need more refining:

$client = getPhpOrientClient(); //suppose this is your custom function to instantiate  a connection

//try to do queries. if socket error happens more than 3 times, then quit
$errorCnt = 0;
do {
    try {
          //do your queries here
    }
    catch(SocketException $e) {
        $errorCnt++;
        $client = getPhpOrientClient();
    }
}
while($errorCnt < 3);

if($errorCnt >= 3) {
    //some serious issue happened
}
lgoix commented 8 years ago

I understand

The OrientDb client is injected in the application with all credentials, calling the dbOpen method, before I use it. It seems not possible in Symfony to reset the connexion.

I've looked into the project, I was thinking that if I put the transport = null, it will recreate the transport. (PhpOrient line 174)

I would think to create a decorator to PhpOrient client, and add a method to reconnect. Maybe it could be something valuable for the PhpOrient class ?

andreyvk commented 8 years ago

I see, I completely overlooked that you were using Symphony. Sorry

I found that there's a connect() function in PhpOrient.php. on line 231. Maybe you can try calling that. You dont have to pass any parameters (it will re-use your last username and password it seems).

If that doesnt work then maybe @Ostico can help a little here.

Ostico commented 8 years ago

Hi @lgoix ,

there are some methods to reset/renew the connection for PhpOrient, surely the most simple one is to use it's internal transport layer to manually create a connection on the underlying OrientSocket:

use PhpOrient\PhpOrient;
use PhpOrient\Protocols\Binary\SocketTransport;

$config = [
        "hostname" => "localhost",
        "port"     => 2424,
        "connect"  => [
                "username" => "root",
                "password" => "root"
        ]
];

$client           = new PhpOrient();
$transport = new SocketTransport();
$this->assertInstanceOf( '\PhpOrient\Protocols\Common\AbstractTransport', $transport );
$this->assertInstanceOf( '\PhpOrient\Protocols\Common\TransportInterface', $transport );

$transport->configure( $config );
$client->setTransport( $transport );
$client->execute( 'connect' );

$this->assertNotEquals( -1, $client->getTransport()->getSessionId() );
$this->assertNotEquals( -1, $client->getTransport()->getProtocolVersion() );

So, you can inject a new socket inside your already configured client. You can also retain the preeceding socket object and re-enable the old connection by using:


$old_transport = $client->getTransport( );

$new_transport = new SocketTransport();
$transport->configure( $config );
$client->setTransport( $transport );
lgoix commented 8 years ago

Hi Ostico,

If you don't configure the $new_transport, it will use the config used at the first time ?