Compare commits

..

5 Commits

Author SHA1 Message Date
2f1b784dc2 v0.0.219 implement error.Is(*) for exerr 2023-07-28 15:42:12 +02:00
190584e0e6 v0.0.218 bf 2023-07-27 17:16:30 +02:00
b7003b9ec9 v0.0.217 2023-07-27 17:12:41 +02:00
4f871271e8 v0.0.216 2023-07-27 17:00:53 +02:00
91f4793678 v0.0.215 Add (ee *ExErr) ToAPIJson 2023-07-27 14:37:11 +02:00
6 changed files with 96 additions and 30 deletions

View File

@@ -22,7 +22,7 @@ type ExErr struct {
WrappedErrType string `json:"wrappedErrType"` WrappedErrType string `json:"wrappedErrType"`
Caller string `json:"caller"` Caller string `json:"caller"`
OriginalError *ExErr OriginalError *ExErr `json:"originalError"`
Meta MetaMap `json:"meta"` Meta MetaMap `json:"meta"`
} }
@@ -31,10 +31,16 @@ func (ee *ExErr) Error() string {
return ee.Message return ee.Message
} }
// Unwrap must be implemented so that some error.XXX methods work
func (ee *ExErr) Unwrap() error { func (ee *ExErr) Unwrap() error {
return ee.OriginalError return ee.OriginalError
} }
// Is must be implemented so that error.Is(x) works
func (ee *ExErr) Is(e error) bool {
return IsFrom(ee, e)
}
func (ee *ExErr) Log(evt *zerolog.Event) { func (ee *ExErr) Log(evt *zerolog.Event) {
evt.Msg(ee.FormatLog(LogPrintFull)) evt.Msg(ee.FormatLog(LogPrintFull))
} }

View File

