Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/Exception/BadApiRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class BadApiRequest extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/ConsumerAlreadyExists.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class ConsumerAlreadyExists extends JetStreamApiException {}
4 changes: 1 addition & 3 deletions src/Exception/ConsumerDoesNotExist.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* @api
*/
final class ConsumerDoesNotExist extends NatsException {}
final class ConsumerDoesNotExist extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/ConsumerNameAlreadyInUse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class ConsumerNameAlreadyInUse extends JetStreamApiException {}
4 changes: 1 addition & 3 deletions src/Exception/ConsumerNotFound.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* @api
*/
final class ConsumerNotFound extends NatsException {}
final class ConsumerNotFound extends JetStreamApiException {}
29 changes: 29 additions & 0 deletions src/Exception/JetStreamApiException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* An error returned by the JetStream API. Errors without a dedicated subclass are thrown as {@see UnknownJetStreamApiError},
* see https://github.com/nats-io/nats-server/blob/main/server/errors.json for the full list of codes.
*
* @api
*/
abstract class JetStreamApiException extends NatsException
{
/**
* @param int $code is the HTTP-like status code (400, 404, 503...), also available through {@see getCode()}
* @param int $errCode is the JetStream specific error code (10059 for stream not found etc.)
*/
public function __construct(
int $code,
public readonly int $errCode,
public readonly string $description,
?\Throwable $previous = null,
) {
parent::__construct($description, $code, $previous);
}
}
10 changes: 10 additions & 0 deletions src/Exception/JetStreamNotEnabled.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class JetStreamNotEnabled extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/JetStreamNotEnabledForAccount.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class JetStreamNotEnabledForAccount extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/MaximumConsumersLimitReached.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class MaximumConsumersLimitReached extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/MaximumStreamsLimitReached.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class MaximumStreamsLimitReached extends JetStreamApiException {}
4 changes: 1 addition & 3 deletions src/Exception/MessageNotFound.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* @api
*/
final class MessageNotFound extends NatsException {}
final class MessageNotFound extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/MessageSizeExceedsMaximum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class MessageSizeExceedsMaximum extends JetStreamApiException {}
4 changes: 1 addition & 3 deletions src/Exception/StreamDoesNotMatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* @api
*/
final class StreamDoesNotMatch extends NatsException {}
final class StreamDoesNotMatch extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/StreamNameAlreadyInUse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class StreamNameAlreadyInUse extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/StreamNameDoesNotMatchSubject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class StreamNameDoesNotMatchSubject extends JetStreamApiException {}
4 changes: 1 addition & 3 deletions src/Exception/StreamNotFound.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* @api
*/
final class StreamNotFound extends NatsException {}
final class StreamNotFound extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/StreamSealed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class StreamSealed extends JetStreamApiException {}
10 changes: 10 additions & 0 deletions src/Exception/StreamStoreFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* @api
*/
final class StreamStoreFailed extends JetStreamApiException {}
12 changes: 12 additions & 0 deletions src/Exception/UnknownJetStreamApiError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Thesis\Nats\Exception;

/**
* A JetStream API error without a dedicated exception, see {@see errCode} to tell it apart.
*
* @api
*/
final class UnknownJetStreamApiError extends JetStreamApiException {}
4 changes: 1 addition & 3 deletions src/Exception/WrongLastMessageId.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* @api
*/
final class WrongLastMessageId extends NatsException {}
final class WrongLastMessageId extends JetStreamApiException {}
4 changes: 1 addition & 3 deletions src/Exception/WrongLastSequence.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

namespace Thesis\Nats\Exception;

use Thesis\Nats\NatsException;

