Skip to content

Commit

Permalink
## 0.2.0-beta12 -> 调整action.Hook
Browse files Browse the repository at this point in the history
  • Loading branch information
glennliao committed Jul 18, 2023
1 parent 48e52ed commit 2bbcb25
Show file tree
Hide file tree
Showing 20 changed files with 361 additions and 171 deletions.
74 changes: 37 additions & 37 deletions action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ type Action struct {

NewQuery func(ctx context.Context, req model.Map) *query.Query
NewAction func(ctx context.Context, method string, req model.Map) *Action

HooksMap map[string][]*Hook
}

func New(ctx context.Context, actionConfig *config.ActionConfig, method string, req model.Map) *Action {
Expand Down Expand Up @@ -127,58 +129,56 @@ func (a *Action) Result() (model.Map, error) {

for _, k := range a.tagRequest.ExecQueue {
node := a.children[k]
err = EmitHook(a.ctx, BeforeNodeExec, node, a.method)
if err != nil {
return nil, err
}
}

for _, k := range a.tagRequest.ExecQueue {

node := a.children[k]
err = node.reqUpdate()
if err != nil {
return nil, err
actionHookReq := &HookReq{
Node: node,
Method: a.method,
ctx: a.ctx,
nextIdx: -1,
isInTransaction: false,
hooks: getHooksByAccessName(a.HooksMap, k),
}
}

transactionHandler := noTransactionHandler

if a.tagRequest.Transaction != nil && *a.tagRequest.Transaction == true {
h := GetTransactionHandler(a.ctx, a)
if h == nil {
err = consts.NewSysErr("transaction handler is nil")
return nil, err
}
actionHookReq.handler = func(ctx context.Context, n *Node, method string) error {
transactionHandler := noTransactionHandler

transactionHandler = h
if a.tagRequest.Transaction != nil && *a.tagRequest.Transaction == true {
h := GetTransactionHandler(a.ctx, a)
if h == nil {
err = consts.NewSysErr("transaction handler is nil")
return err
}

}
transactionHandler = h

err = transactionHandler(a.ctx, func(ctx context.Context) error {
for _, k := range a.tagRequest.ExecQueue {
node := a.children[k]
ret[k], err = node.execute(ctx, a.method)
if err != nil {
return err
}

err = transactionHandler(a.ctx, func(ctx context.Context) error {
for _, k := range a.tagRequest.ExecQueue {
node := a.children[k]
ret[k], err = node.execute(ctx, a.method)
if err != nil {
return err
}
}
return nil
})

return err
}
return nil
})

if err != nil {
return nil, err
}
err = node.reqUpdate()
if err != nil {
return nil, err
}

for _, k := range a.tagRequest.ExecQueue {
node := a.children[k]
err = EmitHook(a.ctx, AfterNodeExec, node, a.method)
err := actionHookReq.Next()
if err != nil {
return nil, err
}
}

return ret, err
return ret, nil
}

func checkTag(req model.Map, method string, requestCfg *config.ActionConfig) (*config.RequestConfig, error) {
Expand Down
162 changes: 121 additions & 41 deletions action/hook.go
Original file line number Diff line number Diff line change
@@ -1,56 +1,136 @@
package action

import "context"

const (
BeforeNodeExec = iota
AfterNodeExec
BeforeExecutorDo
AfterExecutorDo
import (
"context"
"net/http"
)

type Hook struct {
For []string //
// Exec 事务外
BeforeNodeExec func(ctx context.Context, n *Node, method string) error
AfterNodeExec func(ctx context.Context, n *Node, method string) error

// Do 事务内
BeforeExecutorDo func(ctx context.Context, n *Node, method string) error
AfterExecutorDo func(ctx context.Context, n *Node, method string) error
// const (
// BeforeNodeExec = iota
// AfterNodeExec
// BeforeExecutorDo
// AfterExecutorDo
// )

type HookReq struct {
Node *Node
Method string
ctx context.Context
hooks []*Hook
nextIdx int
isInTransaction bool
handler finishHandler
}

var hooksMap = map[string][]Hook{}
func (r *HookReq) IsPost() bool {
return r.Method == http.MethodPost
}

func RegHook(h Hook) {
for _, item := range h.For {
hooksMap[item] = append(hooksMap[item], h)
}
func (r *HookReq) IsPut() bool {
return r.Method == http.MethodPut
}

func (r *HookReq) IsDelete() bool {
return r.Method == http.MethodDelete
}

func EmitHook(ctx context.Context, hookAt int, node *Node, method string) error {

hooks := append(hooksMap["*"], hooksMap[node.Key]...)
for _, hook := range hooks {

var handler func(ctx context.Context, n *Node, method string) error
switch hookAt {
case BeforeNodeExec:
handler = hook.BeforeNodeExec
case AfterNodeExec:
handler = hook.AfterNodeExec
case BeforeExecutorDo:
handler = hook.BeforeExecutorDo
case AfterExecutorDo:
handler = hook.AfterExecutorDo
func (r *HookReq) Next() error {

for {

var h *Hook

for r.nextIdx < len(r.hooks) && h == nil {

if r.nextIdx+1 >= len(r.hooks) {
if r.isInTransaction {
// finish all
return r.handler(r.ctx, r.Node, r.Method)
} else {
r.nextIdx = -1
r.isInTransaction = true
}
}

r.nextIdx++

_h := r.hooks[r.nextIdx]

if r.isInTransaction {
if _h.HandlerInTransaction == nil {
continue
}
h = _h
} else {
if _h.Handler == nil {
continue
}
h = _h
}

}

if handler != nil {
err := handler(ctx, node, method)
if err != nil {
return err
if r.nextIdx < len(r.hooks) {
if r.isInTransaction {
return h.HandlerInTransaction(r.ctx, r)
}

return h.Handler(r.ctx, r)
}
}
return nil

}

type Hook struct {
For []string
// 事务外 , 可执行参数校验,io等耗时操作
Handler func(ctx context.Context, req *HookReq) error
// 事务内,尽量少执行耗时操作 (无论request配置中是否开启事务, 都会先执行handler 然后 在范围内执行HandlerInTransaction)
HandlerInTransaction func(ctx context.Context, req *HookReq) error
}

type finishHandler func(ctx context.Context, n *Node, method string) error

func getHooksByAccessName(hooksMap map[string][]*Hook, accessName string) []*Hook {
hooks := append(hooksMap["*"], hooksMap[accessName]...)
return hooks
}

//
// type Hook2 struct {
// For []string //
// // Exec 事务外
// BeforeNodeExec func(ctx context.Context, n *Node, method string) error
// AfterNodeExec func(ctx context.Context, n *Node, method string) error
//
// // Do 事务内
// BeforeExecutorDo func(ctx context.Context, n *Node, method string) error
// AfterExecutorDo func(ctx context.Context, n *Node, method string) error
// }
//
// func emitHook(ctx context.Context, hooksMap map[string][]Hook, hookAt int, node *Node, method string) error {
//
// hooks := append(hooksMap["*"], hooksMap[node.Key]...)
// for _, hook := range hooks {
//
// var handler func(ctx context.Context, n *Node, method string) error
// switch hookAt {
// case BeforeNodeExec:
// handler = hook.BeforeNodeExec
// case AfterNodeExec:
// handler = hook.AfterNodeExec
// case BeforeExecutorDo:
// handler = hook.BeforeExecutorDo
// case AfterExecutorDo:
// handler = hook.AfterExecutorDo
// }
//
// if handler != nil {
// err := handler(ctx, node, method)
// if err != nil {
// return err
// }
// }
// }
// return nil
// }
18 changes: 4 additions & 14 deletions action/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,11 @@ func (n *Node) reqUpdate() error {

// call functions
{
queryConfig := n.Action.ActionConfig
actionConfig := n.Action.ActionConfig

functionName, paramKeys := util.ParseFunctionsStr(updateVal.(string))

_func := queryConfig.Func(functionName)
_func := actionConfig.Func(functionName)

param := model.Map{}
for paramI, item := range _func.ParamList {
Expand All @@ -279,7 +279,7 @@ func (n *Node) reqUpdate() error {
}
}

val, err := _func.Handler(n.ctx, param)
val, err := actionConfig.CallFunc(n.ctx, functionName, param)
if err != nil {
return err
}
Expand Down Expand Up @@ -327,11 +327,6 @@ func (n *Node) reqUpdateBeforeDo() error {

func (n *Node) do(ctx context.Context, method string) (ret model.Map, err error) {

err = EmitHook(ctx, BeforeExecutorDo, n, method)
if err != nil {
return nil, err
}

var rowKeyVal model.Map
var rowKey string

Expand All @@ -346,7 +341,7 @@ func (n *Node) do(ctx context.Context, method string) (ret model.Map, err error)
if access.RowKeyGen != "" {
for i, _ := range n.Data {

rowKeyVal, err = n.Action.ActionConfig.RowKeyGen(ctx, access.RowKeyGen, n.Key, n.Data[i])
rowKeyVal, err = n.Action.ActionConfig.RowKeyGen(ctx, access.RowKeyGen, n.Key, n.tableName, n.Data[i])
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -406,11 +401,6 @@ func (n *Node) do(ctx context.Context, method string) (ret model.Map, err error)

n.Ret = ret

err = EmitHook(ctx, AfterExecutorDo, n, method)
if err != nil {
return nil, err
}

return
}

Expand Down
14 changes: 14 additions & 0 deletions apijson.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ type ApiJson struct {
config *config.Config
Debug bool // 是否开启debug模式, 显示每步骤
ctx context.Context

actionHooks []action.Hook
actionHookMap map[string][]*action.Hook
}

var DefaultApiJson = New()
Expand Down Expand Up @@ -76,5 +79,16 @@ func (a *ApiJson) NewAction(ctx context.Context, method string, req model.Map) *

act.NewQuery = a.NewQuery

act.HooksMap = a.actionHookMap

return act
}

func (a *ApiJson) RegActionHook(hook action.Hook) {
if a.actionHookMap == nil {
a.actionHookMap = make(map[string][]*action.Hook)
}
for _, item := range hook.For {
a.actionHookMap[item] = append(a.actionHookMap[item], &hook)
}
}
Loading

0 comments on commit 2bbcb25

Please sign in to comment.