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

richer api errors proposal #2168

Merged
merged 3 commits into from May 26, 2021
Merged

Conversation

ripienaar
Copy link
Contributor

@ripienaar ripienaar commented Apr 30, 2021

This creates richer errors in response to #1811 and numerous other requests.

The main idea is that when a 404 is raised in response to accessing a consumer we now include a unique identifier that would allow callers to distinguish between stream not found, consumer not found, no message found and other errors that might raise 404.

One could argue that users might parse the Description like stream not found however this makes our human friendly descriptions part of the API promises and we can never improve, bug fix or translate those strings. For example today there is an unfortunate mix of jetstream and JetStream in use in error descriptions and we would want the ability to improve errors without breaking peoples code.

Additionally I propose capturing help and urls in the code - not in actual API responses - to facilitate a single place where we maintain these errors and then adding tooling like nats error JS1 that will produce the error text, help, additional information and links to documentation that would help users resolve those errors. So the slow ApiErrorByKind would not be used in anything but the CLI to resolve these things, though even thats optional as the ApiErrors is exported.

Signed-off-by: R.I.Pienaar rip@devco.net

/cc @nats-io/core

@ripienaar ripienaar marked this pull request as draft April 30, 2021 13:10
Copy link
Member

@kozlovic kozlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I approve of this idea. Relying on error text is "error prone" :-)

server/jetstream_api.go Outdated Show resolved Hide resolved
@ripienaar
Copy link
Contributor Author

@derekcollison I want to spend some time on this during this week, let me know what you think of the approach before I dive in on a wrong track, thanks!

@derekcollison
Copy link
Member

Probably deserves a meeting between a few folks.

@ripienaar
Copy link
Contributor Author

I added @matthiashanel and @aricart to reviewers for context, will have a call with all reviewers I guess.

@derekcollison
Copy link
Member

Add me onto the list as well if you can.

@aricart
Copy link
Member

aricart commented May 4, 2021

I had looked at the PR before, and I agree that having a code that can be pointed at documentation can provide a richer experience to diagnose problems. The standard string that it represents is useful, but more so I think is the case where these values make it to a server log. Having documentation where the lookup can be performed is very useful.

@ripienaar ripienaar force-pushed the richer_api_errors branch 5 times, most recently from 22c4a1b to 6382bee Compare May 10, 2021 10:57
@ripienaar
Copy link
Contributor Author

@kozlovic @derekcollison this has grown quite big now - and I think we can go deeper by making some of the utility functions also return these errors to better detect causes but for now I am fairly happy with this.

Would you mind taking a peek through and let me know, I'll highlight a few specific areas via comments.

server/jetstream_errors.go Outdated Show resolved Hide resolved
server/jetstream_errors.go Outdated Show resolved Hide resolved
server/jetstream_errors.go Outdated Show resolved Hide resolved
server/jetstream_test.go Outdated Show resolved Hide resolved
server/jetstream_api.go Show resolved Hide resolved
server/jetstream_errors.go Outdated Show resolved Hide resolved
server/mqtt.go Outdated Show resolved Hide resolved
@ripienaar ripienaar force-pushed the richer_api_errors branch 3 times, most recently from fc07299 to 4465601 Compare May 12, 2021 09:43
@ripienaar ripienaar force-pushed the richer_api_errors branch 6 times, most recently from fd2181d to 66c0e1e Compare May 14, 2021 11:59
@ripienaar ripienaar marked this pull request as ready for review May 14, 2021 12:00
@ripienaar
Copy link
Contributor Author

@kozlovic think I am good on this one, I updated MQTT code considering new errors and also added a ADR for how it works and how to maintain it (though I think that needs expanding in time).

for now keen to get this in so we can stop the rebasing pain :)

Copy link
Member

@kozlovic kozlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, except not sure what to do with exported JS errors: removing them may break some apps (but unlikely).


// ErrNoTransforms signals no subject transforms are available to map this subject.
ErrNoTransforms = errors.New("no matching transforms available")

// ErrJetStreamNotEnabled is returned when JetStream is not enabled.
ErrJetStreamNotEnabled = errors.New("jetstream not enabled")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we discussed once, should we leave those but with a doc section that says that they are "deprecated"? I am thinking of use-case where users embed the NATS Server. I assume that internally they will no longer be used or updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah its a difficult one, we could say ErrJetStreamNotEnabled = ApiErrors[JSWhatever] but I am not 100% sure that will solve the problem in all cases tbh

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually it should solve it for these - as they are essentially static, the ones where it wont solve it are the ones where we put in a different description via printf. So it might be fine

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should leave, no harm imo..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the point was that we would not use them anymore, but we may want to keep them as to possibly not break users that embed NATS Server and somehow were checking those error codes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I ppreciate why we would want to keep them - however, keeping them would not solve the problem completely.

