Skip to content

Commit

Permalink
若干调整
Browse files Browse the repository at this point in the history
  • Loading branch information
glennliao committed Mar 28, 2024
1 parent cf16a4e commit c368634
Show file tree
Hide file tree
Showing 49 changed files with 2,055 additions and 1,168 deletions.
172 changes: 19 additions & 153 deletions action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,19 @@ package action

import (
"context"
"strings"

"github.com/glennliao/apijson-go/config"
"github.com/glennliao/apijson-go/consts"
"github.com/glennliao/apijson-go/model"
"github.com/glennliao/apijson-go/query"
"github.com/glennliao/apijson-go/util"
"github.com/gogf/gf/v2/util/gconv"
)

// Action 非get查询的request表中的请求
type Action struct {
ctx context.Context
tagRequest *config.RequestConfig
method string

ctx context.Context
err error
req model.Map
ret model.Map

err error
Method string
tagRequestConfig *config.RequestConfig

children map[string]*Node
keyNode map[string]*Node
Expand All @@ -30,173 +24,45 @@ type Action struct {
// 关闭 request 验证开关, 默认否
NoRequestVerify bool

// Access *config.Access

// dbFieldStyle 数据库字段命名风格 请求传递到数据库中
DbFieldStyle config.FieldStyle

// jsonFieldStyle 数据库返回的字段
JsonFieldStyle config.FieldStyle

ActionConfig *config.ActionConfig

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

ret model.Map
}

func New(ctx context.Context, actionConfig *config.ActionConfig, method string, req model.Map) *Action {

request, err := checkTag(req, method, actionConfig)
if err != nil {
return &Action{
err: err,
}
}

delete(req, consts.Tag)
delete(req, consts.Version)

a := &Action{
ctx: ctx,
tagRequest: request,
method: method,
req: req,
children: map[string]*Node{},
keyNode: map[string]*Node{},
Method: method,
ActionConfig: actionConfig,
}
return a
}

func (a *Action) parse() error {

if a.err != nil {
return a.err
}

structures := a.tagRequest.Structure

for key, v := range a.req {

structuresKey := key
if strings.HasSuffix(key, consts.ListKeySuffix) {
structuresKey = util.RemoveSuffix(key, consts.ListKeySuffix)
}

structure, ok := structures[key]
if !ok {
if structure, ok = structures[structuresKey]; !ok { // User[]可读取User或者User[]
return consts.NewStructureKeyNoFoundErr(key)
}
}

var list []model.Map
_v, ok := v.(model.Map)
if ok { // 将所有node都假设成列表, 如果单个则看成一个元素的批量
list = []model.Map{_v}
} else {
for _, m := range gconv.Maps(v) {
list = append(list, m)
}
}

node := newNode(key, list, structure, a.tagRequest.Executor[key])
node.ctx = a.ctx
node.Action = a
a.keyNode[key] = &node
node.keyNode = a.keyNode
err := node.parse(a.ctx, a.method)
if err != nil {
return err
}

a.children[key] = &node
}

return nil
}

func (a *Action) hookExecute(i int, inTransaction bool) error {
k := a.tagRequest.ExecQueue[i]
node := a.children[k]
nodeHookReq := &HookReq{
Node: node,
Method: a.method,
ctx: a.ctx,
nextIdx: -1,
isInTransaction: inTransaction,
hooks: getHooksByAccessName(a.HooksMap, k),
}

nodeHookReq.handler = func(ctx context.Context, n *Node, method string) error {

if i+1 < len(a.tagRequest.ExecQueue) {
return a.hookExecute(i+1, inTransaction)
}

// 执行完了普通hook的before,开始执行事务内
if !inTransaction {

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 err
}
transactionHandler = h
}

err := transactionHandler(a.ctx, func(ctx context.Context) error {
return a.hookExecute(0, !inTransaction)
})

return err
}

var err error
a.ret[k], err = node.execute(ctx, a.method)
return err
}

err := nodeHookReq.Next()
return err
}

func (a *Action) Result() (model.Map, error) {

err := a.parse()
request, err := CheckTag(req, method, actionConfig)
if err != nil {
return nil, err
a.err = err
return a
}

a.ret = model.Map{}
a.tagRequestConfig = request

err = a.hookExecute(0, false)
if err != nil {
a.err = err
}
return a.ret, err
return a
}

