Selaa lähdekoodia

Domain-semantic errors.

Frederic G. MARAND 5 vuotta sitten
vanhempi
säilyke
0607c74592
5 muutettua tiedostoa jossa 64 lisäystä ja 13 poistoa
  1. 1 3
      domain/domain_api.go
  2. 57 0
      domain/errors.go
  3. 1 2
      domain/short_url.go
  4. 1 3
      infrastructure/memory.go
  5. 4 5
      infrastructure/mysql.go

+ 1 - 3
domain/domain_api.go

@@ -1,7 +1,5 @@
 package domain
 
-import "errors"
-
 func GetTargetURL(shortURL string) (target string, err error) {
 	su := ShortURL{URL: URL(shortURL)}
 	tu, err := shortURLRepository.GetTarget(su)
@@ -18,7 +16,7 @@ func GetShortURL(targetURL string) (short string, isNew bool, err error) {
 	tu := TargetURL{URL: URL(targetURL)}
 	if tu.IsEmpty() {
 		// Zero values are OK for short and isNew.
-		err = errors.New("Empty target is not valid")
+		err = MakeError(TargetInvalidError, "empty URL")
 		return
 	}
 	su, isNew, err := targetURLRepository.GetShort(tu)

+ 57 - 0
domain/errors.go

@@ -0,0 +1,57 @@
+package domain
+
+import (
+	"errors"
+	"fmt"
+)
+
+type ErrorKind int
+
+const (
+	NoError ErrorKind = iota
+	Unimplemented
+
+	ShortNotFound
+
+	TargetBlockedError
+	TargetCensoredError
+	TargetInvalidError
+
+	StorageReadError
+	StorageWriteError
+	StorageUnspecifiedError
+)
+
+var Errors = map[ErrorKind]string{
+	NoError:       "No error",
+	Unimplemented: "Not yet implemented",
+
+	ShortNotFound: "Short URL not defined",
+
+	TargetBlockedError:  "Target blocked",
+	TargetCensoredError: "Target unavailable for legal reasons",
+	TargetInvalidError:  "Target invalid",
+
+	StorageReadError:        "Storage read error",
+	StorageWriteError:       "Storage write error",
+	StorageUnspecifiedError: "Storage unspecified error",
+}
+
+type Error struct {
+	error
+	Kind ErrorKind
+}
+
+func MakeError(kind ErrorKind, detail string) Error {
+	var message string
+	if len(detail) == 0 {
+		message = Errors[kind]
+	} else {
+		message = fmt.Sprintf("%s: %s", Errors[kind], detail)
+	}
+
+	return Error{
+		Kind:  kind,
+		error: errors.New(message),
+	}
+}

+ 1 - 2
domain/short_url.go

@@ -1,7 +1,6 @@
 package domain
 
 import (
-	"errors"
 	"math/rand"
 	"strconv"
 )
@@ -21,7 +20,7 @@ MakeShortURL creates a ShortURL instance from a given RedirectURL/target pair.
 func NewUnspecifiedShortURL(target TargetURL) (ShortURL, error) {
 	var su ShortURL
 	if target.IsEmpty() {
-		return su, errors.New("cannot target empty RedirectURL")
+		return su, MakeError(TargetInvalidError, "empty URL")
 	}
 
 	// FIXME: will cause collisions.

+ 1 - 3
infrastructure/memory.go

@@ -1,8 +1,6 @@
 package infrastructure
 
 import (
-	"errors"
-
 	"code.osinet.fr/fgm/kurz/domain"
 )
 
@@ -26,7 +24,7 @@ func (sr MemoryShortURLRepository) GetTarget(su domain.ShortURL) (domain.TargetU
 	if t, ok := sr.targets[su.URL]; ok {
 		tu = domain.TargetURL{URL: t}
 	} else {
-		err = errors.New("not found")
+		err = domain.MakeError(domain.ShortNotFound, "")
 	}
 	return tu, err
 }

+ 4 - 5
infrastructure/mysql.go

@@ -3,7 +3,6 @@ package infrastructure
 import (
 	"code.osinet.fr/fgm/kurz/domain"
 	"database/sql"
-	"errors"
 )
 
 type MySQLShortURLRepository struct {
@@ -24,11 +23,11 @@ WHERE map.hash = ?
 	err := row.Scan(&tu.URL)
 	switch err {
 	case sql.ErrNoRows:
-		err = errors.New("target not found")
+		err = domain.MakeError(domain.ShortNotFound, string(su.URL))
 	case nil:
 		break
 	default:
-		err = errors.New("storage read error")
+		err = domain.MakeError(domain.StorageReadError, "")
 	}
 	return tu, err
 }
@@ -56,7 +55,7 @@ INSERT INTO map(hash, url, date1, date2, date3, refcount)
 VALUES (?, ?, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), 0)
 `, su.URL, tu.URL)
 		if err != nil {
-			err = errors.New("storage write error")
+			err = domain.MakeError(domain.StorageWriteError, "storing new mapping")
 		}
 		isNew = true
 
@@ -64,7 +63,7 @@ VALUES (?, ?, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), 0)
 		break
 
 	default:
-		err = errors.New("storage read error")
+		err = domain.MakeError(domain.StorageReadError, "looking for mapping")
 	}
 
 	return