Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
2f1b784dc2
|
|||
190584e0e6
|
|||
b7003b9ec9
|
|||
4f871271e8
|
|||
91f4793678
|
@@ -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))
|
||||||
}
|
}
|
||||||
|
54
exerr/gin.go
54
exerr/gin.go
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if applyExtendListener {
|
||||||
pkgconfig.ExtendGinDataOutput(ee, depth, ginJson)
|
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})
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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"
|
||||||
|
@@ -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"`
|
||||||
|
@@ -7,9 +7,19 @@ 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)
|
||||||
}
|
}
|
||||||
@@ -18,6 +28,9 @@ 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 {
|
||||||
@@ -25,6 +38,9 @@ func NewTransaction(xtx *sqlx.Tx, txid uint16, lstr []Listener) Tx {
|
|||||||
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
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user