changeset 4080:af2b20d6c921 historization_ng

Merged default
author Sascha Wilde <wilde@intevation.de>
date Thu, 25 Jul 2019 16:10:28 +0200
parents 21854740f433 (current diff) cb74aa69954e (diff)
children c9bef8c27685
files pkg/imports/agm.go pkg/imports/bn.go pkg/imports/gm.go pkg/imports/wg.go pkg/misc/time.go
diffstat 15 files changed, 95 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/common/time.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/common/time.go	Thu Jul 25 16:10:28 2019 +0200
@@ -27,8 +27,26 @@
 	DateFormat = "2006-01-02"
 )
 
+// TimeParser is a list of time formats.
+type TimeParser []string
+
 var utc0 = time.Unix(0, 0)
 
+// Parse tries to parse a given string by the entries of the layout
+// list one after another. The first matching time is returned.
+// If no layout matches the last error is returned or time zero
+// if the layout list is empty.
+func (tg TimeParser) Parse(s string) (time.Time, error) {
+	var err error
+	var t time.Time
+	for _, layout := range tg {
+		if t, err = time.Parse(layout, s); err == nil {
+			break
+		}
+	}
+	return t, err
+}
+
 func InterpolateTime(t1 time.Time, m1 float64, t2 time.Time, m2 float64) func(float64) time.Time {
 
 	// f(m1) = t1
--- a/pkg/controllers/user.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/controllers/user.go	Thu Jul 25 16:10:28 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/agm.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/imports/agm.go	Thu Jul 25 16:10:28 2019 +0200
@@ -31,6 +31,7 @@
 	"strings"
 	"time"
 
+	"gemma.intevation.de/gemma/pkg/common"
 	"gemma.intevation.de/gemma/pkg/misc"
 	"gemma.intevation.de/gemma/pkg/models"
 )
@@ -103,10 +104,10 @@
 	return os.RemoveAll(agm.Dir)
 }
 
-var guessDate = misc.TimeGuesser([]string{
+var guessDate = common.TimeParser([]string{
 	"02.01.2006 15:04",
 	"2006-01-02T15:04:05-07:00",
-}).Guess
+}).Parse
 
 type timetz struct{ time.Time }
 
--- a/pkg/imports/bn.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/imports/bn.go	Thu Jul 25 16:10:28 2019 +0200
@@ -582,7 +582,7 @@
 		)
 	}
 	if err != nil {
-		feedback.Warn(pgxutils.HandleError(err).Error())
+		feedback.Warn(pgxutils.ReadableError{err}.Error())
 		return nil
 	}
 	defer bns.Close()
@@ -594,7 +594,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 {
@@ -611,7 +611,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
 		}
@@ -624,7 +624,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
 		}
@@ -661,7 +661,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 15:02:19 2019 +0200
+++ b/pkg/imports/fd.go	Thu Jul 25 16:10:28 2019 +0200
@@ -21,7 +21,7 @@
 	"io"
 	"time"
 
-	"gemma.intevation.de/gemma/pkg/misc"
+	"gemma.intevation.de/gemma/pkg/common"
 	"gemma.intevation.de/gemma/pkg/pgxutils"
 	"gemma.intevation.de/gemma/pkg/wfs"
 )
@@ -48,11 +48,11 @@
 
 type fdTime struct{ time.Time }
 
-var guessFDTime = misc.TimeGuesser([]string{
+var guessFDTime = common.TimeParser([]string{
 	"20060102",
 	"2006",
 	"",
-}).Guess
+}).Parse
 
 func (fdt *fdTime) UnmarshalJSON(data []byte) error {
 	var s string
@@ -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 15:02:19 2019 +0200
+++ b/pkg/imports/gm.go	Thu Jul 25 16:10:28 2019 +0200
@@ -443,7 +443,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++
 					}
@@ -474,7 +474,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 15:02:19 2019 +0200
+++ b/pkg/imports/sec.go	Thu Jul 25 16:10:28 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 15:02:19 2019 +0200
+++ b/pkg/imports/st.go	Thu Jul 25 16:10:28 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 15:02:19 2019 +0200
+++ b/pkg/imports/wa.go	Thu Jul 25 16:10:28 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 15:02:19 2019 +0200
+++ b/pkg/imports/wg.go	Thu Jul 25 16:10:28 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/wp.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/imports/wp.go	Thu Jul 25 16:10:28 2019 +0200
@@ -30,7 +30,7 @@
 
 	"github.com/jackc/pgx/pgtype"
 
-	"gemma.intevation.de/gemma/pkg/misc"
+	"gemma.intevation.de/gemma/pkg/common"
 	"gemma.intevation.de/gemma/pkg/models"
 	"gemma.intevation.de/gemma/pkg/wfs"
 )
@@ -418,7 +418,7 @@
 	feedback.Info(
 		"Matching points to lines with a precision of %.4fm.", precision)
 
-	parseDate := misc.TimeGuesser([]string{"02.01.2006"}).Guess
+	parseDate := common.TimeParser([]string{"02.01.2006"}).Parse
 
 	insertStmt, err := tx.PrepareContext(ctx, insertWaterwayProfileSQL)
 	if err != nil {
--- a/pkg/imports/wx.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/imports/wx.go	Thu Jul 25 16:10:28 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/misc/time.go	Thu Jul 25 15:02:19 2019 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-// This is Free Software under GNU Affero General Public License v >= 3.0.Reader.
-// without warranty, see README.md and license for details.
-//
-// SPDX-License-Identifier: AGPL-3.0-or-later
-// License-Filename: LICENSES/AGPL-3.0.txt
-//
-// Copyright (C) 2018 by via donau
-//   – Österreichische Wasserstraßen-Gesellschaft mbH
-// Software engineering by Intevation GmbH
-//
-// Author(s):
-//  * Sascha L. Teichmann <sascha.teichmann@intevation.de>
-
-package misc
-
-import "time"
-
-// TimeGuesser is a list of time formats.
-type TimeGuesser []string
-
-// Guess tries to parse a given string by the entries of the layout
-// list one after another. The first matching time is returned.
-// If no layout matches the last error is returned or time zero
-// if the layout list is empty.
-func (tg TimeGuesser) Guess(s string) (time.Time, error) {
-	var err error
-	var t time.Time
-	for _, layout := range tg {
-		if t, err = time.Parse(layout, s); err == nil {
-			break
-		}
-	}
-	return t, err
-}
--- a/pkg/pgxutils/errors.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/pgxutils/errors.go	Thu Jul 25 16:10:28 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
 }
--- a/pkg/soap/nts/service.go	Thu Jul 25 15:02:19 2019 +0200
+++ b/pkg/soap/nts/service.go	Thu Jul 25 16:10:28 2019 +0200
@@ -18,14 +18,14 @@
 	"encoding/xml"
 	"time"
 
-	"gemma.intevation.de/gemma/pkg/misc"
+	"gemma.intevation.de/gemma/pkg/common"
 	"gemma.intevation.de/gemma/pkg/soap"
 )
 
-var guessDateTime = misc.TimeGuesser([]string{
+var guessDateTime = common.TimeParser([]string{
 	"2006-01-02T15:04:05",
 	"2006-01-02T15:04:05-07:00",
-}).Guess
+}).Parse
 
 type DateTime struct{ time.Time }