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

roachpb: remove deprecated fields from Error #73686

Closed
wants to merge 1 commit into from

Conversation

tbg
Copy link
Member

@tbg tbg commented Dec 10, 2021

CRDB 21.2 already populates Errors.EncodedError, so we can remove the
deprecated fields.

I was motivated to do this when working on a follow-up to #73602 and
ended up trying to marshal an Error to JSON, which panics since
it ends up trying to use reflect to get an unexported value (due
to the customname tags on the deprecated fields). This behavior
persists even with the json: "-" tag, by the way, indicating
that we should never use (gogoproto.customname) to make a field
private. It's also just one more papercut that comes with using
gogoproto but that's a much bigger fish to fry.

cc @lidorcarmel since you're just poking at Error.

Release note: None

@tbg tbg requested a review from nvanbenschoten December 10, 2021 16:58
@tbg tbg requested a review from a team as a code owner December 10, 2021 16:58
@cockroach-teamcity
Copy link
Member

This change is Reviewable

CRDB 21.2 already populates `Errors.EncodedError`, so we can remove the
deprecated fields.

I was motivated by this when working on a follow-up to cockroachdb#73602 and
ended up trying to marshal an `Error` to JSON, which panics since
it ends up trying to use `reflect` to get an unexported value (due
to the `customname` tags on the deprecated fields). This behavior
persists even with the `json: "-"` tag, by the way, indicating
that we should never use `(gogoproto.customname)` to make a field
private. It's also just one more papercut that comes with using
`gogoproto` but that's a much bigger fish to fry.

Release note: None
@tbg tbg force-pushed the error-remove-depr-fields branch from 561e655 to 66c8399 Compare December 10, 2021 20:16
@tbg
Copy link
Member Author

tbg commented Dec 10, 2021

I typed this up at the end of my day and had to send it out in a bit of a rush, so reviewers should feel comfortable waiting until I've given myself a self-review early next week. This stuff is slightly terrifying, don't want to know what will go wrong if there's a bug in here.

@tbg
Copy link
Member Author

tbg commented Dec 10, 2021

note for next week: I can also remove internalError, this is now no longer instantiated and so doesn't have to be handled.

another thread that I should pull on: the loss of fidelity in GoError() is bad. We should have this:

type GoError struct {
  wrapped error // corresponds to pErr.EncodedError, we implement stuff for `errors.Is` etc
  Index int
  // other fields too
}

func (err *GoError) AsProto() *Error {
  return &Error{
    // populate all fields from `err`
  }
}

and then

func (e *Error) GoError() {
  return &GoError{
    wrapped: e.decode(),
    Index: e.Index,
    // ...
  }
}
func NewError(err error) {
  var goErr error
  if errors.As(err, &goErr) {
    return goErr.AsProto()
  }
  return &Error{ /* ... */ }
}

and here we have it, require.Equal(t, NewError(pErr.GoError()), pErr).

@tbg
Copy link
Member Author

tbg commented Jan 3, 2022

Actually rather than having *Error and a Go version of it, the *Error should just implement error. We shied away from that in the past since we were storing errors inside of Error and we were worried that the semantics would get super confusing, but now that we're just using cockroachdb/errors throughout (assuming I've removed the loss of fidelity mentioned above) there doesn't seem to be a reason to avoid it any more.

@knz would appreciate your eyes on the thinking.

Copy link
Contributor

@knz knz 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 this is a step in the right direction. What are the open questions that remain?

(I'm a little bit confused by roachpb.internalError. What purpose does it serve?)

Reviewed 2 of 4 files at r1, 3 of 3 files at r2, all commit messages.
Reviewable status: :shipit: complete! 0 of 0 LGTMs obtained (waiting on @nvanbenschoten and @tbg)


pkg/roachpb/errors.go, line 151 at r2 (raw file):

		return nil
	}
	if intErr, ok := err.(*internalError); ok {

Can you walk me through the role of internalError? What is this for? Why does it hide its cause?


pkg/roachpb/errors.go, line 187 at r2 (raw file):

// SafeFormat implements redact.SafeFormatter.
func (e *Error) SafeFormat(s redact.SafePrinter, _ rune) {

If/when *Error is meant to become an error, you may want to implement errors.SafeFormatter instead. This may be worth adding a TODO.


pkg/roachpb/errors.go, line 230 at r2 (raw file):

func (e *Error) TransactionRestart() TransactionRestart {
	var iface transactionRestartError
	if errors.As(e.decode(), &iface) {

Is there a way to memoize the result of decoding, so we don't end up doing it on every api call that uses .decode()? Decoding is rather expensive.

@irfansharif irfansharif added the X-noremind Bots won't notify about PRs with X-noremind label Aug 26, 2022
@tbg
Copy link
Member Author

tbg commented Sep 9, 2022

@ajwerner did this in #86683 🥳

@tbg tbg closed this Sep 9, 2022
@tbg tbg deleted the error-remove-depr-fields branch September 9, 2022 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
X-noremind Bots won't notify about PRs with X-noremind
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants