Files
nats.go/jetstream/errors.go
Piotr Piotrowski e7ab93ecb8 Add ordered consumer, FetchBytes and Next, rework options
Signed-off-by: Piotr Piotrowski <piotr@synadia.com>
2023-05-23 12:03:02 +02:00

209 lines
8.8 KiB
Go

// Copyright 2020-2023 The NATS Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package jetstream
import (
"errors"
"fmt"
)
type (
// JetStreamError is an error result that happens when using JetStream.
// In case of client-side error, [APIError] returns nil
JetStreamError interface {
APIError() *APIError
error
}
jsError struct {
apiErr *APIError
message string
}
// APIError is included in all API responses if there was an error.
APIError struct {
Code int `json:"code"`
ErrorCode ErrorCode `json:"err_code"`
Description string `json:"description,omitempty"`
}
// ErrorCode represents error_code returned in response from JetStream API
ErrorCode uint16
)
const (
JSErrCodeJetStreamNotEnabledForAccount ErrorCode = 10039
JSErrCodeJetStreamNotEnabled ErrorCode = 10076
JSErrCodeStreamNotFound ErrorCode = 10059
JSErrCodeStreamNameInUse ErrorCode = 10058
JSErrCodeConsumerCreate ErrorCode = 10012
JSErrCodeConsumerNotFound ErrorCode = 10014
JSErrCodeConsumerNameExists ErrorCode = 10013
JSErrCodeConsumerAlreadyExists ErrorCode = 10105
JSErrCodeMessageNotFound ErrorCode = 10037
JSErrCodeBadRequest ErrorCode = 10003
)
var (
// API errors
// ErrJetStreamNotEnabled is an error returned when JetStream is not enabled for an account.
ErrJetStreamNotEnabled JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeJetStreamNotEnabled, Description: "jetstream not enabled", Code: 503}}
// ErrJetStreamNotEnabledForAccount is an error returned when JetStream is not enabled for an account.
ErrJetStreamNotEnabledForAccount JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeJetStreamNotEnabledForAccount, Description: "jetstream not enabled for account", Code: 503}}
// ErrStreamNotFound is an error returned when stream with given name does not exist.
ErrStreamNotFound JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeStreamNotFound, Description: "stream not found", Code: 404}}
// ErrStreamNameAlreadyInUse is returned when a stream with given name already exists and has a different configuration
ErrStreamNameAlreadyInUse JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeStreamNameInUse, Description: "stream name already in use", Code: 400}}
// ErrConsumerNotFound is an error returned when consumer with given name does not exist.
ErrConsumerNotFound JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeConsumerNotFound, Description: "consumer not found", Code: 404}}
// ErrMsgNotFound is returned when message with provided sequence number does npt exist.
ErrMsgNotFound JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeMessageNotFound, Description: "message not found", Code: 404}}
// ErrBadRequest is returned when invalid request is sent to JetStream API.
ErrBadRequest JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeBadRequest, Description: "bad request", Code: 400}}
// ErrConsumerCreate is returned when nats-server reports error when creating consumer (e.g. illegal update).
ErrConsumerCreate JetStreamError = &jsError{apiErr: &APIError{ErrorCode: JSErrCodeConsumerCreate, Description: "could not create consumer", Code: 500}}
// Client errors
// ErrConsumerNotFound is an error returned when consumer with given name does not exist.
ErrConsumerNameAlreadyInUse JetStreamError = &jsError{message: "consumer name already in use"}
// ErrInvalidJSAck is returned when JetStream ack from message publish is invalid.
ErrInvalidJSAck JetStreamError = &jsError{message: "invalid jetstream publish response"}
// ErrStreamNameRequired is returned when the provided stream name is empty.
ErrStreamNameRequired JetStreamError = &jsError{message: "stream name is required"}
// ErrConsumerNameRequired is returned when the provided consumer durable name is empty,
ErrConsumerNameRequired JetStreamError = &jsError{message: "consumer name is required"}
// ErrMsgAlreadyAckd is returned when attempting to acknowledge message more than once.
ErrMsgAlreadyAckd JetStreamError = &jsError{message: "message was already acknowledged"}
// ErrNoStreamResponse is returned when there is no response from stream (e.g. no responders error).
ErrNoStreamResponse JetStreamError = &jsError{message: "no response from stream"}
// ErrNotJSMessage is returned when attempting to get metadata from non JetStream message .
ErrNotJSMessage JetStreamError = &jsError{message: "not a jetstream message"}
// ErrInvalidStreamName is returned when the provided stream name is invalid (contains '.').
ErrInvalidStreamName JetStreamError = &jsError{message: "invalid stream name"}
// ErrInvalidConsumerName is returned when the provided consumer name is invalid (contains '.').
ErrInvalidConsumerName JetStreamError = &jsError{message: "invalid consumer name"}
// ErrNoMessages is returned when no messages are currently available for a consumer.
ErrNoMessages = &jsError{message: "no messages"}
// ErrMaxBytesExceeded is returned when a message would exceed MaxBytes set on a pull request.
ErrMaxBytesExceeded = &jsError{message: "message size exceeds max bytes"}
// ErrConsumerDeleted is returned when attempting to send pull request to a consumer which does not exist
ErrConsumerDeleted JetStreamError = &jsError{message: "consumer deleted"}
// ErrConsumerLeadershipChanged is returned when pending requests are no longer valid after leadership has changed
ErrConsumerLeadershipChanged JetStreamError = &jsError{message: "leadership change"}
// ErrHandlerRequired is returned when no handler func is provided in Stream()
ErrHandlerRequired = &jsError{message: "handler cannot be empty"}
// ErrEndOfData is returned when iterating over paged API from JetStream reaches end of data
ErrEndOfData = errors.New("nats: end of data reached")
// ErrNoHeartbeat is received when no message is received in IdleHeartbeat time (if set)
ErrNoHeartbeat = &jsError{message: "no heartbeat received"}
// ErrConsumerHasActiveSubscription is returned when a consumer is already subscribed to a stream
ErrConsumerHasActiveSubscription = &jsError{message: "consumer has active subscription"}
// ErrMsgNotBound is returned when given message is not bound to any subscription
ErrMsgNotBound = &jsError{message: "message is not bound to subscription/connection"}
// ErrMsgNoReply is returned when attempting to reply to a message without a reply subject
ErrMsgNoReply = &jsError{message: "message does not have a reply"}
// ErrMsgDeleteUnsuccessful is returned when an attempt to delete a message is unsuccessful
ErrMsgDeleteUnsuccessful = &jsError{message: "message deletion unsuccessful"}
// ErrAsyncPublishReplySubjectSet is returned when reply subject is set on async message publish
ErrAsyncPublishReplySubjectSet = &jsError{message: "reply subject should be empty"}
// ErrTooManyStalledMsgs is returned when too many outstanding async messages are waiting for ack
ErrTooManyStalledMsgs = &jsError{message: "stalled with too many outstanding async published messages"}
// ErrInvalidOption is returned when there is a collision between options
ErrInvalidOption = &jsError{message: "invalid jetstream option"}
// ErrMsgIteratorClosed is returned when attempting to get message from a closed iterator
ErrMsgIteratorClosed = &jsError{message: "messages iterator closed"}
ErrOrderedConsumerReset = &jsError{message: "recreating ordered consumer"}
ErrOrderedSequenceMismatch = &jsError{message: "sequence mismatch"}
)
// Error prints the JetStream API error code and description
func (e *APIError) Error() string {
return fmt.Sprintf("nats: API error: code=%d err_code=%d description=%s", e.Code, e.ErrorCode, e.Description)
}
// APIError implements the JetStreamError interface.
func (e *APIError) APIError() *APIError {
return e
}
// Is matches against an APIError.
func (e *APIError) Is(err error) bool {
if e == nil {
return false
}
// Extract internal APIError to match against.
var aerr *APIError
ok := errors.As(err, &aerr)
if !ok {
return ok
}
return e.ErrorCode == aerr.ErrorCode
}
func (err *jsError) APIError() *APIError {
return err.apiErr
}
func (err *jsError) Error() string {
if err.apiErr != nil && err.apiErr.Description != "" {
return err.apiErr.Error()
}
return fmt.Sprintf("nats: %s", err.message)
}
func (err *jsError) Unwrap() error {
// Allow matching to embedded APIError in case there is one.
if err.apiErr == nil {
return nil
}
return err.apiErr
}