From 3d28ca3d6ec6c484aa35ee720a677195e4a0c430 Mon Sep 17 00:00:00 2001 From: Waldemar Quevedo Date: Fri, 12 Aug 2022 16:09:07 -0700 Subject: [PATCH] js: Add JetStreamAPIError with more api response details Signed-off-by: Waldemar Quevedo --- jsm.go | 40 ++++++++++++++++++++++++++++++++++++++-- nats.go | 6 +++++- test/js_test.go | 11 ++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/jsm.go b/jsm.go index b2cfe6e17..0a2073c5c 100644 --- a/jsm.go +++ b/jsm.go @@ -161,6 +161,37 @@ type APIError struct { Description string `json:"description,omitempty"` } +// JetStreamAPIError is an error result from making a request to the +// JetStream API. +type JetStreamAPIError interface { + Code() int + ErrorCode() int + Description() string + Error() string +} + +type jsAPIError struct { + code int + errorCode int + description string +} + +func (err *jsAPIError) Code() int { + return err.code +} + +func (err *jsAPIError) ErrorCode() int { + return err.errorCode +} + +func (err *jsAPIError) Description() string { + return err.description +} + +func (err *jsAPIError) Error() string { + return "nats: jetstream not enabled" +} + // apiResponse is a standard response from the JetStream JSON API type apiResponse struct { Type string `json:"type"` @@ -245,10 +276,15 @@ func (js *js) AccountInfo(opts ...JSOpt) (*AccountInfo, error) { } if info.Error != nil { var err error - if strings.Contains(info.Error.Description, "not enabled for") { + // Check based on error code instead of description match. + if info.Error.ErrorCode == ErrJetStreamNotEnabled.ErrorCode() { err = ErrJetStreamNotEnabled } else { - err = errors.New(info.Error.Description) + err = &jsAPIError{ + code: info.Error.Code, + errorCode: info.Error.ErrorCode, + description: info.Error.Description, + } } return nil, err } diff --git a/nats.go b/nats.go index ec28bb7b6..41b161b02 100644 --- a/nats.go +++ b/nats.go @@ -139,7 +139,6 @@ var ( ErrNoResponders = errors.New("nats: no responders available for request") ErrNoContextOrTimeout = errors.New("nats: no context or timeout given") ErrPullModeNotAllowed = errors.New("nats: pull based not supported") - ErrJetStreamNotEnabled = errors.New("nats: jetstream not enabled") ErrJetStreamBadPre = errors.New("nats: jetstream api prefix not valid") ErrNoStreamResponse = errors.New("nats: no response from stream") ErrNotJSMessage = errors.New("nats: not a jetstream message") @@ -172,6 +171,11 @@ var ( ErrConnectionNotTLS = errors.New("nats: connection is not tls") ) +var ( + // ErrJetStreamNotEnabled is an error returned when JetStream is not enabled for an account. + ErrJetStreamNotEnabled JetStreamAPIError = &jsAPIError{errorCode: 10039} +) + func init() { rand.Seed(time.Now().UnixNano()) } diff --git a/test/js_test.go b/test/js_test.go index f644d64a3..2b6fd4a3b 100644 --- a/test/js_test.go +++ b/test/js_test.go @@ -87,9 +87,18 @@ func TestJetStreamNotAccountEnabled(t *testing.T) { nc, js := jsClient(t, s) defer nc.Close() - if _, err := js.AccountInfo(); err != nats.ErrJetStreamNotEnabled { + _, err := js.AccountInfo() + if err != nats.ErrJetStreamNotEnabled { t.Fatalf("Did not get the proper error, got %v", err) } + jserr, ok := err.(nats.JetStreamAPIError) + if !ok { + t.Fatal("Expected a JetStreamAPIError") + } + expected := 10039 + if jserr.ErrorCode() != expected { + t.Fatalf("Expected: %v, got: %v", expected, jserr.ErrorCode()) + } } func TestJetStreamPublish(t *testing.T) {