For some we can keep them via an alias asignment but any of them that were dynamic would not be possible (the ones with tokens in them):

ErrJetStreamNotEnabled = ApiErrors[Foo]

Non of these had tokens of course so I need to look, might have to adjust NewT() and related functions to instead of a new instance return the existing pointer that is in ApiErrors, thats the only way it could possibly work. This though is risky someone could adjust the "source" of these errors and bad things will happen, as there's no way to really make them read only as such

Copy link
Member

@kozlovic kozlovic May 25, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is silly of me to say to keep them not to "break" their code (because say ErrJetStreamNotEnabled is no longer defined), while it would break it in worse way by having the check for say ErrJetStreamNotEnabled be false because of the new errors returned.
So I would be ok if we remove in 2.3.0, but then if we have to release a 2.2.7 before that release, then we would have to create and maintain a branch_2_2_x to release from, which I would rather not have to do..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old costants were restored in ee9d10f with appropriate comments warning people etc

I think this one is good to go now

@ripienaar
Copy link
Contributor Author

ripienaar commented May 18, 2021

While we wait for @derekcollison to give this a look the one thing I've been mulling over is how we format the errors that are of the ErrorF form.

ApiErrors[JSStreamExternalApiOverlapErrF].ErrOrNewF(foo, bar)

Where the ApiErr is:

{Code: 400, ErrCode: 10021, Description: "stream external api prefix %q must not overlap with %s"},

The problem here is that we want to be able to extend and change these errors - especially if we later need to translate them - then the order based replace becomes a problem.

The typical fix is to make the description something like "stream external api prefix {prefix} must not overlap with {api}" and then:

ApiErrors[JSStreamExternalApiOverlapErrF].ErrOrNewF("{prefix}", foo, "{api}", bar)

This is much more robust and future proof, personally I think it's worth it, but curious what @ColinSullivan1 (who like me also seem to care for translation) and @kozlovic thinks

@kozlovic
Copy link
Member

This is much more robust and future proof, personally I think it's worth it, but curious what @ColinSullivan1 (who like me also seem to care for translation) and @kozlovic thinks

I agree.

@derekcollison derekcollison self-requested a review May 19, 2021 00:35
Copy link
Member

@derekcollison derekcollison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general LGTM. Went through them one by one so ignore repeated comments on codes need to be numbers.

server/jetstream_api.go Outdated Show resolved Hide resolved
server/jetstream_api.go Outdated Show resolved Hide resolved
server/jetstream_api.go Outdated Show resolved Hide resolved

// ErrNoTransforms signals no subject transforms are available to map this subject.
ErrNoTransforms = errors.New("no matching transforms available")

// ErrJetStreamNotEnabled is returned when JetStream is not enabled.
ErrJetStreamNotEnabled = errors.New("jetstream not enabled")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should leave, no harm imo..

server/jetstream_errors.go Outdated Show resolved Hide resolved
@ripienaar
Copy link
Contributor Author

I squashed this but I think I need more time to find a better solution to handle the named token replace things, forcing all things to be strings is terrible which is what strings.Replacer() wants. So will investigate more.

@derekcollison
Copy link
Member

We could do the string replace solution at a different time as well.

Copy link
Member

@derekcollison derekcollison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can merge once @kozlovic has signed off.

Copy link
Member

@kozlovic kozlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last comment regarding removing server's existing ErrXXX...

doc/adr/0007-error-codes.md Show resolved Hide resolved

// ErrNoTransforms signals no subject transforms are available to map this subject.
ErrNoTransforms = errors.New("no matching transforms available")

// ErrJetStreamNotEnabled is returned when JetStream is not enabled.
ErrJetStreamNotEnabled = errors.New("jetstream not enabled")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the point was that we would not use them anymore, but we may want to keep them as to possibly not break users that embed NATS Server and somehow were checking those error codes?

Signed-off-by: R.I.Pienaar <rip@devco.net>
Signed-off-by: R.I.Pienaar <rip@devco.net>
Copy link
Member

@kozlovic kozlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New field deprecates is misspelled in one of the error, also comment regarding ordering of the error codes in the json file.

server/errors.json Show resolved Hide resolved
server/errors.json Outdated Show resolved Hide resolved
Signed-off-by: R.I.Pienaar <rip@devco.net>
Copy link
Member

@kozlovic kozlovic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

server/errors_gen.go Show resolved Hide resolved
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

Successfully merging this pull request may close these issues.

None yet

4 participants