func checkTag(req model.Map, method string, requestCfg *config.ActionConfig) (*config.RequestConfig, error) {
_tag, ok := req[consts.Tag]
if !ok {
return nil, consts.ErrNoTag
func (a *Action) Result() (model.Map, error) {
if a.err != nil {
return nil, a.err
}

tag := gconv.String(_tag)
version := req[consts.Version]

request, err := requestCfg.GetRequest(tag, method, gconv.String(version))
if err != nil {
return nil, err
a.parse()
if a.err != nil {
return nil, a.err
}

return request, nil
a.exec()
return a.ret, a.err
}
79 changes: 79 additions & 0 deletions action/action_exec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package action

import (
"context"

"github.com/glennliao/apijson-go/model"

"github.com/glennliao/apijson-go/consts"
)

func (a *Action) exec() {
a.ret = model.Map{}
a.err = a.hookExecute(0, false)
}

// hook like middleware 洋葱模型
func (a *Action) hookExecute(i int, inTransaction bool) error {
var (
execNodeKey = a.tagRequestConfig.ExecQueue[i]
node = a.children[execNodeKey]
)

nodeHookReq := &HookReq{
ctx: a.ctx,
Node: node,
Method: a.Method,
nextId: -1,
isInTransaction: inTransaction,
hooks: getHooksByAccessName(a.HooksMap, execNodeKey),
}

nodeHookReq.handler = func(ctx context.Context, n *Node, method string) error {
if i+1 < len(a.tagRequestConfig.ExecQueue) {
return a.hookExecute(i+1, inTransaction)
}

// 执行完了普通hook的before,开始执行事务内
if !inTransaction {

transactionHandler := noTransactionHandler

if a.tagRequestConfig.Transaction != nil && *a.tagRequestConfig.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 {
return a.hookExecute(0, !inTransaction)
})

return err
}

// 执行完 全部前置hook
var err error

for _, name := range a.tagRequestConfig.ExecQueue {
node := a.children[name]
a.ret[name], err = node.execute(ctx, a.Method)
if err != nil {
return err
}
}

return err
}

err := nodeHookReq.Next()
return err
}

func getHooksByAccessName(hooksMap map[string][]*Hook, accessName string) []*Hook {
hooks := append(hooksMap["*"], hooksMap[accessName]...)
return hooks
}
40 changes: 40 additions & 0 deletions action/action_parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package action

import (
"github.com/glennliao/apijson-go/consts"
"github.com/gogf/gf/v2/util/gconv"
"github.com/samber/lo"
)

func (a *Action) parse() {
structures := a.tagRequestConfig.Structure

a.children = make(map[string]*Node)
a.keyNode = make(map[string]*Node)

for key, v := range a.req {

if lo.Contains([]string{consts.Tag, consts.Version}, key) {
continue
}

structure, ok := structures[key]
if !ok {
a.err = consts.NewStructureKeyNoFoundErr(key)
return
}

val := gconv.Map(v)

node := newNode(a, key, val, structure)

a.keyNode[key] = node
a.children[key] = node

err := node.parse()
if err != nil {
a.err = consts.NewStructureKeyNoFoundErr(key)
return
}
}
}
29 changes: 14 additions & 15 deletions action/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,26 @@ import (
"github.com/glennliao/apijson-go/config"
"github.com/glennliao/apijson-go/consts"
"github.com/glennliao/apijson-go/model"
"github.com/glennliao/apijson-go/query"
"github.com/samber/lo"
)

type ActionExecutorReq struct {
Method string
Table string
Data []model.Map
Where []model.Map
Access *config.AccessConfig
Config *config.ActionConfig
NewQuery func(ctx context.Context, req model.Map) *query.Query
type ExecutorReq struct {
Method string
Table string
Data model.Map
Where model.Map
AccessCondition *config.ConditionRet
Access *config.AccessConfig
Config *config.ActionConfig
}

var actionExecutorMap = map[string]ActionExecutor{}
var actionExecutorMap = map[string]Executor{}

func RegExecutor(name string, e ActionExecutor) {
func RegExecutor(name string, e Executor) {
actionExecutorMap[name] = e
}

func GetActionExecutor(name string) (ActionExecutor, error) {
func GetActionExecutor(name string) (Executor, error) {
if name == "" {
name = "default"
}
Expand All @@ -36,12 +35,12 @@ func GetActionExecutor(name string) (ActionExecutor, error) {
return nil, consts.NewSysErr("action executor not found: " + name)
}

func ActionExecutorList() []string {
func ExecutorList() []string {
return lo.Keys(actionExecutorMap)
}

type ActionExecutor interface {
Do(ctx context.Context, req ActionExecutorReq) (ret model.Map, err error)
type Executor interface {
Do(ctx context.Context, req ExecutorReq) (ret model.Map, err error)
}

// TransactionHandler 事务处理函数
Expand Down
Loading

0 comments on commit c368634

Please sign in to comment.