@@ -3,12 +3,13 @@ package exerr
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
json "gogs.mikescher.com/BlackForestBytes/goext/gojson" json "gogs.mikescher.com/BlackForestBytes/goext/gojson"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"net/http" "net/http"
"time" "time"
) )
func (ee *ExErr) toJson(depth int) gin.H { func (ee *ExErr) toJson(depth int, applyExtendListener bool) langext.H {
ginJson := gin.H{} ginJson := langext.H{}
if ee.UniqueID != "" { if ee.UniqueID != "" {
ginJson["id"] = ee.UniqueID ginJson["id"] = ee.UniqueID
@@ -38,21 +39,51 @@ func (ee *ExErr) toJson(depth int) gin.H {
ginJson["wrappedErrType"] = ee.WrappedErrType ginJson["wrappedErrType"] = ee.WrappedErrType
} }
if ee.OriginalError != nil { if ee.OriginalError != nil {
ginJson["original"] = ee.OriginalError.toJson(depth + 1) ginJson["original"] = ee.OriginalError.toJson(depth+1, applyExtendListener)
} }
pkgconfig.ExtendGinDataOutput(ee, depth, ginJson) if applyExtendListener {
pkgconfig.ExtendGinDataOutput(ee, depth, ginJson)
}
return ginJson return ginJson
} }
// ToAPIJson converts the ExError to a json object
// (the same object as used in the Output(gin) method)
//
// Parameters:
// - [applyExtendListener]: if false the pkgconfig.ExtendGinOutput / pkgconfig.ExtendGinDataOutput will not be applied
// - [includeWrappedErrors]: if false we do not include the recursive/wrapped errors in `__data`
func (ee *ExErr) ToAPIJson(applyExtendListener bool, includeWrappedErrors bool) langext.H {
apiOutput := langext.H{
"errorid": ee.UniqueID,
"message": ee.RecursiveMessage(),
"errorcode": ee.RecursiveType().Key,
"category": ee.RecursiveCategory().Category,
}
if includeWrappedErrors {
apiOutput["__data"] = ee.toJson(0, applyExtendListener)
}
if applyExtendListener {
pkgconfig.ExtendGinOutput(ee, apiOutput)
}
return apiOutput
}
func (ee *ExErr) Output(g *gin.Context) { func (ee *ExErr) Output(g *gin.Context) {
warnOnPkgConfigNotInitialized()
var statuscode = http.StatusInternalServerError var statuscode = http.StatusInternalServerError
var baseCat = ee.RecursiveCategory() var baseCat = ee.RecursiveCategory()
var baseType = ee.RecursiveType() var baseType = ee.RecursiveType()
var baseStatuscode = ee.RecursiveStatuscode() var baseStatuscode = ee.RecursiveStatuscode()
var baseMessage = ee.RecursiveMessage()
if baseCat == CatUser { if baseCat == CatUser {
statuscode = http.StatusBadRequest statuscode = http.StatusBadRequest
@@ -66,20 +97,7 @@ func (ee *ExErr) Output(g *gin.Context) {
statuscode = *baseType.DefaultStatusCode statuscode = *baseType.DefaultStatusCode
} }
warnOnPkgConfigNotInitialized() ginOutput := ee.ToAPIJson(true, pkgconfig.ExtendedGinOutput)
ginOutput := gin.H{
"errorid": ee.UniqueID,
"message": baseMessage,
"errorcode": baseType.Key,
"category": baseCat.Category,
}
if pkgconfig.ExtendedGinOutput {
ginOutput["__data"] = ee.toJson(0)
}
pkgconfig.ExtendGinOutput(ee, ginOutput)
g.Render(statuscode, json.GoJsonRender{Data: ginOutput, NilSafeSlices: true, NilSafeMaps: true}) g.Render(statuscode, json.GoJsonRender{Data: ginOutput, NilSafeSlices: true, NilSafeMaps: true})
} }

View File

@@ -24,6 +24,8 @@ func IsFrom(e error, original error) bool {
if e == nil { if e == nil {
return false return false
} }
//goland:noinspection GoDirectComparisonOfErrors
if e == original { if e == original {
return true return true
} }

View File

@@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.214" const GoextVersion = "0.0.219"
const GoextVersionTimestamp = "2023-07-27T09:58:10+0200" const GoextVersionTimestamp = "2023-07-28T15:42:12+0200"

View File

@@ -39,7 +39,7 @@ func HashSqliteSchema(ctx context.Context, schemaStr string) (string, error) {
return HashSqliteDatabase(ctx, db) return HashSqliteDatabase(ctx, db)
} }
func HashSqliteDatabase(ctx context.Context, db DB) (string, error) { func HashSqliteDatabase(ctx context.Context, db Queryable) (string, error) {
ss, err := CreateSqliteDatabaseSchemaString(ctx, db) ss, err := CreateSqliteDatabaseSchemaString(ctx, db)
if err != nil { if err != nil {
return "", err return "", err
@@ -50,7 +50,7 @@ func HashSqliteDatabase(ctx context.Context, db DB) (string, error) {
return hex.EncodeToString(cs[:]), nil return hex.EncodeToString(cs[:]), nil
} }
func CreateSqliteDatabaseSchemaString(ctx context.Context, db DB) (string, error) { func CreateSqliteDatabaseSchemaString(ctx context.Context, db Queryable) (string, error) {
type colInfo struct { type colInfo struct {
Name string `db:"name"` Name string `db:"name"`

View File

@@ -7,24 +7,40 @@ import (
"gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/langext"
) )
type TxStatus string
const (
TxStatusInitial TxStatus = "INITIAL"
TxStatusActive TxStatus = "ACTIVE"
TxStatusComitted TxStatus = "COMMITTED"
TxStatusRollback TxStatus = "ROLLBACK"
)
type Tx interface { type Tx interface {
Rollback() error Rollback() error
Commit() error Commit() error
Status() TxStatus
Exec(ctx context.Context, sql string, prep PP) (sql.Result, error) Exec(ctx context.Context, sql string, prep PP) (sql.Result, error)
Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error) Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error)
} }
type transaction struct { type transaction struct {
tx *sqlx.Tx tx *sqlx.Tx
id uint16 id uint16
lstr []Listener lstr []Listener
status TxStatus
execCtr int
queryCtr int
} }
func NewTransaction(xtx *sqlx.Tx, txid uint16, lstr []Listener) Tx { func NewTransaction(xtx *sqlx.Tx, txid uint16, lstr []Listener) Tx {
return &transaction{ return &transaction{
tx: xtx, tx: xtx,
id: txid, id: txid,
lstr: lstr, lstr: lstr,
status: TxStatusInitial,
execCtr: 0,
queryCtr: 0,
} }
} }
@@ -38,6 +54,10 @@ func (tx *transaction) Rollback() error {
result := tx.tx.Rollback() result := tx.tx.Rollback()
if result == nil {
tx.status = TxStatusRollback
}
for _, v := range tx.lstr { for _, v := range tx.lstr {
v.PostTxRollback(tx.id, result) v.PostTxRollback(tx.id, result)
} }
@@ -55,6 +75,10 @@ func (tx *transaction) Commit() error {
result := tx.tx.Commit() result := tx.tx.Commit()
if result == nil {
tx.status = TxStatusComitted
}
for _, v := range tx.lstr { for _, v := range tx.lstr {
v.PostTxRollback(tx.id, result) v.PostTxRollback(tx.id, result)
} }
@@ -73,6 +97,10 @@ func (tx *transaction) Exec(ctx context.Context, sqlstr string, prep PP) (sql.Re
res, err := tx.tx.NamedExecContext(ctx, sqlstr, prep) res, err := tx.tx.NamedExecContext(ctx, sqlstr, prep)
if tx.status == TxStatusInitial && err == nil {
tx.status = TxStatusActive
}
for _, v := range tx.lstr { for _, v := range tx.lstr {
v.PostExec(langext.Ptr(tx.id), origsql, sqlstr, prep) v.PostExec(langext.Ptr(tx.id), origsql, sqlstr, prep)
} }
@@ -94,6 +122,10 @@ func (tx *transaction) Query(ctx context.Context, sqlstr string, prep PP) (*sqlx
rows, err := sqlx.NamedQueryContext(ctx, tx.tx, sqlstr, prep) rows, err := sqlx.NamedQueryContext(ctx, tx.tx, sqlstr, prep)
if tx.status == TxStatusInitial && err == nil {
tx.status = TxStatusActive
}
for _, v := range tx.lstr { for _, v := range tx.lstr {
v.PostQuery(langext.Ptr(tx.id), origsql, sqlstr, prep) v.PostQuery(langext.Ptr(tx.id), origsql, sqlstr, prep)
} }
@@ -103,3 +135,11 @@ func (tx *transaction) Query(ctx context.Context, sqlstr string, prep PP) (*sqlx
} }
return rows, nil return rows, nil
} }
func (tx *transaction) Status() TxStatus {
return tx.status
}
func (tx *transaction) Traffic() (int, int) {
return tx.execCtr, tx.queryCtr
}