Skip to content

Commit

Permalink
Merge pull request #240 from trheyi/main
Browse files Browse the repository at this point in the history
Refactor error handling
  • Loading branch information
trheyi authored Dec 14, 2024
2 parents bd8f1e3 + e5ae01f commit 243ba71
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 21 deletions.
20 changes: 15 additions & 5 deletions api/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/yaoapp/gou/process"
"github.com/yaoapp/gou/session"
"github.com/yaoapp/gou/types"
"github.com/yaoapp/kun/exception"
"github.com/yaoapp/kun/maps"
)

Expand Down Expand Up @@ -55,26 +56,35 @@ func ProcessGuard(name string) gin.HandlerFunc {

process, err := process.Of(name, args...)
if err != nil {
c.JSON(400, gin.H{"code": 400, "message": fmt.Sprintf("Guard: %s %s", name, err.Error())})
c.JSON(500, gin.H{"code": 500, "message": "Guard process error: " + err.Error()})
c.Abort()
return
}

if sid, has := c.Get("__sid"); has { // 设定会话ID
if sid, has := c.Get("__sid"); has { // Set session id
if sid, ok := sid.(string); ok {
process.WithSID(sid)
}
}

if global, has := c.Get("__global"); has { // 设定全局变量
if global, has := c.Get("__global"); has { // Set global variables
if global, ok := global.(map[string]interface{}); ok {
process.WithGlobal(global)
}
}

v := process.Run()
err = process.Execute()
if err != nil {
ex := exception.New(err.Error(), 500)
c.JSON(ex.Code, gin.H{"code": ex.Code, "message": ex.Message})
c.Abort()
return
}
defer process.Release()

v := process.Value()
if data, ok := v.(map[string]interface{}); ok {
if sid, ok := data["__sid"].(string); ok {
if sid, ok := data["sid"].(string); ok {
c.Set("__sid", sid)
}

Expand Down
16 changes: 16 additions & 0 deletions connector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/connector/database"
"github.com/yaoapp/gou/connector/moapi"
mongo "github.com/yaoapp/gou/connector/mongo"
"github.com/yaoapp/gou/connector/openai"
"github.com/yaoapp/gou/connector/redis"
Expand Down Expand Up @@ -41,6 +42,17 @@ func Load(file string, id string) (Connector, error) {
return Connectors[id], nil
}

// New create a new connector
func New(typ string, id string, data []byte) (Connector, error) {
c, err := make(typ)
if err != nil {
return nil, err
}
c.Register(id, "__source__", data)
Connectors[id] = c
return Connectors[id], nil
}

// Select a connector
func Select(id string) (Connector, error) {
connector, has := Connectors[id]
Expand Down Expand Up @@ -82,6 +94,10 @@ func make(typ string) (Connector, error) {
case OPENAI:
c := &openai.Connector{}
return c, nil

case MOAPI:
c := &moapi.Connector{}
return c, nil
}

return nil, fmt.Errorf("%s does not support yet", typ)
Expand Down
78 changes: 78 additions & 0 deletions connector/moapi/moapi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package moapi

import (
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/helper"
"github.com/yaoapp/xun/dbal/query"
"github.com/yaoapp/xun/dbal/schema"
)

// Connector connector
type Connector struct {
id string
file string
Name string `json:"name"`
Options Options `json:"options"`
}

// Options the redis connector option
type Options struct {
Proxy string `json:"proxy,omitempty"`
Model string `json:"model,omitempty"`
Key string `json:"key"`
}

// Register the connections from dsl
func (o *Connector) Register(file string, id string, dsl []byte) error {
o.id = id
o.file = file
err := application.Parse(file, dsl, o)
if err != nil {
return err
}

o.Options.Proxy = helper.EnvString(o.Options.Proxy)
o.Options.Model = helper.EnvString(o.Options.Model)
o.Options.Key = helper.EnvString(o.Options.Key)
return nil
}

// Is the connections from dsl
func (o *Connector) Is(typ int) bool {
return 6 == typ || 8 == typ
}

// ID get connector id
func (o *Connector) ID() string {
return o.id
}

// Query get connector query interface
func (o *Connector) Query() (query.Query, error) {
return nil, nil
}

// Schema get connector schema interface
func (o *Connector) Schema() (schema.Schema, error) {
return nil, nil
}

// Close connections
func (o *Connector) Close() error {
return nil
}

// Setting get the connection setting
func (o *Connector) Setting() map[string]interface{} {

host := "https://api.moapi.ai"
if o.Options.Proxy != "" {
host = o.Options.Proxy
}

return map[string]interface{}{
"host": host,
"key": o.Options.Key,
"model": o.Options.Model,
}
}
4 changes: 4 additions & 0 deletions connector/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const (
// WEAVIATE the weaviate connector
WEAVIATE

// MOAPI the moapi connector
MOAPI

// SCRIPT ? the script connector ( difference with widget ?)
SCRIPT
)
Expand All @@ -45,6 +48,7 @@ var types = map[string]int{
"openai": OPENAI,
"weaviate": WEAVIATE,
"script": SCRIPT, // ?
"moapi": MOAPI,
}

// Connector the connector interface
Expand Down
26 changes: 25 additions & 1 deletion process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"strings"
"time"

"github.com/fatih/color"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/kun/exception"
)

Expand Down Expand Up @@ -57,7 +59,13 @@ func (process *Process) Execute() (err error) {
done := make(chan struct{})
go func() {
defer close(done)
defer func() { err = exception.Catch(recover()) }()
defer func() {
recovered := recover()
err = exception.Catch(recovered)
if err != nil {
exception.DebugPrint(err, "%s", process)
}
}()
value := hd(process)
process._val = &value
}()
Expand Down Expand Up @@ -195,6 +203,22 @@ func (process *Process) WithRuntime(runtime Runtime) *Process {
return process
}

// String the process as string
func (process Process) String() string {
args, _ := jsoniter.MarshalToString(process.Args)
global, _ := jsoniter.MarshalToString(process.Global)
return fmt.Sprintf("%s%s\n%s%s\n%s%s\n%s%s\n",
color.YellowString("Process: "),
color.WhiteString(process.Name),
color.YellowString("Sid: "),
color.WhiteString(process.Sid),
color.YellowString("Args: \n"),
color.WhiteString(args),
color.YellowString("Global: \n"),
color.WhiteString(global),
)
}

// handler get the process handler
func (process *Process) handler() (Handler, error) {
if hander, has := Handlers[process.Handler]; has && hander != nil {
Expand Down
5 changes: 2 additions & 3 deletions runtime/v8/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package v8
import (
"context"

"github.com/fatih/color"
"github.com/yaoapp/gou/runtime/v8/bridge"
"github.com/yaoapp/gou/runtime/v8/objects/console"
"github.com/yaoapp/kun/log"
Expand Down Expand Up @@ -45,7 +44,7 @@ func (context *Context) Call(method string, args ...interface{}) (interface{}, e
jsRes, err := global.MethodCall(method, bridge.Valuers(jsArgs)...)
if err != nil {
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e, context.SourceRoots))
PrintException(method, args, e, context.SourceRoots)
}
log.Error("%s.%s %s", context.ID, method, err.Error())
return nil, err
Expand Down Expand Up @@ -111,7 +110,7 @@ func (context *Context) CallWith(ctx context.Context, method string, args ...int
jsRes, err := global.MethodCall(method, bridge.Valuers(jsArgs)...)
if err != nil {
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e, context.SourceRoots))
PrintException(method, args, e, context.SourceRoots)
}
errChan <- err
return
Expand Down
3 changes: 1 addition & 2 deletions runtime/v8/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"strings"
"time"

"github.com/fatih/color"
"github.com/google/uuid"
"github.com/yaoapp/gou/runtime/v8/bridge"
"github.com/yaoapp/gou/runtime/v8/objects/console"
Expand Down Expand Up @@ -230,7 +229,7 @@ func (runner *Runner) _exec() {
jsRes, err := global.MethodCall(runner.method, bridge.Valuers(jsArgs)...)
if err != nil {
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e, runner.script.SourceRoots))
PrintException(runner.method, runner.args, e, runner.script.SourceRoots)
}
runner.chResp <- err
return
Expand Down
3 changes: 1 addition & 2 deletions runtime/v8/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"time"

"github.com/evanw/esbuild/pkg/api"
"github.com/fatih/color"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/gou/process"
"github.com/yaoapp/gou/runtime/v8/bridge"
Expand Down Expand Up @@ -658,7 +657,7 @@ func (script *Script) execStandard(process *process.Process) interface{} {

// Debug output the error stack
if e, ok := err.(*v8go.JSError); ok {
color.Red("%s\n\n", StackTrace(e, script.SourceRoots))
PrintException(process.Method, process.Args, e, script.SourceRoots)
}

log.Error("scripts.%s.%s %s", script.ID, process.Method, err.Error())
Expand Down
26 changes: 21 additions & 5 deletions runtime/v8/sourcemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import (
"strconv"
"strings"

"github.com/fatih/color"
"github.com/go-sourcemap/sourcemap"
jsoniter "github.com/json-iterator/go"
"github.com/yaoapp/gou/application"
"github.com/yaoapp/kun/exception"
"rogchap.com/v8go"
)

Expand Down Expand Up @@ -65,13 +67,27 @@ func clearSourceMaps() {
SourceCodes = map[string][]byte{}
}

// PrintException print the exception
func PrintException(method string, args []interface{}, jserr *v8go.JSError, rootMapping interface{}) {

if runtimeOption.Debug {
ex := exception.New(jserr.Message, 500)
color.Red("\n----------------------------------")
color.Red("Script Exception: %s", fmt.Sprintf("%d %s", ex.Code, ex.Message))
color.Red("----------------------------------")

color.Red("%s\n", StackTrace(jserr, rootMapping))
fmt.Println(color.YellowString("\nMethod:"), color.WhiteString("%s", method))
color.Yellow("Args:")
raw, _ := jsoniter.MarshalToString(args)
color.White("%s\n", raw)
}
}

// StackTrace get the stack trace
func StackTrace(jserr *v8go.JSError, rootMapping interface{}) string {

// Production mode will not show the stack trace
if runtimeOption.Debug == false {
return jserr.Message
}
ex := exception.New(jserr.Message, 500)

// Development mode will show the stack trace
entries := parseStackTrace(jserr.StackTrace)
Expand All @@ -84,7 +100,7 @@ func StackTrace(jserr *v8go.JSError, rootMapping interface{}) string {
return err.Error() + "\n" + jserr.StackTrace
}

return fmt.Sprintf("%s\n%s", jserr.Message, output)
return fmt.Sprintf("%s\n%s", fmt.Sprintf("%d %s", ex.Code, ex.Message), output)
}

func (entry *StackLogEntry) String() string {
Expand Down
6 changes: 3 additions & 3 deletions runtime/v8/sourcemap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,15 @@ func TestStackTrace(t *testing.T) {

trace := StackTrace(e, nil)
assert.NotEmpty(t, trace)
assert.Contains(t, trace, "Exception|400: Error occurred")
assert.Contains(t, trace, "400 Error occurred")
assert.Contains(t, trace, "/scripts/runtime/ts/page.ts:12:2")
assert.Contains(t, trace, "/scripts/runtime/ts/lib/bar.ts:7:2")
assert.Contains(t, trace, "/scripts/runtime/ts/lib/err.ts:8:10")

// with source root
trace = StackTrace(e, map[string]string{"/scripts": "/iscripts"})
assert.NotEmpty(t, trace)
assert.Contains(t, trace, "Exception|400: Error occurred")
assert.Contains(t, trace, "400 Error occurred")
assert.Contains(t, trace, "/iscripts/runtime/ts/page.ts:12:2")
assert.Contains(t, trace, "/iscripts/runtime/ts/lib/bar.ts:7:2")
assert.Contains(t, trace, "/iscripts/runtime/ts/lib/err.ts:8:10")
Expand All @@ -87,7 +87,7 @@ func TestStackTrace(t *testing.T) {

trace = StackTrace(e, replace)
assert.NotEmpty(t, trace)
assert.Contains(t, trace, "Exception|400: Error occurred")
assert.Contains(t, trace, "400 Error occurred")
assert.Contains(t, trace, "/fscripts/runtime/ts/page.ts:12:2")
assert.Contains(t, trace, "/fscripts/runtime/ts/lib/bar.ts:7:2")
assert.Contains(t, trace, "/fscripts/runtime/ts/lib/err.ts:8:10")
Expand Down

0 comments on commit 243ba71

Please sign in to comment.