Created
January 18, 2020 16:57
-
-
Save steebchen/51ab929e04ae7436afca6b9d605e78f4 to your computer and use it in GitHub Desktop.
Prisma Go database client error handling
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"errors" | |
"fmt" | |
"log" | |
) | |
func main() { | |
// Since FindMany only reads data, there can be no expected errors. There may | |
// be unexpected errors such as that the database connection is lost, but this is | |
// a fatal error which doesn't make sense to be handled individually with `err != nil` | |
// because they don't provide any more value. Instead, if there's a fatal error, this | |
// method panics (which will be handled by your webserver to return a 500 code). | |
users := FindManyUsers() | |
log.Printf("users: %+v", users) | |
// FindOne with `ok`, since there would be one error of type ErrNotFound which is not really an error | |
user, ok := FindOneUser() | |
if !ok { | |
fmt.Printf("no user found") | |
} | |
log.Printf("%+v", user) | |
// ------------ | |
// implementing errors | |
_, delErr := DeleteUser() // returns (User, error) | |
// the next line won't compile, because `delErr` does not satisfy the parameter | |
if v, ok := IsUniqueConstraintViolation(delErr); ok { // <- WON'T COMPILE! | |
// ^^^^^^ | |
// Cannot use 'delErr' (type error) as type CanUniqueConstraintViolation | |
fmt.Printf("colum %s is not unique", v.Column) | |
} | |
// super nice error handling: | |
_, createErr := CreateUser() | |
// following line will compile, because `createErr` can have a unique constraint violation | |
if v, ok := IsUniqueConstraintViolation(createErr); ok { | |
// v is of type UserConstraintViolation, which contains details such as v.Column of type UniqueColumnUser so you can provide fine-grained error messages | |
switch v.Column { | |
case UniqueColumnUserEmail: | |
fmt.Printf("hey user, email %s is already taken!", v.Column) | |
default: | |
fmt.Printf("colum %s is not unique", v.Column) | |
} | |
} else { | |
fmt.Printf("unhandled error") | |
} | |
// ------------ | |
// evolution of errors | |
// 1 | |
var v *ErrUniqueConstraintViolation | |
if errors.As(createErr, v) { | |
fmt.Printf("err in column %s", v.Column) | |
} | |
// 2 | |
if v := CheckUniqueConstraintViolation(); errors.As(createErr, v) { | |
fmt.Printf("colum %s is not unique", v.Column) | |
} | |
// 3 | |
if v, ok := IsUniqueConstraintViolation(createErr); ok { | |
fmt.Printf("colum %s is not unique", v.Column) | |
} | |
} | |
func CheckUniqueConstraintViolation() *ErrUniqueConstraintViolation { | |
return &ErrUniqueConstraintViolation{} | |
} | |
type UniqueColumnUser string | |
const ( | |
UniqueColumnUserID UniqueColumnUser = "id" | |
UniqueColumnUserEmail UniqueColumnUser = "email" | |
) | |
type ErrUniqueConstraintViolation struct { | |
Column UniqueColumnUser | |
} | |
func (e ErrUniqueConstraintViolation) Error() string { | |
return fmt.Sprintf("unique constraint violated for field %s", e.Column) | |
} | |
func IsUniqueConstraintViolation(err CanUniqueConstraintViolation) (*ErrUniqueConstraintViolation, bool) { | |
var v *ErrUniqueConstraintViolation | |
if errors.As(err, v) { | |
fmt.Printf("err in column %s", v.Column) | |
return v, true | |
} | |
return nil, false | |
} | |
type CanUniqueConstraintViolation interface { | |
Error() string | |
CanUniqueConstraintViolation() | |
} | |
type UserCreateError interface { | |
Error() string | |
CanUniqueConstraintViolation() | |
} | |
type userError struct{} | |
func (userError) Error() string { | |
return "stuff" | |
} | |
func (userError) CanUniqueConstraintViolation() {} | |
func CreateUser() (User, UserCreateError) { | |
return User{}, &userError{} | |
} | |
func DeleteUser() (User, error) { | |
return User{}, errors.New("x") | |
} | |
func FindOneUser() (User, bool) { | |
return User{}, true | |
} | |
func FindManyUsers() []User { | |
return []User{} | |
} | |
type User struct { | |
Name string | |
} |
Author
steebchen
commented
Jan 18, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment