Mercurial > gemma
changeset 4071:5867dcf8e93c
Introduced a new ReadableError type for better readable error messages of pgx.PgErrors.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Thu, 25 Jul 2019 13:31:51 +0200 |
parents | 6ebe42af392d |
children | eb2f949ddfa2 0507a9e4772b |
files | pkg/controllers/user.go pkg/imports/bn.go pkg/imports/fd.go pkg/imports/gm.go pkg/imports/sec.go pkg/imports/st.go pkg/imports/wa.go pkg/imports/wg.go pkg/imports/wx.go pkg/pgxutils/errors.go |
diffstat | 10 files changed, 66 insertions(+), 39 deletions(-) [+] |
line wrap: on
line diff
--- a/pkg/controllers/user.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/controllers/user.go Thu Jul 25 13:31:51 2019 +0200 @@ -263,7 +263,8 @@ } if err != nil { - err = pgxutils.HandleError(err) + m, c := pgxutils.ReadableError{err}.MessageAndCode() + err = JSONError{Code: c, Message: m} return }
--- a/pkg/imports/bn.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/bn.go Thu Jul 25 13:31:51 2019 +0200 @@ -591,7 +591,7 @@ ) } if err != nil { - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) return nil } defer bns.Close() @@ -603,7 +603,7 @@ bnIds = append(bnIds, nid) } if err := bns.Err(); err != nil { - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) return nil } if len(bnIds) == 0 { @@ -620,7 +620,7 @@ &validity, &pgBnIds, ); err != nil { - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) if err2 := tx.Rollback(); err2 != nil { return err2 } @@ -633,7 +633,7 @@ bn.Bottleneck_id, validity, ); err != nil { - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) if err2 := tx.Rollback(); err2 != nil { return err2 } @@ -670,7 +670,7 @@ &pgMaterials, ); err != nil { feedback.Warn("Failed to insert riverbed materials") - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) return nil } }
--- a/pkg/imports/fd.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/fd.go Thu Jul 25 13:31:51 2019 +0200 @@ -311,7 +311,7 @@ // ignore -> filtered by responsibility_areas continue features case err != nil: - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) continue features } // Store for potential later removal.
--- a/pkg/imports/gm.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/gm.go Thu Jul 25 13:31:51 2019 +0200 @@ -457,7 +457,7 @@ case err == sql.ErrNoRows: // thats expected, nothing to do case err != nil: - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) default: newP++ } @@ -488,7 +488,7 @@ case err == sql.ErrNoRows: // thats expected, nothing to do case err != nil: - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) default: newM++ }
--- a/pkg/imports/sec.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/sec.go Thu Jul 25 13:31:51 2019 +0200 @@ -182,7 +182,7 @@ sec.Source, sec.Tolerance, ).Scan(&id); err != nil { - return nil, pgxutils.HandleError(err) + return nil, pgxutils.ReadableError{err} } if err := track(ctx, tx, importID, "waterway.sections", id); err != nil {
--- a/pkg/imports/st.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/st.go Thu Jul 25 13:31:51 2019 +0200 @@ -203,7 +203,7 @@ st.Source, st.Tolerance, ).Scan(&id); err != nil { - return nil, pgxutils.HandleError(err) + return nil, pgxutils.ReadableError{err} } // store the associated countries.
--- a/pkg/imports/wa.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/wa.go Thu Jul 25 13:31:51 2019 +0200 @@ -247,7 +247,7 @@ outside++ // ignore -> filtered by responsibility_areas case err != nil: - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) default: features++ }
--- a/pkg/imports/wg.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/wg.go Thu Jul 25 13:31:51 2019 +0200 @@ -327,7 +327,7 @@ ).Scan(&isNew) switch { case err != nil: - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) if err2 := tx.Rollback(); err2 != nil { return nil, err2 } @@ -352,7 +352,7 @@ source, time.Time(*dr.Lastupdate), ); err != nil { - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) if err2 := tx.Rollback(); err2 != nil { return nil, err2 } @@ -389,7 +389,7 @@ unchanged++ continue case err2 != nil: - feedback.Warn(pgxutils.HandleError(err2).Error()) + feedback.Warn(pgxutils.ReadableError{err2}.Error()) if err3 := tx.Rollback(); err3 != nil { return nil, err3 } @@ -436,7 +436,7 @@ code.String(), &validity, ); err != nil { - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) if err2 := tx.Rollback(); err2 != nil { return nil, err2 } @@ -484,7 +484,7 @@ string(**wl.level), int64(**wl.value), ); err != nil { - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) tx.Rollback() continue }
--- a/pkg/imports/wx.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/imports/wx.go Thu Jul 25 13:31:51 2019 +0200 @@ -321,7 +321,7 @@ // ignore -> filtered by responsibility_areas return nil case err != nil: - feedback.Warn(pgxutils.HandleError(err).Error()) + feedback.Warn(pgxutils.ReadableError{err}.Error()) default: *features++ }
--- a/pkg/pgxutils/errors.go Thu Jul 25 12:32:10 2019 +0200 +++ b/pkg/pgxutils/errors.go Thu Jul 25 13:31:51 2019 +0200 @@ -10,24 +10,17 @@ // // Author(s): // * Tom Gottfried <tom.gottfried@intevation.de> +// * Sascha L. Teichmann <sascha.teichmann@intevation.de> package pgxutils import ( + "net/http" "strings" "github.com/jackc/pgx" ) -// Handle PostgreSQL error codes -func HandleError(err error) error { - switch e := err.(type) { - case pgx.PgError: - return dbError(e) - } - return err -} - const ( notNullViolation = "23502" foreignKeyViolation = "23503" @@ -36,9 +29,31 @@ noDataFound = "P0002" ) -type dbError pgx.PgError +type ReadableError struct { + Err error +} + +func (re ReadableError) Error() string { + m, _ := re.MessageAndCode() + return m +} -func (err dbError) Error() string { +// MessageAndCode returns a user-readable message +// and a matching HTTP status code. +// If its not a pgx.PgError it defaults to +// calling the parent Error method and returns its +// result together with http.StatusInternalServerError. +func (re ReadableError) MessageAndCode() (string, int) { + if e, ok := re.Err.(pgx.PgError); ok { + return messageAndCode(e) + } + return re.Err.Error(), http.StatusInternalServerError +} + +func messageAndCode(err pgx.PgError) (m string, c int) { + + c = http.StatusInternalServerError + switch err.Code { case notNullViolation: switch err.SchemaName { @@ -47,11 +62,14 @@ case "gauges": switch err.ColumnName { case "objname": - return "Missing objname" + m = "Missing objname" + return case "geom": - return "Missing lat/lon" + m = "Missing lat/lon" + return case "zero_point": - return "Missing zeropoint" + m = "Missing zeropoint" + return } } } @@ -62,7 +80,8 @@ case "gauge_measurements", "gauge_predictions", "bottlenecks": switch err.ConstraintName { case "gauge_key": - return "Referenced gauge with matching temporal validity not available" + m = "Referenced gauge with matching temporal validity not available" + return } } } @@ -73,7 +92,9 @@ case "user_profiles": switch err.ConstraintName { case "user_profiles_pkey": - return "A user with that name already exists" + m = "A user with that name already exists" + c = http.StatusConflict + return } } } @@ -82,14 +103,19 @@ recent := strings.SplitN(err.Where, "\n", 1)[0] switch { case strings.Contains(recent, "isrsrange_points"): - return "No distance mark found for at least one given ISRS Location Code" + m = "No distance mark found for at least one given ISRS Location Code" + return case strings.Contains(recent, "isrsrange_axis"): - return "No contiguous axis found between given ISRS Location Codes" + m = "No contiguous axis found between given ISRS Location Codes" + return case strings.Contains(recent, "isrsrange_area"): - return "No area around axis between given ISRS Location Codes" + m = "No area around axis between given ISRS Location Codes" + return } case violatesRowLevelSecurity: - return "Could not save: Data outside the area of responsibility." + m = "Could not save: Data outside the area of responsibility." + return } - return "Unexpected database error: " + err.Message + m = "Unexpected database error: " + err.Message + return }