|
Currently there are a lot of duplicate errors between the mongo package and packages in the "x/" directory. The API of packages in the "x/" directory is not stable, so we never want to return an error type defined there. However, that requires us to replace errors defined in "x/" packages with errors defined in the mongo package (see replaceErrors and processWriteError). Unfortunately, that logic sometimes misses error types or values because it is difficult to keep in-sync with error logic in other packages. Additionally, it makes reasoning about errors difficult and is a source of bugs and usability problems.
Generally the pattern of replaceErrors/processWriteError is bug-prone because it's extremely difficult to comprehensively account for all error types. There are a some better options for handling errors like this:
- Don't break out error types in the "x/" (i.e. internal but exported) packages. Define one or a few error types that communicate the error information and break them out into more usable error types that are all defined in the mongo package.
- Define error interfaces in the mongo package that define expected error methods instead of error types. Assert that the errors satisfy the expected interfaces in the mongo package.
package mongo
|
|
type ExternalError interface {
|
ErrorInfo()
|
}
|
|
var _ ExternalError = driver.InternalError
|
That allows using errors.As like
var exterr ExternalError
|
if errors.As(err, &exterr) {
|
exterr.ErrorInfo()
|
// ...
|
Open questions:
- Which approach supports all of our error handling requirements?
- Which approach is the simplest to implement? To maintain? To use?
Definition of done:
- Pick an approach for error handling that doesn't require implementing a function like replaceErrors, and implement it. Also, experimental/internal packages cannot reference symbols in the stable packages, so it must be done in a way that doesn't require all packages to reference one symbol.
- Remove the the replaceErrors function.
|