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

Improve "merkledag: not found" error #55

Merged
merged 4 commits into from
Mar 26, 2020
Merged

Improve "merkledag: not found" error #55

merged 4 commits into from
Mar 26, 2020

Conversation

hsanjuan
Copy link
Contributor

Based on #33, taking advantage of the rather new Is() methods from the errors
package to check for equality.

Based on #33, taking advantage of the rather new Is() methods from the errors
package to check for equality.
merkledag.go Outdated
// ErrNotFound is used to signal when a Node could not be found. The specific
// meaning will depend on the DAGService implementation, which may be trying
// to read nodes locally but also, trying to find them remotely.
var ErrNotFound = ErrNotFoundCid{}
Copy link
Member

Choose a reason for hiding this comment

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

Returning ErrNotFoundCid{Cid} is already going to break anything comparing against ErrNotFound. Given that, I'd rather explicitly break it and replace ErrNotFound with type ErrNotFound struct { Cid }.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, but no-one returns ErrNotFoundCid (and we can grep-fix all of our things accordingly). So for everyone else things would still work. But yeah, let's play safe and break.

@Stebalien
Copy link
Member

We should consider the comments form #33 and implement a NotFound method on the error. See: https://github.com/ipfs/go-datastore/blob/9e9a3a8350fe9b372e4d1cf8dc590d1f005a1540/datastore.go#L202-L213.

@Stebalien
Copy link
Member

Note: we're definitely going to punt this till after 0.5 as it may have other consequences.

@hsanjuan
Copy link
Contributor Author

We should consider the comments form #33 and implement a NotFound method on the error. See: https://github.com/ipfs/go-datastore/blob/9e9a3a8350fe9b372e4d1cf8dc590d1f005a1540/datastore.go#L202-L213.

What is the rationale for this approach? I don't fully understand it. Is the rationale here to be able to check if an error implements a NotFound interface and then use that method to decide? Who is supposed to call a .NotFound method?

I checked the blog post and my take is that wrapping and letting the original packages decide if it's one of their NotFound is the accepted approach. Particularly now that Go added wrap() and Is() methods natively. This allows both treating them as opaque and checking them when needed. It also allows every package to have their own ErrNotFound (which can wrap other ErrNotFounds).

Am I missing something?

merkledag.go Show resolved Hide resolved
Comment on lines +15 to +17
type ErrNotFound struct {
Cid cid.Cid
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exposed Cid thinking that this might be used from outside this module.

It is ugly though that you have to instantiate the struct whenever you want to check if errors.Is(whatever, ErrNotFound{}).

Copy link
Member

Choose a reason for hiding this comment

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

We can add an IsNotFound function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added, and made it equivalent to Is.

@Stebalien
Copy link
Member

From async discussion:

Really, there are two kinds of checks: "is" and "property".

  • is: Useful when you want to check if an error was ultimately caused by some specific error. Honestly, that's probably what we want here.
  • property: This is how, e.g., timeout errors usually work. You implement functions on your custom error type indicating the properties your error has. Then, you can call As(err, &targetInterface) on the error to tell if the error can have the given property. Finally, you invoke the actual function (in this case, NotFound() bool to determine if the error actually has that property.

TL;DR: NotFound() is probably a "nice to have". For our particular use-case, it's not really all that useful as we specifically want to know if the error was "IPLD node not found", not some random "datastore is broken because the index wasn't found" error.

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.

2 participants