Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failing connections cause exceptions thrown outside of Promise #74

Open
one-horned-flying opened this issue Oct 18, 2018 · 2 comments
Open

Comments

@one-horned-flying
Copy link

I'm getting this error when connecting to RabbitMQ
PHP Fatal error: Uncaught Bunny\Exception\ClientException: Broken pipe or closed connection. in /.../vendor/bunny/bunny/src/Bunny/AbstractClient.php:289

This happens because when I connect, I'm connecting with specific credentials and RabbitMQ is denying the connection. When this happens the stream is closed so we get an end of file:

if (@feof($this->stream)) {
throw new ClientException("Broken pipe or closed connection.");
}

I have multiple connections opened by different users, so I need to handle this gracefully. This is the extension I've written to handle the problem.

I'm using https://packagist.org/packages/evenement/evenement as well.

Hope this helps.

<?php
declare(strict_types=1);

namespace MyClient;

use Bunny\Async\Client;
use Evenement\EventEmitterInterface;
use Evenement\EventEmitterTrait;
use React\Promise;

class BunnyAsyncClient extends Client implements EventEmitterInterface
{
    use EventEmitterTrait;

    /**
     *
     */
    public function onDataAvailable()
    {
        try {
            parent::onDataAvailable();
        } catch (\Throwable $e) {
            $this->eventLoop->removeReadStream($this->getStream());
            $this->eventLoop->futureTick(function () use ($e) {
                $this->emit('error', [$e, $this]);
            });
        }
    }

    /**
     * @return Promise\PromiseInterface
     */
    public function connect()
    {
        $deferred = new Promise\Deferred();

        $errBack = function (\Throwable $e) use ($deferred, &$errBack) {
            $this->removeListener('error', $errBack);
            $deferred->reject($e);
        };

        $this->on('error', $errBack);

        parent::connect()->then(
            function () use ($deferred) {
                return $deferred->resolve($this);
            },
            function (\Throwable $e) use ($deferred) {
                // needed in case rejected not by the errBack
                $deferred->reject($e);
            }
        )->always(function () use ($errBack) {
            $this->removeListener('error', $errBack);
        });

        return $deferred->promise();
    }
}
@hsldymq
Copy link

hsldymq commented Mar 27, 2019

I noticed when this exception caused,call $client->isConnected() gave you the wrong result which is true while I was expecting false.

I'm wondering if it can be fixed by just write following code in that if condition:

    if (@feof($this->stream)) { 
        $this->eventLoop->removeReadStream($this->getStream());
        $this->state = ClientStateEnum::ERROR;
        throw new ClientException("Broken pipe or closed connection."); 
    } 

@fritz-gerneth
Copy link
Contributor

A similar issue occurs when disconnecting a client that has not opened a channel yet.

======================================================================
   The application has thrown an exception!
======================================================================
 Bunny\Exception\ClientException
 Connection closed by server: CHANNEL_ERROR - expected 'channel.open'
----------------------------------------------------------------------
/var/www/vendor/bunny/bunny/src/Bunny/AbstractClient.php:448
#0 /var/www/vendor/bunny/bunny/src/Bunny/Async/Client.php(306): Bunny\AbstractClient->onFrameReceived(Object(Bunny\Protocol\MethodConnectionCloseFrame))
#1 /var/www/vendor/react/event-loop/src/StreamSelectLoop.php(245): Bunny\Async\Client->onDataAvailable(Resource id #2073)
#2 /var/www/vendor/react/event-loop/src/StreamSelectLoop.php(212): React\EventLoop\StreamSelectLoop->waitForStreamActivity(NULL)
#3 /var/www/Common/src/Adapter/Cli/CliController.php(88): React\EventLoop\StreamSelectLoop->run()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants