How we handle error from the api?
Suppose we create server that expose functionality to getUserById
. There are some options to use for exposing our functionality (ex: using grpc/rest/graphql). There are some options to persist out data too (ex: mysql,redis, or just in memory?). Suppose I have interface:
package user
type Service interface {
UserByID(ID: string): (*User, error)
}
and then we can implement it using mysql/sqlite/inmemory. But all of this implementation have different behaviour and can return different error. Mysql may return connection error, sqlite may return error that indicates no disk space available.
When user call out API, it might go to graphql -> user.Service
-> maybe user.Store?
. And when error happened, we want our API to provide error information to the user (ex: by using error code like NoSuchUser
, TooManyRequest
). But we don’t want user to know internal error like ConnectionError
, DiskError
etc. We want hide the internal error to InternalServerError
to user.
So how our implementation of user.Service
should return the error so our api can decide whether to hide that error into InternalServerError
.
I found really nice article Don’t just check errors, handle them gracefully by Dave Cheney.
It says that we should assert error by behaviour instead of type.
Should we create interface IsInternalError
, so the api can now whether they should hide the error. But how does the implementation of user.Service
know that it should returns error that implement this interface?