Add more specific exceptions

This commit is contained in:
2021-01-24 18:39:26 +03:00
parent 92e8ca0812
commit caa1bab9b5
13 changed files with 98 additions and 29 deletions

View File

@ -5,10 +5,13 @@ declare(strict_types=1);
namespace Nsq; namespace Nsq;
use Composer\InstalledVersions; use Composer\InstalledVersions;
use Nsq\Exception\ConnectionFail;
use Nsq\Exception\UnexpectedResponse;
use PHPinnacle\Buffer\ByteBuffer; use PHPinnacle\Buffer\ByteBuffer;
use Psr\Log\LoggerAwareTrait; use Psr\Log\LoggerAwareTrait;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger; use Psr\Log\NullLogger;
use Socket\Raw\Exception;
use Socket\Raw\Factory; use Socket\Raw\Factory;
use Socket\Raw\Socket; use Socket\Raw\Socket;
use Throwable; use Throwable;
@ -65,7 +68,12 @@ abstract class Connection
public function connect(): void public function connect(): void
{ {
try {
$this->socket = (new Factory())->createClient($this->address); $this->socket = (new Factory())->createClient($this->address);
} catch (Exception $e) {
throw ConnectionFail::fromThrowable($e);
}
$this->send(' V2'); $this->send(' V2');
$body = json_encode($this->features, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT); $body = json_encode($this->features, JSON_THROW_ON_ERROR | JSON_FORCE_OBJECT);
@ -121,12 +129,12 @@ abstract class Connection
try { try {
$socket->write($buffer); $socket->write($buffer);
} catch (Throwable $e) { } catch (Exception $e) {
$this->closed = true; $this->closed = true;
$this->logger->error($e->getMessage(), ['exception' => $e]); $this->logger->error($e->getMessage(), ['exception' => $e]);
throw $e; throw ConnectionFail::fromThrowable($e);
} }
return $this; return $this;
@ -162,7 +170,7 @@ abstract class Connection
$response = $this->receive(0.1); $response = $this->receive(0.1);
if (null === $response) { if (null === $response) {
throw new Exception('Response was expected, but null received.'); throw new UnexpectedResponse('Response was expected, but null received.');
} }
return $response; return $response;
@ -171,7 +179,7 @@ abstract class Connection
private function socket(): Socket private function socket(): Socket
{ {
if ($this->closed) { if ($this->closed) {
throw new Exception('This connection is closed, create new one.'); throw new ConnectionFail('This connection is closed, create new one.');
} }
if (null === $this->socket) { if (null === $this->socket) {

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Nsq;
final class Exception extends \RuntimeException implements NsqException
{
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Nsq\Exception;
use RuntimeException;
use Throwable;
final class ConnectionFail extends RuntimeException implements NsqException
{
public static function fromThrowable(Throwable $throwable): self
{
return new self($throwable->getMessage(), (int) $throwable->getCode(), $throwable);
}
}

View File

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Nsq\Exception;
use Nsq\Message;
use RuntimeException;
final class MessageAlreadyFinished extends RuntimeException implements NsqException
{
public static function finish(Message $message): self
{
return new self('Can\'t finish message as it already finished.');
}
public static function requeue(Message $message): self
{
return new self('Can\'t requeue message as it already finished.');
}
public static function touch(Message $message): self
{
return new self('Can\'t touch message as it already finished.');
}
}

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace Nsq\Exception;
use RuntimeException;
final class NsqError extends RuntimeException implements NsqException
{
}

View File

@ -2,7 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace Nsq; namespace Nsq\Exception;
use Throwable; use Throwable;

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
namespace Nsq\Exception;
use RuntimeException;
final class UnexpectedResponse extends RuntimeException implements NsqException
{
}

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Nsq; namespace Nsq;
use Nsq\Exception\MessageAlreadyFinished;
final class Message final class Message
{ {
/** /**
@ -48,7 +50,7 @@ final class Message
public function finish(): void public function finish(): void
{ {
if ($this->finished) { if ($this->finished) {
throw new Exception('Can\'t finish message as it already finished.'); throw MessageAlreadyFinished::finish($this);
} }
$this->consumer->fin($this->id); $this->consumer->fin($this->id);
@ -58,7 +60,7 @@ final class Message
public function requeue(int $timeout): void public function requeue(int $timeout): void
{ {
if ($this->finished) { if ($this->finished) {
throw new Exception('Can\'t requeue message as it already finished.'); throw MessageAlreadyFinished::requeue($this);
} }
$this->consumer->req($this->id, $timeout); $this->consumer->req($this->id, $timeout);
@ -68,7 +70,7 @@ final class Message
public function touch(): void public function touch(): void
{ {
if ($this->finished) { if ($this->finished) {
throw new Exception('Can\'t touch message as it already finished.'); throw MessageAlreadyFinished::touch($this);
} }
$this->consumer->touch($this->id); $this->consumer->touch($this->id);

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Nsq; namespace Nsq;
use Nsq\Exception\NsqError;
use Nsq\Exception\UnexpectedResponse;
use PHPinnacle\Buffer\ByteBuffer; use PHPinnacle\Buffer\ByteBuffer;
final class Response final class Response
@ -27,15 +29,15 @@ final class Response
public function okOrFail(): void public function okOrFail(): void
{ {
if (self::TYPE_ERROR === $this->type) { if (self::TYPE_ERROR === $this->type) {
throw new Exception($this->buffer->bytes()); throw new NsqError($this->buffer->bytes());
} }
if (self::TYPE_RESPONSE !== $this->type) { if (self::TYPE_RESPONSE !== $this->type) {
throw new Exception(sprintf('"%s" type expected, but "%s" received.', self::TYPE_RESPONSE, $this->type)); throw new UnexpectedResponse(sprintf('"%s" type expected, but "%s" received.', self::TYPE_RESPONSE, $this->type));
} }
if (self::OK !== $this->buffer->bytes()) { if (self::OK !== $this->buffer->bytes()) {
throw new Exception(sprintf('OK response expected, but "%s" received.', $this->buffer->bytes())); throw new UnexpectedResponse(sprintf('OK response expected, but "%s" received.', $this->buffer->bytes()));
} }
} }
@ -47,7 +49,7 @@ final class Response
public function toMessage(Consumer $reader): Message public function toMessage(Consumer $reader): Message
{ {
if (self::TYPE_MESSAGE !== $this->type) { if (self::TYPE_MESSAGE !== $this->type) {
throw new Exception(sprintf('Expecting "%s" type, but NSQ return: "%s"', self::TYPE_MESSAGE, $this->type)); throw new UnexpectedResponse(sprintf('Expecting "%s" type, but NSQ return: "%s"', self::TYPE_MESSAGE, $this->type));
} }
$buffer = new ByteBuffer($this->buffer->bytes()); $buffer = new ByteBuffer($this->buffer->bytes());

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Nsq; namespace Nsq;
use Generator; use Generator;
use InvalidArgumentException;
use function get_debug_type; use function get_debug_type;
use function sprintf; use function sprintf;
@ -41,7 +42,7 @@ final class Subscriber
$newTimeout = yield null; $newTimeout = yield null;
if (!\is_float($newTimeout)) { if (!\is_float($newTimeout)) {
throw new Exception(sprintf('Timeout must be float, "%s" given.', get_debug_type($newTimeout))); throw new InvalidArgumentException(sprintf('Timeout must be float, "%s" given.', get_debug_type($newTimeout)));
} }
$timeout = $newTimeout; $timeout = $newTimeout;

View File

@ -3,7 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
use Nsq\Consumer; use Nsq\Consumer;
use Nsq\Exception; use Nsq\Exception\MessageAlreadyFinished;
use Nsq\Message; use Nsq\Message;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -20,7 +20,7 @@ final class MessageTest extends TestCase
self::assertTrue($message->isFinished()); self::assertTrue($message->isFinished());
$this->expectException(Exception::class); $this->expectException(MessageAlreadyFinished::class);
$this->expectExceptionMessage('Can\'t finish message as it already finished.'); $this->expectExceptionMessage('Can\'t finish message as it already finished.');
$message->finish(); $message->finish();
@ -37,7 +37,7 @@ final class MessageTest extends TestCase
self::assertTrue($message->isFinished()); self::assertTrue($message->isFinished());
$this->expectException(Exception::class); $this->expectException(MessageAlreadyFinished::class);
$this->expectExceptionMessage('Can\'t requeue message as it already finished.'); $this->expectExceptionMessage('Can\'t requeue message as it already finished.');
$message->requeue(5); $message->requeue(5);
@ -52,7 +52,7 @@ final class MessageTest extends TestCase
$message->finish(); $message->finish();
$this->expectException(Exception::class); $this->expectException(MessageAlreadyFinished::class);
$this->expectExceptionMessage('Can\'t touch message as it already finished.'); $this->expectExceptionMessage('Can\'t touch message as it already finished.');
$message->touch(); $message->touch();

View File

@ -2,6 +2,7 @@
declare(strict_types=1); declare(strict_types=1);
use Nsq\Exception\NsqError;
use Nsq\Producer; use Nsq\Producer;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -12,7 +13,7 @@ final class ProducerTest extends TestCase
*/ */
public function testPubFail(string $topic, string $body, string $exceptionMessage): void public function testPubFail(string $topic, string $body, string $exceptionMessage): void
{ {
$this->expectException(Exception::class); $this->expectException(NsqError::class);
$this->expectExceptionMessage($exceptionMessage); $this->expectExceptionMessage($exceptionMessage);
$producer = new Producer('tcp://localhost:4150'); $producer = new Producer('tcp://localhost:4150');

View File

@ -34,7 +34,7 @@ final class SubscriberTest extends TestCase
public function testInvalidChangeInterval(): void public function testInvalidChangeInterval(): void
{ {
$this->expectException(\Nsq\Exception::class); $this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Timeout must be float, "string" given.'); $this->expectExceptionMessage('Timeout must be float, "string" given.');
$generator = $this->subscriber->subscribe(__FUNCTION__, __FUNCTION__); $generator = $this->subscriber->subscribe(__FUNCTION__, __FUNCTION__);