Skip to content

Commit

Permalink
fix(api): Fix/standardize db error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
alexstojda committed Aug 6, 2023
1 parent fdce652 commit 1101e0f
Show file tree
Hide file tree
Showing 10 changed files with 18 additions and 14 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ require (
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090
gorm.io/datatypes v1.2.0
gorm.io/driver/postgres v1.5.0
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11
gorm.io/gorm v1.25.2
)

require (
Expand Down
5 changes: 5 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
Expand Down Expand Up @@ -145,6 +146,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
Expand Down Expand Up @@ -173,6 +175,7 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
Expand Down Expand Up @@ -682,6 +685,8 @@ gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g=
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
7 changes: 3 additions & 4 deletions internal/app/api/league/league.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package league

import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
Expand Down Expand Up @@ -43,7 +42,7 @@ func (c *Controller) CreateLeague(ctx *gin.Context) {
location := models.Location{}
locationQueryResult := c.DB.Where("id = ?", payload.LocationId).First(&location)
if locationQueryResult.Error != nil {
if errors.Is(locationQueryResult.Error, gorm.ErrRecordNotFound) {
if strings.Contains(locationQueryResult.Error.Error(), "not found") {
apierrors.AbortWithError(http.StatusBadRequest, fmt.Sprintf("location with id %s does not exist", payload.LocationId), ctx)
return
} else {
Expand All @@ -65,7 +64,7 @@ func (c *Controller) CreateLeague(ctx *gin.Context) {

createResult := c.DB.Create(&league)
if createResult.Error != nil {
if strings.Contains(createResult.Error.Error(), "duplicate key value violates unique") {
if strings.Contains(createResult.Error.Error(), "duplicate key") {
apierrors.AbortWithError(http.StatusConflict, "league with slug already exists", ctx)
return
} else {
Expand Down Expand Up @@ -135,7 +134,7 @@ func (c *Controller) GetLeagueWithSlug(ctx *gin.Context, slug string) {
var dbResult models.League
result := c.DB.Preload("Location").Where("slug = ?", slug).First(&dbResult)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
if strings.Contains(result.Error.Error(), "not found") {
apierrors.AbortWithError(http.StatusNotFound, "league not found", ctx)
return
} else {
Expand Down
2 changes: 1 addition & 1 deletion internal/app/api/league/league_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ var _ = ginkgo.Describe("Controller", func() {
const sqlInsert = `INSERT INTO "leagues" ("name","slug","owner_id","location_id","created_at","updated_at") VALUES ($1,$2,$3,$4,$5,$6) RETURNING "id"`
mock.ExpectQuery(regexp.QuoteMeta(sqlInsert)).
WithArgs(payload.Name, payload.Slug, userObj.ID.String(), payload.LocationId, utils.AnyTime{}, utils.AnyTime{}).
WillReturnError(fmt.Errorf("duplicate key value violates unique"))
WillReturnError(fmt.Errorf("ERROR: duplicate key value violates unique constraint \"idx_league_slug\" (SQLSTATE 23505)"))
mock.ExpectRollback()

body, err := json.Marshal(payload)
Expand Down
7 changes: 3 additions & 4 deletions internal/app/api/location/location.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package location

import (
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
Expand Down Expand Up @@ -61,8 +60,8 @@ func (c *Controller) CreateLocation(ctx *gin.Context) {

result := c.DB.Create(&location)
if result.Error != nil {
if strings.Contains(result.Error.Error(), "duplicate key value violates unique") {
//TODO: Add some retry logic to generate a different slug if this happens
if strings.Contains(result.Error.Error(), "duplicate key") {
// TODO: Add some retry logic to generate a different slug if this happens
apierrors.AbortWithError(http.StatusConflict, "location with slug already exists", ctx)
return
} else {
Expand Down Expand Up @@ -116,7 +115,7 @@ func (c *Controller) GetLocationWithSlug(ctx *gin.Context, slug string) {
var location models.Location
result := c.DB.Where("slug = ?", slug).First(&location)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
if strings.Contains(result.Error.Error(), "not found") {
apierrors.AbortWithError(http.StatusNotFound, "location not found", ctx)
return
} else {
Expand Down
2 changes: 1 addition & 1 deletion internal/app/api/location/location_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ var _ = ginkgo.Describe("Location", func() {
"123 Main St, Austin, TX, USA",
1,
utils.AnyTime{}, utils.AnyTime{},
).WillReturnError(fmt.Errorf("duplicate key value violates unique"))
).WillReturnError(fmt.Errorf("ERROR: duplicate key value violates unique constraint \"idx_location_slug\" (SQLSTATE 23505)"))
mock.ExpectRollback()

body, err := json.Marshal(&generated.LocationCreate{
Expand Down
2 changes: 1 addition & 1 deletion internal/app/api/tournament/tournament.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (c *Controller) CreateTournament(ctx *gin.Context) {

result := c.DB.Create(tournament)
if result.Error != nil {
if strings.Contains(result.Error.Error(), "duplicate key value violates unique") {
if strings.Contains(result.Error.Error(), "duplicate key") {
apierrors.AbortWithError(http.StatusBadRequest, "tournament with slug already exists", ctx)
return
} else {
Expand Down
2 changes: 1 addition & 1 deletion internal/app/api/user/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (c *Controller) SignUpUser(ctx *gin.Context) {
result := c.DB.Create(&newUser)

if result.Error != nil {
if strings.Contains(result.Error.Error(), "duplicate key value violates unique") {
if strings.Contains(result.Error.Error(), "duplicate key") {
errors.AbortWithError(http.StatusConflict, "user with that email already exists", ctx)
return
} else {
Expand Down
2 changes: 1 addition & 1 deletion internal/app/api/user/user_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ var _ = g.Describe("Controller", func() {
const sqlInsert = `INSERT INTO "users" ("name","email","password","role","verified","created_at","updated_at") VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING "id"`
mock.ExpectQuery(regexp.QuoteMeta(sqlInsert)).
WithArgs(payload.Name, payload.Email, utils.AnyString{}, "user", true, utils.AnyTime{}, utils.AnyTime{}).
WillReturnError(fmt.Errorf("duplicate key value violates unique"))
WillReturnError(fmt.Errorf("ERROR: duplicate key value violates unique constraint \"idx_user_email\" (SQLSTATE 23505)"))

body, err := json.Marshal(payload)
m.Expect(err).To(m.BeNil())
Expand Down
1 change: 1 addition & 0 deletions internal/utils/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func ConnectDB(config *Config, dialector ...gorm.Dialector) (*gorm.DB, error) {

db, err := gorm.Open(dialectorVar, &gorm.Config{
Logger: GormLogger{},
//TranslateError: false,
})
if err != nil {
return nil, err
Expand Down

0 comments on commit 1101e0f

Please sign in to comment.