/**
* @api
*/
final class WrongLastSequence extends NatsException {}
final class WrongLastSequence extends JetStreamApiException {}
3 changes: 2 additions & 1 deletion src/Internal/Rpc/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ public function request(
if ($status === Status::NoResponders) {
$deferred->error(new RequestHasNoResponders());
} elseif ($status === Status::NoMessages) {
$deferred->error(new MessageNotFound());
// Direct get answers with a bare 404 status instead of an API error, so mimic the API one.
$deferred->error(new MessageNotFound(Status::NoMessages->value, 10037, 'no message found'));
} else {
$deferred->complete($delivery);
}
Expand Down
64 changes: 46 additions & 18 deletions src/JetStream/Api/Result/Error.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,25 @@

namespace Thesis\Nats\JetStream\Api\Result;

use Thesis\Nats\Exception\BadApiRequest;
use Thesis\Nats\Exception\ConsumerAlreadyExists;
use Thesis\Nats\Exception\ConsumerDoesNotExist;
use Thesis\Nats\Exception\ConsumerNameAlreadyInUse;
use Thesis\Nats\Exception\ConsumerNotFound;
use Thesis\Nats\Exception\JetStreamApiException;
use Thesis\Nats\Exception\JetStreamNotEnabled;
use Thesis\Nats\Exception\JetStreamNotEnabledForAccount;
use Thesis\Nats\Exception\MaximumConsumersLimitReached;
use Thesis\Nats\Exception\MaximumStreamsLimitReached;
use Thesis\Nats\Exception\MessageNotFound;
use Thesis\Nats\Exception\MessageSizeExceedsMaximum;
use Thesis\Nats\Exception\StreamDoesNotMatch;
use Thesis\Nats\Exception\StreamNameAlreadyInUse;
use Thesis\Nats\Exception\StreamNameDoesNotMatchSubject;
use Thesis\Nats\Exception\StreamNotFound;
use Thesis\Nats\Exception\StreamSealed;
use Thesis\Nats\Exception\StreamStoreFailed;
use Thesis\Nats\Exception\UnknownJetStreamApiError;
use Thesis\Nats\Exception\WrongLastMessageId;
use Thesis\Nats\Exception\WrongLastSequence;

Expand All @@ -17,31 +31,45 @@
*/
final readonly class Error
{
private const int STREAM_NOT_FOUND = 10059;
private const int CONSUMER_NOT_FOUND = 10014;
private const int CONSUMER_DOES_NOT_EXISTS = 10149;
private const int STREAM_DOES_NOT_MATCH = 10060;
private const int WRONG_LAST_MESSAGE_ID = 10070;
private const int WRONG_LAST_SEQUENCE = 10071;
private const int MESSAGE_NOT_FOUND = 10037;
/**
* Codes are taken from https://github.com/nats-io/nats-server/blob/main/server/errors.json.
*
* @var array<int, class-string<JetStreamApiException>>
*/
private const array EXCEPTIONS = [
10003 => BadApiRequest::class,
10013 => ConsumerNameAlreadyInUse::class,
10014 => ConsumerNotFound::class,
10026 => MaximumConsumersLimitReached::class,
10027 => MaximumStreamsLimitReached::class,
10037 => MessageNotFound::class,
10039 => JetStreamNotEnabledForAccount::class,
10054 => MessageSizeExceedsMaximum::class,
10056 => StreamNameDoesNotMatchSubject::class,
10058 => StreamNameAlreadyInUse::class,
10059 => StreamNotFound::class,
10060 => StreamDoesNotMatch::class,
10070 => WrongLastMessageId::class,
10071 => WrongLastSequence::class,
10076 => JetStreamNotEnabled::class,
10077 => StreamStoreFailed::class,
10105 => ConsumerAlreadyExists::class, // consumer already exists and is still active
10109 => StreamSealed::class,
10148 => ConsumerAlreadyExists::class,
10149 => ConsumerDoesNotExist::class,
10164 => WrongLastSequence::class, // the same as 10071, but without the sequence in the description
];

public function __construct(
public int $code,
public int $errCode,
public string $description,
) {}

public function exception(): \Exception
public function exception(): JetStreamApiException
{
return match ($this->errCode) {
self::STREAM_NOT_FOUND => new StreamNotFound($this->description),
self::CONSUMER_NOT_FOUND => new ConsumerNotFound($this->description),
self::CONSUMER_DOES_NOT_EXISTS => new ConsumerDoesNotExist($this->description),
self::STREAM_DOES_NOT_MATCH => new StreamDoesNotMatch($this->description),
self::WRONG_LAST_MESSAGE_ID => new WrongLastMessageId($this->description),
self::WRONG_LAST_SEQUENCE => new WrongLastSequence($this->description),
self::MESSAGE_NOT_FOUND => new MessageNotFound($this->description),
default => new \RuntimeException("Nats error: '{$this->description} ({$this->errCode}) received'."),
};
$exception = self::EXCEPTIONS[$this->errCode] ?? UnknownJetStreamApiError::class;

return new $exception($this->code, $this->errCode, $this->description);
}
}
Loading
Loading