From 0662113a26b893da56ffbaee7f926f3be9728ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=97=AD?= Date: Thu, 31 Oct 2019 15:27:30 +0800 Subject: [PATCH] btsgen support dao interface --- tool/kratos-gen-bts/README.md | 2 + tool/kratos-gen-bts/header_template.go | 6 +-- tool/kratos-gen-bts/main.go | 52 ++++++++++++++++++-------- tool/kratos-gen-bts/multi_template.go | 6 ++- tool/kratos-gen-bts/none_template.go | 8 +++- tool/kratos-gen-bts/single_template.go | 6 ++- tool/kratos/tool_index.go | 2 +- 7 files changed, 59 insertions(+), 23 deletions(-) diff --git a/tool/kratos-gen-bts/README.md b/tool/kratos-gen-bts/README.md index 3e6ef48bb..82f6b0af2 100644 --- a/tool/kratos-gen-bts/README.md +++ b/tool/kratos-gen-bts/README.md @@ -36,6 +36,7 @@ dao里面需要有cache对象 代码会调用d.cache来新增缓存 | ---------------- | ------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | -nullcache | | 空指针对象(存正常业务不会出现的内容 id的话像是-1这样的) | &Demo{ID:-1} 或-1 或"null" | | -check_null_code | | 开启空缓存并且value为指针对象时必填 用于判断是否是空缓存 $来指代对象名 | `-check_null_code=$!=nil&&$.ID==-1 或 $ == -1` | +| -cache_err |continue| 缓存出错的时候的行为 continue: 继续执行 break: 抛出错误 方法返回|break| | -batch | | (限多key模板) 批量获取数据 每组大小 | 100 | | -max_group | | (限多key模板)批量获取数据 最大组数量 | 10 | | -batch_err | break | (限多key模板)批量获取数据回源错误的时候 降级继续请求(continue)还是直接返回(break) | break 或 continue | @@ -44,3 +45,4 @@ dao里面需要有cache对象 代码会调用d.cache来新增缓存 | -paging | false | (限单key模板)分页 数据源应返回2个值 第一个为对外数据 第二个为全量数据 用于新增缓存 | false | | -ignores | | 用于依赖的三个方法参数和主方法参数不一致的情况. 忽略方法的某些参数 用\|分隔方法逗号分隔参数 | pn,ps\|pn\|origin 表示"缓存获取"方法忽略pn,ps两个参数 回源方法忽略pn参数 加缓存方法忽略origin参数 | | -custom_method | false | 自定义方法名 \|分隔 缓存获取方法名\|回源方法名\|增加缓存方法名 | d.mc.AddDemo\|d.mysql.Demo\|d.mc.AddDemo | +| -struct_name | dao | 所属结构体名称 | Dao| \ No newline at end of file diff --git a/tool/kratos-gen-bts/header_template.go b/tool/kratos-gen-bts/header_template.go index 3d5d56292..5d130b132 100644 --- a/tool/kratos-gen-bts/header_template.go +++ b/tool/kratos-gen-bts/header_template.go @@ -24,9 +24,9 @@ NEWLINE {{if .EnableSingleFlight}} "golang.org/x/sync/singleflight" {{end}} ) -var ( - _ _bts -) +{{if .UseBTS}} +var _ _bts +{{end }} {{if .EnableSingleFlight}} var cacheSingleFlights = [SFCOUNT]*singleflight.Group{SFINIT} {{end }} diff --git a/tool/kratos-gen-bts/main.go b/tool/kratos-gen-bts/main.go index 66fc161d1..0261db11b 100644 --- a/tool/kratos-gen-bts/main.go +++ b/tool/kratos-gen-bts/main.go @@ -22,6 +22,7 @@ var ( singleFlight = flag.Bool("singleflight", false, "enable singleflight") nullCache = flag.String("nullcache", "", "null cache") checkNullCode = flag.String("check_null_code", "", "check null code") + cacheErr = flag.String("cache_err", "continue", "cache err to contine or break") batchSize = flag.Int("batch", 0, "batch size") batchErr = flag.String("batch_err", "break", "batch err to contine or break") maxGroup = flag.Int("max_group", 0, "max group size") @@ -29,18 +30,19 @@ var ( paging = flag.Bool("paging", false, "use paging in single template") ignores = flag.String("ignores", "", "ignore params") customMethod = flag.String("custom_method", "", "自定义方法名 |分隔: 缓存|回源|增加缓存") + structName = flag.String("struct_name", "dao", "struct name") numberTypes = []string{"int", "int8", "int16", "int32", "int64", "float32", "float64", "uint", "uint8", "uint16", "uint32", "uint64"} simpleTypes = []string{"int", "int8", "int16", "int32", "int64", "float32", "float64", "uint", "uint8", "uint16", "uint32", "uint64", "bool", "string", "[]byte"} - optionNames = []string{"singleflight", "nullcache", "check_null_code", "batch", "max_group", "sync", "paging", "ignores", "batch_err", "custom_method"} + optionNames = []string{"singleflight", "nullcache", "check_null_code", "batch", "max_group", "sync", "paging", "ignores", "batch_err", "custom_method", "cache_err", "struct_name"} optionNamesMap = map[string]bool{} + interfaceName string ) const ( - _interfaceName = "_bts" - _multiTpl = 1 - _singleTpl = 2 - _noneTpl = 3 + _multiTpl = 1 + _singleTpl = 2 + _noneTpl = 3 ) func resetFlag() { @@ -52,8 +54,10 @@ func resetFlag() { *sync = false *paging = false *batchErr = "break" + *cacheErr = "continue" *ignores = "" *customMethod = "" + *structName = "dao" } // options options @@ -91,6 +95,10 @@ type options struct { Comment string CustomMethod string IDName string + CacheErrContinue bool + StructName string + hasDec bool + UseBTS bool } func getOptions(opt *options, comment string) { @@ -108,6 +116,7 @@ func getOptions(opt *options, comment string) { os.Args = append(os.Args, arg) } } + opt.hasDec = true } resetFlag() flag.Parse() @@ -122,13 +131,15 @@ func getOptions(opt *options, comment string) { opt.GroupSize = *batchSize opt.MaxGroup = *maxGroup opt.CustomMethod = *customMethod + opt.CacheErrContinue = *cacheErr == "continue" + opt.StructName = *structName } func processList(s *pkg.Source, list *ast.Field) (opt options) { fset := s.Fset src := s.Src lines := strings.Split(src, "\n") - opt = options{Args: s.GetDef(_interfaceName), importPackages: s.Packages(list)} + opt = options{name: list.Names[0].Name, Args: s.GetDef(interfaceName), importPackages: s.Packages(list)} // get comment line := fset.Position(list.Pos()).Line - 3 if len(lines)-1 >= line { @@ -140,8 +151,11 @@ func processList(s *pkg.Source, list *ast.Field) (opt options) { line = fset.Position(list.Pos()).Line - 2 comment := lines[line] getOptions(&opt, comment) + if !opt.hasDec { + log.Printf("%s: 无声明 忽略此方法\n", opt.name) + return + } // get func - opt.name = list.Names[0].Name params := list.Type.(*ast.FuncType).Params.List if len(params) == 0 { log.Fatalln(opt.name + "参数不足") @@ -304,15 +318,26 @@ func processList(s *pkg.Source, list *ast.Field) (opt options) { // parse parse options func parse(s *pkg.Source) (opts []*options) { - c := s.F.Scope.Lookup(_interfaceName) - if (c == nil) || (c.Kind != ast.Typ) { + var c *ast.Object + for _, name := range []string{"_bts", "Dao"} { + c = s.F.Scope.Lookup(name) + if (c == nil) || (c.Kind != ast.Typ) { + c = nil + continue + } + interfaceName = name + break + } + if c == nil { log.Fatalln("无法找到缓存声明") } lists := c.Decl.(*ast.TypeSpec).Type.(*ast.InterfaceType).Methods.List for _, list := range lists { opt := processList(s, list) - opt.Check() - opts = append(opts, &opt) + if opt.hasDec { + opt.Check() + opts = append(opts, &opt) + } } return } @@ -339,10 +364,6 @@ func (option *options) Check() { if option.SimpleValue && option.NullCache == option.ZeroValue { log.Fatalf("%s: %s 不能作为空缓存值 \n", option.name, option.NullCache) } - if strings.Contains(option.NullCache, "{}") { - // -nullcache=[]*model.OrderMain{} 这种无效 - log.Fatalf("%s: %s 不能作为空缓存值 会导致空缓存无效 \n", option.name, option.NullCache) - } if strings.Contains(option.CheckNullCode, "len") && strings.Contains(strings.Replace(option.CheckNullCode, " ", "", -1), "==0") { // -check_null_code=len($)==0 这种无效 log.Fatalf("%s: -check_null_code=%s 错误 会有无意义的赋值\n", option.name, option.CheckNullCode) @@ -352,6 +373,7 @@ func (option *options) Check() { func genHeader(opts []*options) (src string) { option := options{PkgName: os.Getenv("GOPACKAGE")} + option.UseBTS = interfaceName == "_bts" var sfCount int var packages, sfInit []string packagesMap := map[string]bool{`"context"`: true} diff --git a/tool/kratos-gen-bts/multi_template.go b/tool/kratos-gen-bts/multi_template.go index 6d4ffcffa..7034f00af 100644 --- a/tool/kratos-gen-bts/multi_template.go +++ b/tool/kratos-gen-bts/multi_template.go @@ -2,15 +2,19 @@ package main var _multiTemplate = ` // NAME {{or .Comment "get data from cache if miss will call source method, then add to cache."}} -func (d *Dao) NAME(c context.Context, {{.IDName}} []KEY{{.ExtraArgsType}}) (res map[KEY]VALUE, err error) { +func (d *{{.StructName}}) NAME(c context.Context, {{.IDName}} []KEY{{.ExtraArgsType}}) (res map[KEY]VALUE, err error) { if len({{.IDName}}) == 0 { return } addCache := true if res, err = CACHEFUNC(c, {{.IDName}} {{.ExtraCacheArgs}});err != nil { + {{if .CacheErrContinue}} addCache = false res = nil err = nil + {{else}} + return + {{end}} } var miss []KEY for _, key := range {{.IDName}} { diff --git a/tool/kratos-gen-bts/none_template.go b/tool/kratos-gen-bts/none_template.go index dfdf53ab8..90c4063d0 100644 --- a/tool/kratos-gen-bts/none_template.go +++ b/tool/kratos-gen-bts/none_template.go @@ -2,12 +2,16 @@ package main var _noneTemplate = ` // NAME {{or .Comment "get data from cache if miss will call source method, then add to cache."}} -func (d *Dao) NAME(c context.Context) (res VALUE, err error) { +func (d *{{.StructName}}) NAME(c context.Context) (res VALUE, err error) { addCache := true res, err = CACHEFUNC(c) if err != nil { + {{if .CacheErrContinue}} addCache = false err = nil + {{else}} + return + {{end}} } {{if .EnableNullCache}} defer func() { @@ -21,7 +25,7 @@ func (d *Dao) NAME(c context.Context) (res VALUE, err error) { {{else}} if res != {{.ZeroValue}} { {{end}} - cache.MetricHits.Inc("bts:NAME") + cache.MetricHits.Inc("bts:NAME") return } {{if .EnableSingleFlight}} diff --git a/tool/kratos-gen-bts/single_template.go b/tool/kratos-gen-bts/single_template.go index 7d3219e1f..0ec2d4473 100644 --- a/tool/kratos-gen-bts/single_template.go +++ b/tool/kratos-gen-bts/single_template.go @@ -2,12 +2,16 @@ package main var _singleTemplate = ` // NAME {{or .Comment "get data from cache if miss will call source method, then add to cache."}} -func (d *Dao) NAME(c context.Context, {{.IDName}} KEY{{.ExtraArgsType}}) (res VALUE, err error) { +func (d *{{.StructName}}) NAME(c context.Context, {{.IDName}} KEY{{.ExtraArgsType}}) (res VALUE, err error) { addCache := true res, err = CACHEFUNC(c, {{.IDName}} {{.ExtraCacheArgs}}) if err != nil { + {{if .CacheErrContinue}} addCache = false err = nil + {{else}} + return + {{end}} } {{if .EnableNullCache}} defer func() { diff --git a/tool/kratos/tool_index.go b/tool/kratos/tool_index.go index 6a7918a04..c3e9d4782 100644 --- a/tool/kratos/tool_index.go +++ b/tool/kratos/tool_index.go @@ -34,7 +34,7 @@ var toolIndexs = []*Tool{ { Name: "genbts", Alias: "kratos-gen-bts", - BuildTime: time.Date(2019, 7, 23, 0, 0, 0, 0, time.Local), + BuildTime: time.Date(2019, 10, 31, 0, 0, 0, 0, time.Local), Install: "go get -u github.com/bilibili/kratos/tool/kratos-gen-bts", Summary: "缓存回源逻辑代码生成器", Platform: []string{"darwin", "linux", "windows"},