-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
361 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.