Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
2f1b784dc2
|
|||
190584e0e6
|
|||
b7003b9ec9
|
|||
4f871271e8
|
|||
91f4793678
|
|||
3b30bb049e | |||
f0c5b36ea9 | |||
647ec64c3b
|
@@ -31,13 +31,13 @@ type EnumDef struct {
|
||||
Values []EnumDefVal
|
||||
}
|
||||
|
||||
var rexPackage = rext.W(regexp.MustCompile("^package\\s+(?P<name>[A-Za-z0-9_]+)\\s*$"))
|
||||
var rexPackage = rext.W(regexp.MustCompile(`^package\s+(?P<name>[A-Za-z0-9_]+)\s*$`))
|
||||
|
||||
var rexEnumDef = rext.W(regexp.MustCompile("^\\s*type\\s+(?P<name>[A-Za-z0-9_]+)\\s+(?P<type>[A-Za-z0-9_]+)\\s*//\\s*(@enum:type).*$"))
|
||||
var rexEnumDef = rext.W(regexp.MustCompile(`^\s*type\s+(?P<name>[A-Za-z0-9_]+)\s+(?P<type>[A-Za-z0-9_]+)\s*//\s*(@enum:type).*$`))
|
||||
|
||||
var rexValueDef = rext.W(regexp.MustCompile("^\\s*(?P<name>[A-Za-z0-9_]+)\\s+(?P<type>[A-Za-z0-9_]+)\\s*=\\s*(?P<value>(\"[A-Za-z0-9_:]+\"|[0-9]+))\\s*(//(?P<descr>.*))?.*$"))
|
||||
var rexValueDef = rext.W(regexp.MustCompile(`^\s*(?P<name>[A-Za-z0-9_]+)\s+(?P<type>[A-Za-z0-9_]+)\s*=\s*(?P<value>("[A-Za-z0-9_:]+"|[0-9]+))\s*(//(?P<descr>.*))?.*$`))
|
||||
|
||||
var rexChecksumConst = rext.W(regexp.MustCompile("const ChecksumGenerator = \"(?P<cs>[A-Za-z0-9_]*)\""))
|
||||
var rexChecksumConst = rext.W(regexp.MustCompile(`const ChecksumGenerator = "(?P<cs>[A-Za-z0-9_]*)"`))
|
||||
|
||||
func GenerateEnumSpecs(sourceDir string, destFile string) error {
|
||||
|
||||
|
@@ -22,7 +22,7 @@ type ExErr struct {
|
||||
WrappedErrType string `json:"wrappedErrType"`
|
||||
Caller string `json:"caller"`
|
||||
|
||||
OriginalError *ExErr
|
||||
OriginalError *ExErr `json:"originalError"`
|
||||
|
||||
Meta MetaMap `json:"meta"`
|
||||
}
|
||||
@@ -31,10 +31,16 @@ func (ee *ExErr) Error() string {
|
||||
return ee.Message
|
||||
}
|
||||
|
||||
// Unwrap must be implemented so that some error.XXX methods work
|
||||
func (ee *ExErr) Unwrap() error {
|
||||
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) {
|
||||
evt.Msg(ee.FormatLog(LogPrintFull))
|
||||
}
|
||||
|
56
exerr/gin.go
56
exerr/gin.go
@@ -3,12 +3,13 @@ package exerr
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
json "gogs.mikescher.com/BlackForestBytes/goext/gojson"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (ee *ExErr) toJson(depth int) gin.H {
|
||||
ginJson := gin.H{}
|
||||
func (ee *ExErr) toJson(depth int, applyExtendListener bool) langext.H {
|
||||
ginJson := langext.H{}
|
||||
|
||||
if ee.UniqueID != "" {
|
||||
ginJson["id"] = ee.UniqueID
|
||||
@@ -38,21 +39,51 @@ func (ee *ExErr) toJson(depth int) gin.H {
|
||||
ginJson["wrappedErrType"] = ee.WrappedErrType
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
warnOnPkgConfigNotInitialized()
|
||||
|
||||
var statuscode = http.StatusInternalServerError
|
||||
|
||||
var baseCat = ee.RecursiveCategory()
|
||||
var baseType = ee.RecursiveType()
|
||||
var baseStatuscode = ee.RecursiveStatuscode()
|
||||
var baseMessage = ee.RecursiveMessage()
|
||||
|
||||
if baseCat == CatUser {
|
||||
statuscode = http.StatusBadRequest
|
||||
@@ -66,20 +97,7 @@ func (ee *ExErr) Output(g *gin.Context) {
|
||||
statuscode = *baseType.DefaultStatusCode
|
||||
}
|
||||
|
||||
warnOnPkgConfigNotInitialized()
|
||||
|
||||
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)
|
||||
ginOutput := ee.ToAPIJson(true, pkgconfig.ExtendedGinOutput)
|
||||
|
||||
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 {
|
||||
return false
|
||||
}
|
||||
|
||||
//goland:noinspection GoDirectComparisonOfErrors
|
||||
if e == original {
|
||||
return true
|
||||
}
|
||||
|
@@ -14,6 +14,9 @@ type AppContext struct {
|
||||
}
|
||||
|
||||
func CreateAppContext(g *gin.Context, innerCtx context.Context, cancelFn context.CancelFunc) *AppContext {
|
||||
for key, value := range g.Keys {
|
||||
innerCtx = context.WithValue(innerCtx, key, value)
|
||||
}
|
||||
return &AppContext{
|
||||
inner: innerCtx,
|
||||
cancelFunc: cancelFn,
|
||||
@@ -38,6 +41,10 @@ func (ac *AppContext) Value(key any) any {
|
||||
return ac.inner.Value(key)
|
||||
}
|
||||
|
||||
func (ac *AppContext) Set(key, value any) {
|
||||
ac.inner = context.WithValue(ac.inner, key, value)
|
||||
}
|
||||
|
||||
func (ac *AppContext) Cancel() {
|
||||
ac.cancelled = true
|
||||
ac.cancelFunc()
|
||||
|
@@ -162,7 +162,7 @@ func nameOfFunction(f any) string {
|
||||
fname = fname[:len(fname)-len("-fm")]
|
||||
}
|
||||
|
||||
suffix := rext.W(regexp.MustCompile("\\.func[0-9]+$"))
|
||||
suffix := rext.W(regexp.MustCompile(`\.func[0-9]+(?:\.[0-9]+)*$`))
|
||||
|
||||
if match, ok := suffix.MatchFirst(fname); ok {
|
||||
fname = fname[:len(fname)-match.FullMatch().Length()]
|
||||
|
@@ -1,5 +1,5 @@
|
||||
package goext
|
||||
|
||||
const GoextVersion = "0.0.211"
|
||||
const GoextVersion = "0.0.219"
|
||||
|
||||
const GoextVersionTimestamp = "2023-07-26T10:40:42+0200"
|
||||
const GoextVersionTimestamp = "2023-07-28T15:42:12+0200"
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
|
||||
func TestGroupByNameOrEmpty1(t *testing.T) {
|
||||
|
||||
regex1 := W(regexp.MustCompile("0(?P<group1>A+)B(?P<group2>C+)0"))
|
||||
regex1 := W(regexp.MustCompile(`0(?P<group1>A+)B(?P<group2>C+)0`))
|
||||
|
||||
match1, ok1 := regex1.MatchFirst("Hello 0AAAABCCC0 Bye.")
|
||||
|
||||
@@ -26,7 +26,7 @@ func TestGroupByNameOrEmpty1(t *testing.T) {
|
||||
|
||||
func TestGroupByNameOrEmpty2(t *testing.T) {
|
||||
|
||||
regex1 := W(regexp.MustCompile("0(?P<group1>A+)B(?P<group2>C+)(?P<group3>C+)?0"))
|
||||
regex1 := W(regexp.MustCompile(`0(?P<group1>A+)B(?P<group2>C+)(?P<group3>C+)?0`))
|
||||
|
||||
match1, ok1 := regex1.MatchFirst("Hello 0AAAABCCC0 Bye.")
|
||||
|
||||
|
@@ -39,7 +39,7 @@ func HashSqliteSchema(ctx context.Context, schemaStr string) (string, error) {
|
||||
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)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -50,7 +50,7 @@ func HashSqliteDatabase(ctx context.Context, db DB) (string, error) {
|
||||
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 {
|
||||
Name string `db:"name"`
|
||||
|
@@ -7,24 +7,40 @@ import (
|
||||
"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 {
|
||||
Rollback() error
|
||||
Commit() error
|
||||
Status() TxStatus
|
||||
Exec(ctx context.Context, sql string, prep PP) (sql.Result, error)
|
||||
Query(ctx context.Context, sql string, prep PP) (*sqlx.Rows, error)
|
||||
}
|
||||
|
||||
type transaction struct {
|
||||
tx *sqlx.Tx
|
||||
id uint16
|
||||
lstr []Listener
|
||||
tx *sqlx.Tx
|
||||
id uint16
|
||||
lstr []Listener
|
||||
status TxStatus
|
||||
execCtr int
|
||||
queryCtr int
|
||||
}
|
||||
|
||||
func NewTransaction(xtx *sqlx.Tx, txid uint16, lstr []Listener) Tx {
|
||||
return &transaction{
|
||||
tx: xtx,
|
||||
id: txid,
|
||||
lstr: lstr,
|
||||
tx: xtx,
|
||||
id: txid,
|
||||
lstr: lstr,
|
||||
status: TxStatusInitial,
|
||||
execCtr: 0,
|
||||
queryCtr: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +54,10 @@ func (tx *transaction) Rollback() error {
|
||||
|
||||
result := tx.tx.Rollback()
|
||||
|
||||
if result == nil {
|
||||
tx.status = TxStatusRollback
|
||||
}
|
||||
|
||||
for _, v := range tx.lstr {
|
||||
v.PostTxRollback(tx.id, result)
|
||||
}
|
||||
@@ -55,6 +75,10 @@ func (tx *transaction) Commit() error {
|
||||
|
||||
result := tx.tx.Commit()
|
||||
|
||||
if result == nil {
|
||||
tx.status = TxStatusComitted
|
||||
}
|
||||
|
||||
for _, v := range tx.lstr {
|
||||
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)
|
||||
|
||||
if tx.status == TxStatusInitial && err == nil {
|
||||
tx.status = TxStatusActive
|
||||
}
|
||||
|
||||
for _, v := range tx.lstr {
|
||||
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)
|
||||
|
||||
if tx.status == TxStatusInitial && err == nil {
|
||||
tx.status = TxStatusActive
|
||||
}
|
||||
|
||||
for _, v := range tx.lstr {
|
||||
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
|
||||
}
|
||||
|
||||
func (tx *transaction) Status() TxStatus {
|
||||
return tx.status
|
||||
}
|
||||
|
||||
func (tx *transaction) Traffic() (int, int) {
|
||||
return tx.execCtr, tx.queryCtr
|
||||
}
|
||||
|
@@ -71,12 +71,12 @@ func SupportsColors() bool {
|
||||
}
|
||||
}
|
||||
|
||||
var term256Regex = regexp.MustCompile("(?i)-256(color)?$")
|
||||
var term256Regex = regexp.MustCompile(`(?i)-256(color)?$`)
|
||||
if term256Regex.MatchString(termenv) {
|
||||
return true
|
||||
}
|
||||
|
||||
var termBasicRegex = regexp.MustCompile("(?i)^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux")
|
||||
var termBasicRegex = regexp.MustCompile(`(?i)^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux`)
|
||||
|
||||
if termBasicRegex.MatchString(termenv) {
|
||||
return true
|
||||
|
Reference in New Issue
Block a user