Merge pull request #410 from bilibili/tool/di

新项目工具采用依赖注入
pull/413/head
Terry.Mao 5 years ago committed by GitHub
commit 4804ae4831
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      doc/wiki-cn/blademaster-quickstart.md
  2. 71
      doc/wiki-cn/cache-mc.md
  3. 70
      doc/wiki-cn/cache-redis.md
  4. 56
      doc/wiki-cn/database-mysql-orm.md
  5. 66
      doc/wiki-cn/database-mysql.md
  6. 17
      doc/wiki-cn/kratos-tool.md
  7. 56
      doc/wiki-cn/quickstart.md
  8. 15
      go.mod
  9. 71
      go.sum
  10. 2
      tool/kratos-gen-bts/README.md
  11. 6
      tool/kratos-gen-bts/header_template.go
  12. 45
      tool/kratos-gen-bts/main.go
  13. 6
      tool/kratos-gen-bts/multi_template.go
  14. 6
      tool/kratos-gen-bts/none_template.go
  15. 6
      tool/kratos-gen-bts/single_template.go
  16. 14
      tool/kratos-gen-bts/testdata/dao.bts.go
  17. 6
      tool/kratos-gen-bts/testdata/dao.go
  18. 12
      tool/kratos-gen-bts/testdata/multi.go
  19. 6
      tool/kratos-gen-bts/testdata/none.go
  20. 12
      tool/kratos-gen-bts/testdata/single.go
  21. 5
      tool/kratos-gen-mc/README.md
  22. 6
      tool/kratos-gen-mc/header_template.go
  23. 48
      tool/kratos-gen-mc/main.go
  24. 5
      tool/kratos-gen-mc/multi_template.go
  25. 5
      tool/kratos-gen-mc/none_template.go
  26. 5
      tool/kratos-gen-mc/single_template.go
  27. 2
      tool/kratos-gen-mc/testdata/mc.cache.go
  28. 8
      tool/kratos-gen-project/main-packr.go
  29. 76
      tool/kratos-gen-project/main.go
  30. 55
      tool/kratos-gen-project/new.go
  31. 174
      tool/kratos-gen-project/packrd/packed-packr.go
  32. 93
      tool/kratos-gen-project/project.go
  33. 4
      tool/kratos-gen-project/templates/all/CHANGELOG.md
  34. 2
      tool/kratos-gen-project/templates/all/OWNERS
  35. 4
      tool/kratos-gen-project/templates/all/README.md
  36. 34
      tool/kratos-gen-project/templates/all/api/api.proto
  37. 25
      tool/kratos-gen-project/templates/all/api/client.go.tmpl
  38. 41
      tool/kratos-gen-project/templates/all/cmd/main.go.tmpl
  39. 3
      tool/kratos-gen-project/templates/all/configs/application.toml
  40. 10
      tool/kratos-gen-project/templates/all/configs/db.toml
  41. 3
      tool/kratos-gen-project/templates/all/configs/grpc.toml
  42. 3
      tool/kratos-gen-project/templates/all/configs/http.toml
  43. 10
      tool/kratos-gen-project/templates/all/configs/memcache.toml
  44. 10
      tool/kratos-gen-project/templates/all/configs/redis.toml
  45. 11
      tool/kratos-gen-project/templates/all/go.mod.tmpl
  46. 63
      tool/kratos-gen-project/templates/all/internal/dao/dao.go.tmpl
  47. 25
      tool/kratos-gen-project/templates/all/internal/dao/db.go.tmpl
  48. 43
      tool/kratos-gen-project/templates/all/internal/dao/mc.go.tmpl
  49. 27
      tool/kratos-gen-project/templates/all/internal/dao/redis.go.tmpl
  50. 39
      tool/kratos-gen-project/templates/all/internal/di/app.go.tmpl
  51. 21
      tool/kratos-gen-project/templates/all/internal/di/wire.go.tmpl
  52. 12
      tool/kratos-gen-project/templates/all/internal/model/model.go.tmpl
  53. 23
      tool/kratos-gen-project/templates/all/internal/server/grpc/server.go.tmpl
  54. 57
      tool/kratos-gen-project/templates/all/internal/server/http/server.go.tmpl
  55. 54
      tool/kratos-gen-project/templates/all/internal/service/service.go.tmpl
  56. 40
      tool/kratos-gen-project/templates/all/test/docker-compose.yaml
  57. 4
      tool/kratos-gen-project/templates/grpc/CHANGELOG.md
  58. 2
      tool/kratos-gen-project/templates/grpc/OWNERS
  59. 4
      tool/kratos-gen-project/templates/grpc/README.md
  60. 34
      tool/kratos-gen-project/templates/grpc/api/api.proto
  61. 25
      tool/kratos-gen-project/templates/grpc/api/client.go.tmpl
  62. 41
      tool/kratos-gen-project/templates/grpc/cmd/main.go.tmpl
  63. 3
      tool/kratos-gen-project/templates/grpc/configs/application.toml
  64. 10
      tool/kratos-gen-project/templates/grpc/configs/db.toml
  65. 3
      tool/kratos-gen-project/templates/grpc/configs/grpc.toml
  66. 10
      tool/kratos-gen-project/templates/grpc/configs/memcache.toml
  67. 10
      tool/kratos-gen-project/templates/grpc/configs/redis.toml
  68. 11
      tool/kratos-gen-project/templates/grpc/go.mod.tmpl
  69. 63
      tool/kratos-gen-project/templates/grpc/internal/dao/dao.go.tmpl
  70. 25
      tool/kratos-gen-project/templates/grpc/internal/dao/db.go.tmpl
  71. 43
      tool/kratos-gen-project/templates/grpc/internal/dao/mc.go.tmpl
  72. 27
      tool/kratos-gen-project/templates/grpc/internal/dao/redis.go.tmpl
  73. 33
      tool/kratos-gen-project/templates/grpc/internal/di/app.go.tmpl
  74. 20
      tool/kratos-gen-project/templates/grpc/internal/di/wire.go.tmpl
  75. 12
      tool/kratos-gen-project/templates/grpc/internal/model/model.go.tmpl
  76. 23
      tool/kratos-gen-project/templates/grpc/internal/server/grpc/server.go.tmpl
  77. 54
      tool/kratos-gen-project/templates/grpc/internal/service/service.go.tmpl
  78. 40
      tool/kratos-gen-project/templates/grpc/test/docker-compose.yaml
  79. 4
      tool/kratos-gen-project/templates/http/CHANGELOG.md
  80. 2
      tool/kratos-gen-project/templates/http/OWNERS
  81. 4
      tool/kratos-gen-project/templates/http/README.md
  82. 34
      tool/kratos-gen-project/templates/http/api/api.proto
  83. 25
      tool/kratos-gen-project/templates/http/api/client.go.tmpl
  84. 41
      tool/kratos-gen-project/templates/http/cmd/main.go.tmpl
  85. 3
      tool/kratos-gen-project/templates/http/configs/application.toml
  86. 10
      tool/kratos-gen-project/templates/http/configs/db.toml
  87. 3
      tool/kratos-gen-project/templates/http/configs/http.toml
  88. 10
      tool/kratos-gen-project/templates/http/configs/memcache.toml
  89. 10
      tool/kratos-gen-project/templates/http/configs/redis.toml
  90. 11
      tool/kratos-gen-project/templates/http/go.mod.tmpl
  91. 63
      tool/kratos-gen-project/templates/http/internal/dao/dao.go.tmpl
  92. 25
      tool/kratos-gen-project/templates/http/internal/dao/db.go.tmpl
  93. 43
      tool/kratos-gen-project/templates/http/internal/dao/mc.go.tmpl
  94. 27
      tool/kratos-gen-project/templates/http/internal/dao/redis.go.tmpl
  95. 33
      tool/kratos-gen-project/templates/http/internal/di/app.go.tmpl
  96. 20
      tool/kratos-gen-project/templates/http/internal/di/wire.go.tmpl
  97. 12
      tool/kratos-gen-project/templates/http/internal/model/model.go.tmpl
  98. 57
      tool/kratos-gen-project/templates/http/internal/server/http/server.go.tmpl
  99. 54
      tool/kratos-gen-project/templates/http/internal/service/service.go.tmpl
  100. 40
      tool/kratos-gen-project/templates/http/test/docker-compose.yaml
  101. Some files were not shown because too many files have changed in this diff Show More

@ -4,32 +4,48 @@
``` ```
├── CHANGELOG.md ├── CHANGELOG.md
├── CONTRIBUTORS.md ├── OWNERS
├── LICENSE
├── README.md ├── README.md
├── api
   ├── api.bm.go
   ├── api.pb.go
   ├── api.proto
   └── client.go
├── cmd ├── cmd
   ├── cmd    ├── cmd
   └── main.go    └── main.go
├── configs ├── configs
   ├── application.toml    ├── application.toml
   ├── db.toml
   ├── grpc.toml    ├── grpc.toml
   ├── http.toml    ├── http.toml
   ├── log.toml
   ├── memcache.toml    ├── memcache.toml
   ├── mysql.toml
   └── redis.toml    └── redis.toml
├── go.mod ├── go.mod
├── go.sum ├── go.sum
└── internal ├── internal
├── dao    ├── dao
   └── dao.go      ├── dao.bts.go
├── model      ├── dao.go
   └── model.go      ├── db.go
├── server      ├── mc.cache.go
   └── http      ├── mc.go
   └── http.go      └── redis.go
└── service    ├── di
└── service.go      ├── app.go
     ├── wire.go
     └── wire_gen.go
   ├── model
     └── model.go
   ├── server
     ├── grpc
       └── server.go
     └── http
     └── server.go
   └── service
   └── service.go
└── test
└── docker-compose.yaml
``` ```
# 路由 # 路由

@ -4,32 +4,48 @@
``` ```
├── CHANGELOG.md ├── CHANGELOG.md
├── CONTRIBUTORS.md ├── OWNERS
├── LICENSE
├── README.md ├── README.md
├── api
   ├── api.bm.go
   ├── api.pb.go
   ├── api.proto
   └── client.go
├── cmd ├── cmd
   ├── cmd    ├── cmd
   └── main.go    └── main.go
├── configs ├── configs
   ├── application.toml    ├── application.toml
   ├── db.toml
   ├── grpc.toml    ├── grpc.toml
   ├── http.toml    ├── http.toml
   ├── log.toml
   ├── memcache.toml    ├── memcache.toml
   ├── mysql.toml
   └── redis.toml    └── redis.toml
├── go.mod ├── go.mod
├── go.sum ├── go.sum
└── internal ├── internal
├── dao    ├── dao
   └── dao.go      ├── dao.bts.go
├── model      ├── dao.go
   └── model.go      ├── db.go
├── server      ├── mc.cache.go
   └── http      ├── mc.go
   └── http.go      └── redis.go
└── service    ├── di
└── service.go      ├── app.go
     ├── wire.go
     └── wire_gen.go
   ├── model
     └── model.go
   ├── server
     ├── grpc
       └── server.go
     └── http
     └── server.go
   └── service
   └── service.go
└── test
└── docker-compose.yaml
``` ```
# 开始使用 # 开始使用
@ -39,9 +55,8 @@
创建项目成功后,进入项目中的configs目录,打开memcache.toml,我们可以看到: 创建项目成功后,进入项目中的configs目录,打开memcache.toml,我们可以看到:
```toml ```toml
demoExpire = "24h" [Client]
[demo] name = "abc"
name = "kratos-demo"
proto = "tcp" proto = "tcp"
addr = "127.0.0.1:11211" addr = "127.0.0.1:11211"
active = 50 active = 50
@ -53,27 +68,21 @@ demoExpire = "24h"
``` ```
在该配置文件中我们可以配置memcache的连接方式proto、连接地址addr、连接池的闲置连接数idle、最大连接数active以及各类超时。 在该配置文件中我们可以配置memcache的连接方式proto、连接地址addr、连接池的闲置连接数idle、最大连接数active以及各类超时。
这里可选添加mc的过期时间设置。
## 初始化 ## 初始化
进入项目的internal/dao目录,打开dao.go,其中: 进入项目的internal/dao目录,打开mc.go,其中:
```go ```go
var ( var cfg struct {
mc struct { Client *memcache.Config
Demo *memcache.Config
DemoExpire xtime.Duration
} }
)
checkErr(paladin.Get("memcache.toml").UnmarshalTOML(&mc)) checkErr(paladin.Get("memcache.toml").UnmarshalTOML(&mc))
``` ```
使用paladin配置管理工具将上文中的memcache.toml中的配置解析为我们需要使用的配置。 使用paladin配置管理工具将上文中的memcache.toml中的配置解析为我们需要使用的配置。
```go ```go
// Dao dao. // dao dao.
type Dao struct { type dao struct {
mc *memcache.Memcache mc *memcache.Memcache
mcExpire int32 mcExpire int32
} }
@ -82,7 +91,7 @@ type Dao struct {
在dao的主结构提中定义了memcache的连接池对象和过期时间。 在dao的主结构提中定义了memcache的连接池对象和过期时间。
```go ```go
dao = &Dao{ d = &dao{
// memcache // memcache
mc: memcache.New(mc.Demo), mc: memcache.New(mc.Demo),
mcExpire: int32(time.Duration(mc.DemoExpire) / time.Second), mcExpire: int32(time.Duration(mc.DemoExpire) / time.Second),
@ -95,11 +104,11 @@ dao = &Dao{
```go ```go
// Ping ping the resource. // Ping ping the resource.
func (d *Dao) Ping(ctx context.Context) (err error) { func (d *dao) Ping(ctx context.Context) (err error) {
return d.pingMC(ctx) return d.pingMC(ctx)
} }
func (d *Dao) pingMC(ctx context.Context) (err error) { func (d *dao) pingMC(ctx context.Context) (err error) {
if err = d.mc.Set(ctx, &memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil { if err = d.mc.Set(ctx, &memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("conn.Set(PING) error(%v)", err) log.Error("conn.Set(PING) error(%v)", err)
} }

@ -4,32 +4,48 @@
``` ```
├── CHANGELOG.md ├── CHANGELOG.md
├── CONTRIBUTORS.md ├── OWNERS
├── LICENSE
├── README.md ├── README.md
├── api
   ├── api.bm.go
   ├── api.pb.go
   ├── api.proto
   └── client.go
├── cmd ├── cmd
   ├── cmd    ├── cmd
   └── main.go    └── main.go
├── configs ├── configs
   ├── application.toml    ├── application.toml
   ├── db.toml
   ├── grpc.toml    ├── grpc.toml
   ├── http.toml    ├── http.toml
   ├── log.toml
   ├── memcache.toml    ├── memcache.toml
   ├── mysql.toml
   └── redis.toml    └── redis.toml
├── go.mod ├── go.mod
├── go.sum ├── go.sum
└── internal ├── internal
├── dao    ├── dao
   └── dao.go      ├── dao.bts.go
├── model      ├── dao.go
   └── model.go      ├── db.go
├── server      ├── mc.cache.go
   └── http      ├── mc.go
   └── http.go      └── redis.go
└── service    ├── di
└── service.go      ├── app.go
     ├── wire.go
     └── wire_gen.go
   ├── model
     └── model.go
   ├── server
     ├── grpc
       └── server.go
     └── http
     └── server.go
   └── service
   └── service.go
└── test
└── docker-compose.yaml
``` ```
# 开始使用 # 开始使用
@ -39,9 +55,7 @@
创建项目成功后,进入项目中的configs目录,打开redis.toml,我们可以看到: 创建项目成功后,进入项目中的configs目录,打开redis.toml,我们可以看到:
```toml ```toml
demoExpire = "24h" [Client]
[demo]
name = "kratos-demo" name = "kratos-demo"
proto = "tcp" proto = "tcp"
addr = "127.0.0.1:6389" addr = "127.0.0.1:6389"
@ -55,20 +69,14 @@ demoExpire = "24h"
在该配置文件中我们可以配置redis的连接方式proto、连接地址addr、连接池的闲置连接数idle、最大连接数active以及各类超时。 在该配置文件中我们可以配置redis的连接方式proto、连接地址addr、连接池的闲置连接数idle、最大连接数active以及各类超时。
这里可选添加redis的过期时间设置。
## 初始化 ## 初始化
进入项目的internal/dao目录,打开dao.go,其中: 进入项目的internal/dao目录,打开redis.go,其中:
```go ```go
var ( var cfg struct {
rc struct { Client *memcache.Config
Demo *redis.Config
DemoExpire xtime.Duration
} }
)
checkErr(paladin.Get("redis.toml").UnmarshalTOML(&rc)) checkErr(paladin.Get("redis.toml").UnmarshalTOML(&rc))
``` ```
使用paladin配置管理工具将上文中的redis.toml中的配置解析为我们需要使用的配置。 使用paladin配置管理工具将上文中的redis.toml中的配置解析为我们需要使用的配置。
@ -84,7 +92,7 @@ type Dao struct {
在dao的主结构提中定义了redis的连接池对象和过期时间。 在dao的主结构提中定义了redis的连接池对象和过期时间。
```go ```go
dao = &Dao{ d = &dao{
// redis // redis
redis: redis.NewPool(rc.Demo), redis: redis.NewPool(rc.Demo),
redisExpire: int32(time.Duration(rc.DemoExpire) / time.Second), redisExpire: int32(time.Duration(rc.DemoExpire) / time.Second),
@ -97,11 +105,11 @@ dao = &Dao{
```go ```go
// Ping ping the resource. // Ping ping the resource.
func (d *Dao) Ping(ctx context.Context) (err error) { func (d *dao) Ping(ctx context.Context) (err error) {
return d.pingRedis(ctx) return d.pingRedis(ctx)
} }
func (d *Dao) pingRedis(ctx context.Context) (err error) { func (d *dao) pingRedis(ctx context.Context) (err error) {
conn := d.redis.Get(ctx) conn := d.redis.Get(ctx)
defer conn.Close() defer conn.Close()
if _, err = conn.Do("SET", "ping", "pong"); err != nil { if _, err = conn.Do("SET", "ping", "pong"); err != nil {
@ -130,7 +138,7 @@ func (d *Dao) Close() {
```go ```go
// DemoIncrby . // DemoIncrby .
func (d *Dao) DemoIncrby(c context.Context, pid int) (err error) { func (d *dao) DemoIncrby(c context.Context, pid int) (err error) {
cacheKey := keyDemo(pid) cacheKey := keyDemo(pid)
conn := d.redis.Get(c) conn := d.redis.Get(c)
defer conn.Close() defer conn.Close()
@ -149,7 +157,7 @@ kratos/pkg/cache/redis包除了支持发送单个命令,也支持批量发送
```go ```go
// DemoIncrbys . // DemoIncrbys .
func (d *Dao) DemoIncrbys(c context.Context, pid int) (err error) { func (d *dao) DemoIncrbys(c context.Context, pid int) (err error) {
cacheKey := keyDemo(pid) cacheKey := keyDemo(pid)
conn := d.redis.Get(c) conn := d.redis.Get(c)
defer conn.Close() defer conn.Close()

@ -4,32 +4,48 @@
``` ```
├── CHANGELOG.md ├── CHANGELOG.md
├── CONTRIBUTORS.md ├── OWNERS
├── LICENSE
├── README.md ├── README.md
├── api
   ├── api.bm.go
   ├── api.pb.go
   ├── api.proto
   └── client.go
├── cmd ├── cmd
   ├── cmd    ├── cmd
   └── main.go    └── main.go
├── configs ├── configs
   ├── application.toml    ├── application.toml
   ├── db.toml
   ├── grpc.toml    ├── grpc.toml
   ├── http.toml    ├── http.toml
   ├── log.toml
   ├── memcache.toml    ├── memcache.toml
   ├── mysql.toml
   └── redis.toml    └── redis.toml
├── go.mod ├── go.mod
├── go.sum ├── go.sum
└── internal ├── internal
├── dao    ├── dao
   └── dao.go      ├── dao.bts.go
├── model      ├── dao.go
   └── model.go      ├── db.go
├── server      ├── mc.cache.go
   └── http      ├── mc.go
   └── http.go      └── redis.go
└── service    ├── di
└── service.go      ├── app.go
     ├── wire.go
     └── wire_gen.go
   ├── model
     └── model.go
   ├── server
     ├── grpc
       └── server.go
     └── http
     └── server.go
   └── service
   └── service.go
└── test
└── docker-compose.yaml
``` ```
# 开始使用 # 开始使用
@ -57,17 +73,15 @@
## 初始化 ## 初始化
进入项目的internal/dao目录,打开dao.go,其中: 进入项目的internal/dao目录,打开db.go,其中:
```go ```go
var ( var cfg struct {
dc struct { Client *sql.Config
Demo *sql.Config
} }
) checkErr(paladin.Get("db.toml").UnmarshalTOML(&dc))
checkErr(paladin.Get("mysql.toml").UnmarshalTOML(&dc))
``` ```
使用paladin配置管理工具将上文中的mysql.toml中的配置解析为我们需要使用mysql的相关配置。 使用paladin配置管理工具将上文中的db.toml中的配置解析为我们需要使用db的相关配置。
# TODO:补充常用方法 # TODO:补充常用方法

@ -4,32 +4,48 @@
``` ```
├── CHANGELOG.md ├── CHANGELOG.md
├── CONTRIBUTORS.md ├── OWNERS
├── LICENSE
├── README.md ├── README.md
├── api
   ├── api.bm.go
   ├── api.pb.go
   ├── api.proto
   └── client.go
├── cmd ├── cmd
   ├── cmd    ├── cmd
   └── main.go    └── main.go
├── configs ├── configs
   ├── application.toml    ├── application.toml
   ├── db.toml
   ├── grpc.toml    ├── grpc.toml
   ├── http.toml    ├── http.toml
   ├── log.toml
   ├── memcache.toml    ├── memcache.toml
   ├── mysql.toml
   └── redis.toml    └── redis.toml
├── go.mod ├── go.mod
├── go.sum ├── go.sum
└── internal ├── internal
├── dao    ├── dao
   └── dao.go      ├── dao.bts.go
├── model      ├── dao.go
   └── model.go      ├── db.go
├── server      ├── mc.cache.go
   └── http      ├── mc.go
   └── http.go      └── redis.go
└── service    ├── di
└── service.go      ├── app.go
     ├── wire.go
     └── wire_gen.go
   ├── model
     └── model.go
   ├── server
     ├── grpc
       └── server.go
     └── http
     └── server.go
   └── service
   └── service.go
└── test
└── docker-compose.yaml
``` ```
# 开始使用 # 开始使用
@ -57,17 +73,15 @@
## 初始化 ## 初始化
进入项目的internal/dao目录,打开dao.go,其中: 进入项目的internal/dao目录,打开db.go,其中:
```go ```go
var ( var cfg struct {
dc struct { Client *sql.Config
Demo *sql.Config
} }
) checkErr(paladin.Get("db.toml").UnmarshalTOML(&dc))
checkErr(paladin.Get("mysql.toml").UnmarshalTOML(&dc))
``` ```
使用paladin配置管理工具将上文中的mysql.toml中的配置解析为我们需要使用mysql的相关配置。 使用paladin配置管理工具将上文中的db.toml中的配置解析为我们需要使用db的相关配置。
```go ```go
// Dao dao. // Dao dao.
@ -79,7 +93,7 @@ type Dao struct {
在dao的主结构提中定义了mysql的连接池对象。 在dao的主结构提中定义了mysql的连接池对象。
```go ```go
dao = &Dao{ d = &dao{
db: sql.NewMySQL(dc.Demo), db: sql.NewMySQL(dc.Demo),
} }
``` ```
@ -90,7 +104,7 @@ dao = &Dao{
```go ```go
// Ping ping the resource. // Ping ping the resource.
func (d *Dao) Ping(ctx context.Context) (err error) { func (d *dao) Ping(ctx context.Context) (err error) {
return d.db.Ping(ctx) return d.db.Ping(ctx)
} }
``` ```
@ -101,7 +115,7 @@ func (d *Dao) Ping(ctx context.Context) (err error) {
```go ```go
// Close close the resource. // Close close the resource.
func (d *Dao) Close() { func (d *dao) Close() {
d.db.Close() d.db.Close()
} }
``` ```
@ -114,7 +128,7 @@ func (d *Dao) Close() {
```go ```go
// GetDemo 用户角色 // GetDemo 用户角色
func (d *Dao) GetDemo(c context.Context, did int64) (demo int8, err error) { func (d *dao) GetDemo(c context.Context, did int64) (demo int8, err error) {
err = d.db.QueryRow(c, _getDemoSQL, did).Scan(&demo) err = d.db.QueryRow(c, _getDemoSQL, did).Scan(&demo)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
log.Error("d.GetDemo.Query error(%v)", err) log.Error("d.GetDemo.Query error(%v)", err)
@ -132,7 +146,7 @@ db.QueryRow方法用于返回最多一条记录的查询,在QueryRow方法后
```go ```go
// ResourceLogs ResourceLogs. // ResourceLogs ResourceLogs.
func (d *Dao) GetDemos(c context.Context, dids []int64) (demos []int8, err error) { func (d *dao) GetDemos(c context.Context, dids []int64) (demos []int8, err error) {
rows, err := d.db.Query(c, _getDemosSQL, dids) rows, err := d.db.Query(c, _getDemosSQL, dids)
if err != nil { if err != nil {
log.Error("query error(%v)", err) log.Error("query error(%v)", err)

@ -55,10 +55,16 @@ kratos new kratos-demo
kratos new kratos-demo -o YourName -d YourPath kratos new kratos-demo -o YourName -d YourPath
``` ```
注意,`kratos new`默认是不会生成通过 protobuf 定义的`grpc`和`bm`示例代码的,如需生成请加`--proto`,如下: 注意,`kratos new`默认会生成通过 protobuf 定义的`grpc`和`bm`示例代码的,如只生成bm请加`--http`,如下:
```shell ```shell
kratos new kratos-demo -o YourName -d YourPath --proto kratos new kratos-demo -o YourName -d YourPath --http
```
如只生成grpc请加`--grpc`,如下:
```shell
kratos new kratos-demo -o YourName -d YourPath --grpc
``` ```
> 特别注意,如果不是MacOS系统,需要自己进行手动安装protoc,用于生成的示例项目`api`目录下的`proto`文件并不会自动生成对应的`.pb.go`和`.bm.go`文件。 > 特别注意,如果不是MacOS系统,需要自己进行手动安装protoc,用于生成的示例项目`api`目录下的`proto`文件并不会自动生成对应的`.pb.go`和`.bm.go`文件。
@ -76,13 +82,16 @@ kratos new kratos-demo -o YourName -d YourPath --proto
``` ```
kratos tool kratos tool
protoc(已安装): 快速方便生成pb.go的protoc封装,windows、Linux请先安装protoc工具 Author(kratos) [2019/10/31]
genbts(已安装): 缓存回源逻辑代码生成器 Author(kratos) [2019/10/31]
testcli(已安装): 测试代码生成 Author(kratos) [2019/09/09]
genmc(已安装): mc缓存代码生成 Author(kratos) [2019/07/23]
swagger(已安装): swagger api文档 Author(goswagger.io) [2019/05/05] swagger(已安装): swagger api文档 Author(goswagger.io) [2019/05/05]
protoc(已安装): 快速方便生成pb.go和bm.go的protoc封装,windows、Linux请先安装protoc工具 Author(kratos) [2019/05/04]
kratos(已安装): Kratos工具集本体 Author(kratos) [2019/04/02]
安装工具: kratos tool install demo 安装工具: kratos tool install demo
执行工具: kratos tool demo 执行工具: kratos tool demo
安装全部工具: kratos tool install all 安装全部工具: kratos tool install all
全部升级: kratos tool upgrade all
详细文档: https://github.com/bilibili/kratos/blob/master/doc/wiki-cn/kratos-tool.md 详细文档: https://github.com/bilibili/kratos/blob/master/doc/wiki-cn/kratos-tool.md
``` ```

@ -11,36 +11,48 @@ kratos new kratos-demo
根据提示可以快速创建项目,如[kratos-demo](https://github.com/bilibili/kratos-demo)就是通过工具创建生成。目录结构如下: 根据提示可以快速创建项目,如[kratos-demo](https://github.com/bilibili/kratos-demo)就是通过工具创建生成。目录结构如下:
``` ```
├── CHANGELOG.md # CHANGELOG ├── CHANGELOG.md
├── CONTRIBUTORS.md # CONTRIBUTORS ├── OWNERS
├── README.md # README ├── README.md
├── api # api目录为对外保留的proto文件及生成的pb.go文件,注:需要"--proto"参数 ├── api # api目录为对外保留的proto文件及生成的pb.go文件
   ├── api.proto    ├── api.bm.go
   ├── api.pb.go # 通过go generate生成的pb.go文件    ├── api.pb.go # 通过go generate生成的pb.go文件
   └── generate.go    ├── api.proto
├── cmd # cmd目录为main所在    └── client.go
   └── main.go # main.go ├── cmd
   └── main.go # cmd目录为main所在
├── configs # configs为配置文件目录 ├── configs # configs为配置文件目录
   ├── application.toml # 应用的自定义配置文件,可能是一些业务开关如:useABtest = true    ├── application.toml # 应用的自定义配置文件,可能是一些业务开关如:useABtest = true
   ├── db.toml # db相关配置
   ├── grpc.toml # grpc相关配置    ├── grpc.toml # grpc相关配置
   ├── http.toml # http相关配置    ├── http.toml # http相关配置
   ├── log.toml # log相关配置
   ├── memcache.toml # memcache相关配置    ├── memcache.toml # memcache相关配置
   ├── mysql.toml # mysql相关配置
   └── redis.toml # redis相关配置    └── redis.toml # redis相关配置
├── go.mod # go.mod ├── go.mod
├── go.sum
└── internal # internal为项目内部包,包括以下目录: └── internal # internal为项目内部包,包括以下目录:
├── dao # dao层,用于数据库、cache、MQ、依赖某业务grpc|http等资源访问    ├── dao # dao层,用于数据库、cache、MQ、依赖某业务grpc|http等资源访问
   └── dao.go      ├── dao.bts.go
├── model # model层,用于声明业务结构体      ├── dao.go
   └── model.go      ├── db.go
├── server # server层,用于初始化grpc和http server      ├── mc.cache.go
   └── http # http层,用于初始化http server和声明handler      ├── mc.go
   └── http.go      └── redis.go
   └── grpc # grpc层,用于初始化grpc server和定义method    ├── di # 依赖注入层 采用wire静态分析依赖
   └── grpc.go      ├── app.go
└── service # service层,用于业务逻辑处理,且为方便http和grpc共用方法,建议入参和出参保持grpc风格,且使用pb文件生成代码      ├── wire.go # wire 声明
└── service.go      └── wire_gen.go # go generate 生成的代码
   ├── model # model层,用于声明业务结构体
     └── model.go
   ├── server # server层,用于初始化grpc和http server
     ├── grpc # grpc层,用于初始化grpc server和定义method
       └── server.go
     └── http # http层,用于初始化http server和声明handler
     └── server.go
   └── service # service层,用于业务逻辑处理,且为方便http和grpc共用方法,建议入参和出参保持grpc风格,且使用pb文件生成代码
   └── service.go
└── test # 测试资源层 用于存放测试相关资源数据 如docker-compose配置 数据库初始化语句等
└── docker-compose.yaml
``` ```
生成后可直接运行如下: 生成后可直接运行如下:

@ -7,6 +7,7 @@ require (
github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6 // indirect github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6 // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect
@ -17,16 +18,16 @@ require (
github.com/go-playground/locales v0.12.1 // indirect github.com/go-playground/locales v0.12.1 // indirect
github.com/go-playground/universal-translator v0.16.0 // indirect github.com/go-playground/universal-translator v0.16.0 // indirect
github.com/go-sql-driver/mysql v1.4.1 github.com/go-sql-driver/mysql v1.4.1
github.com/gobuffalo/packr/v2 v2.7.1
github.com/gogo/protobuf v1.3.0 github.com/gogo/protobuf v1.3.0
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect
github.com/golang/mock v1.3.1 // indirect github.com/golang/mock v1.3.1 // indirect
github.com/golang/protobuf v1.3.2 github.com/golang/protobuf v1.3.2
github.com/google/uuid v1.1.1 // indirect github.com/google/uuid v1.1.1 // indirect
github.com/gorilla/websocket v1.4.0 // indirect github.com/gorilla/websocket v1.4.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/leodido/go-urn v1.1.0 // indirect github.com/leodido/go-urn v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.2 // indirect github.com/mattn/go-colorable v0.1.4 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/mattn/go-isatty v0.0.10 // indirect
github.com/montanaflynn/stats v0.5.0 github.com/montanaflynn/stats v0.5.0
github.com/openzipkin/zipkin-go v0.2.1 github.com/openzipkin/zipkin-go v0.2.1
github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3 github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3
@ -38,17 +39,17 @@ require (
github.com/shirou/gopsutil v2.19.6+incompatible github.com/shirou/gopsutil v2.19.6+incompatible
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726
github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus v1.4.2
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.4.0
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa
github.com/urfave/cli v1.20.0 github.com/urfave/cli v1.22.1
go.etcd.io/etcd v0.0.0-20190917205325-a14579fbfb1a go.etcd.io/etcd v0.0.0-20190917205325-a14579fbfb1a
go.uber.org/atomic v1.4.0 // indirect go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.2.0 // indirect go.uber.org/multierr v1.2.0 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect
golang.org/x/net v0.0.0-20191011234655-491137f69257 golang.org/x/net v0.0.0-20191011234655-491137f69257
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 // indirect golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c // indirect
golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89 golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3
google.golang.org/appengine v1.6.1 // indirect google.golang.org/appengine v1.6.1 // indirect
google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03 google.golang.org/genproto v0.0.0-20191009194640-548a555dbc03
google.golang.org/grpc v1.24.0 google.golang.org/grpc v1.24.0

@ -14,6 +14,7 @@ github.com/aristanetworks/glog v0.0.0-20180419172825-c15b03b3054f/go.mod h1:KASm
github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6 h1:6bZNnQcA2fkzH9AhZXbp2nDqbWa4bBqFeUb70Zq1HBM= github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6 h1:6bZNnQcA2fkzH9AhZXbp2nDqbWa4bBqFeUb70Zq1HBM=
github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns= github.com/aristanetworks/goarista v0.0.0-20190912214011-b54698eaaca6/go.mod h1:Z4RTxGAuYhPzcq8+EdRM+R8M48Ssle2TsWtwRKa+vns=
github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc= github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@ -22,6 +23,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
@ -32,6 +35,12 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBt
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8= github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8= github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
@ -71,6 +80,15 @@ github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEK
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8=
github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w=
github.com/gobuffalo/logger v1.0.1 h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg=
github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o=
github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc=
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@ -113,10 +131,13 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI= github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1QAp/SlnNrZhI=
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxdb1-client v0.0.0-20190809212627-fc22c7df067e/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= github.com/jcmturner/gofork v0.0.0-20190328161633-dc7c13fece03/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -141,15 +162,20 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -171,10 +197,9 @@ github.com/openzipkin/zipkin-go v0.2.1 h1:noL5/5Uf1HpVl3wNsfkZhIKbSWCVi5jgqkONNx
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3 h1:zjmNboC3QFuMdJSaZJ7Qvi3HUxWXPdj7wb3rc4jH5HI= github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3 h1:zjmNboC3QFuMdJSaZJ7Qvi3HUxWXPdj7wb3rc4jH5HI=
github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3/go.mod h1:pLR8n2aimFxvvDJ6n8JuQWthMGezCYMjuhlaTjPTZf0= github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3/go.mod h1:pLR8n2aimFxvvDJ6n8JuQWthMGezCYMjuhlaTjPTZf0=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/philchia/agollo v0.0.0-20190728085453-a95533fccea3 h1:e/WwwXpp+h9CtbiwSdDxrgq6ymvrvLH/P+kS+8qq4v8= github.com/philchia/agollo v0.0.0-20190728085453-a95533fccea3 h1:e/WwwXpp+h9CtbiwSdDxrgq6ymvrvLH/P+kS+8qq4v8=
github.com/philchia/agollo v0.0.0-20190728085453-a95533fccea3/go.mod h1:EXNdWdQkS+QBi0nb/Xm+sBBuQ1PM7/NIPr1JDzOlt8A= github.com/philchia/agollo v0.0.0-20190728085453-a95533fccea3/go.mod h1:EXNdWdQkS+QBi0nb/Xm+sBBuQ1PM7/NIPr1JDzOlt8A=
github.com/philchia/agollo v2.3.1+incompatible h1:C4zDDuOcP1Qynikz2rSJQSMjwexv4GfDpwBHJRinhPc=
github.com/philchia/agollo v2.3.1+incompatible/go.mod h1:EXNdWdQkS+QBi0nb/Xm+sBBuQ1PM7/NIPr1JDzOlt8A=
github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -201,12 +226,23 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237 h1:HQagqIiBmr8YXawX/le3+O26N+vPPC1PtjaF3mwnook= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237 h1:HQagqIiBmr8YXawX/le3+O26N+vPPC1PtjaF3mwnook=
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.4.0 h1:LUa41nrWTQNGhzdsZ5lTnkwbNjj6rXTdazA1cSdjkOY=
github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY= github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY=
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shirou/gopsutil v2.19.6+incompatible h1:49/Gru26Lne9Cl3IoAVDZVM09hvkSrUodgIIsCVRwbs= github.com/shirou/gopsutil v2.19.6+incompatible h1:49/Gru26Lne9Cl3IoAVDZVM09hvkSrUodgIIsCVRwbs=
github.com/shirou/gopsutil v2.19.6+incompatible/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= github.com/shirou/gopsutil v2.19.6+incompatible/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM= github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -214,15 +250,24 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
@ -231,12 +276,16 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa h1:V/ABqiqsgqmpoIcLDSpJ1KqPfbxRmkcfET5+BRy9ctM= github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa h1:V/ABqiqsgqmpoIcLDSpJ1KqPfbxRmkcfET5+BRy9ctM=
github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa/go.mod h1:3HfLQly3YNLGxNv/2YOfmz30vcjG9hbuME1GpxoLlGs= github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa/go.mod h1:3HfLQly3YNLGxNv/2YOfmz30vcjG9hbuME1GpxoLlGs=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= github.com/xtaci/kcp-go v5.4.5+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
@ -253,9 +302,11 @@ go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -283,23 +334,28 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8 h1:41hwlulw1prEMBxLQSlMSux1zxJf07B3WPsdjJlKZxE= golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8 h1:41hwlulw1prEMBxLQSlMSux1zxJf07B3WPsdjJlKZxE=
golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190912141932-bc967efca4b8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE=
golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -318,6 +374,8 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b h1:mSUCVIwDx4hfXJfWsOPfdzE
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89 h1:WiVZGyzQN7gPNLRkkpsNX3jC0Jx5j9GxadCZW/8eXw0= golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89 h1:WiVZGyzQN7gPNLRkkpsNX3jC0Jx5j9GxadCZW/8eXw0=
golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190912185636-87d9f09c5d89/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3 h1:2AmBLzhAfXj+2HCW09VCkJtHIYgHTIPcTeYqgP7Bwt0=
golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -338,6 +396,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=

@ -36,6 +36,7 @@ dao里面需要有cache对象 代码会调用d.cache来新增缓存
| ---------------- | ------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | ---------------- | ------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| -nullcache | | 空指针对象(存正常业务不会出现的内容 id的话像是-1这样的) | &Demo{ID:-1} 或-1 或"null" | | -nullcache | | 空指针对象(存正常业务不会出现的内容 id的话像是-1这样的) | &Demo{ID:-1} 或-1 或"null" |
| -check_null_code | | 开启空缓存并且value为指针对象时必填 用于判断是否是空缓存 $来指代对象名 | `-check_null_code=$!=nil&&$.ID==-1 或 $ == -1` | | -check_null_code | | 开启空缓存并且value为指针对象时必填 用于判断是否是空缓存 $来指代对象名 | `-check_null_code=$!=nil&&$.ID==-1 或 $ == -1` |
| -cache_err |continue| 缓存出错的时候的行为 continue: 继续执行 break: 抛出错误 方法返回|break|
| -batch | | (限多key模板) 批量获取数据 每组大小 | 100 | | -batch | | (限多key模板) 批量获取数据 每组大小 | 100 |
| -max_group | | (限多key模板)批量获取数据 最大组数量 | 10 | | -max_group | | (限多key模板)批量获取数据 最大组数量 | 10 |
| -batch_err | break | (限多key模板)批量获取数据回源错误的时候 降级继续请求(continue)还是直接返回(break) | break 或 continue | | -batch_err | break | (限多key模板)批量获取数据回源错误的时候 降级继续请求(continue)还是直接返回(break) | break 或 continue |
@ -44,3 +45,4 @@ dao里面需要有cache对象 代码会调用d.cache来新增缓存
| -paging | false | (限单key模板)分页 数据源应返回2个值 第一个为对外数据 第二个为全量数据 用于新增缓存 | false | | -paging | false | (限单key模板)分页 数据源应返回2个值 第一个为对外数据 第二个为全量数据 用于新增缓存 | false |
| -ignores | | 用于依赖的三个方法参数和主方法参数不一致的情况. 忽略方法的某些参数 用\|分隔方法逗号分隔参数 | pn,ps\|pn\|origin 表示"缓存获取"方法忽略pn,ps两个参数 回源方法忽略pn参数 加缓存方法忽略origin参数 | | -ignores | | 用于依赖的三个方法参数和主方法参数不一致的情况. 忽略方法的某些参数 用\|分隔方法逗号分隔参数 | pn,ps\|pn\|origin 表示"缓存获取"方法忽略pn,ps两个参数 回源方法忽略pn参数 加缓存方法忽略origin参数 |
| -custom_method | false | 自定义方法名 \|分隔 缓存获取方法名\|回源方法名\|增加缓存方法名 | d.mc.AddDemo\|d.mysql.Demo\|d.mc.AddDemo | | -custom_method | false | 自定义方法名 \|分隔 缓存获取方法名\|回源方法名\|增加缓存方法名 | d.mc.AddDemo\|d.mysql.Demo\|d.mc.AddDemo |
| -struct_name | dao | 所属结构体名称 | Dao|

@ -24,9 +24,9 @@ NEWLINE
{{if .EnableSingleFlight}} "golang.org/x/sync/singleflight" {{end}} {{if .EnableSingleFlight}} "golang.org/x/sync/singleflight" {{end}}
) )
var ( {{if .UseBTS}}
_ _bts var _ _bts
) {{end }}
{{if .EnableSingleFlight}} {{if .EnableSingleFlight}}
var cacheSingleFlights = [SFCOUNT]*singleflight.Group{SFINIT} var cacheSingleFlights = [SFCOUNT]*singleflight.Group{SFINIT}
{{end }} {{end }}

@ -10,6 +10,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime"
"strconv" "strconv"
"strings" "strings"
"text/template" "text/template"
@ -22,6 +23,7 @@ var (
singleFlight = flag.Bool("singleflight", false, "enable singleflight") singleFlight = flag.Bool("singleflight", false, "enable singleflight")
nullCache = flag.String("nullcache", "", "null cache") nullCache = flag.String("nullcache", "", "null cache")
checkNullCode = flag.String("check_null_code", "", "check null code") 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") batchSize = flag.Int("batch", 0, "batch size")
batchErr = flag.String("batch_err", "break", "batch err to contine or break") batchErr = flag.String("batch_err", "break", "batch err to contine or break")
maxGroup = flag.Int("max_group", 0, "max group size") maxGroup = flag.Int("max_group", 0, "max group size")
@ -29,15 +31,16 @@ var (
paging = flag.Bool("paging", false, "use paging in single template") paging = flag.Bool("paging", false, "use paging in single template")
ignores = flag.String("ignores", "", "ignore params") ignores = flag.String("ignores", "", "ignore params")
customMethod = flag.String("custom_method", "", "自定义方法名 |分隔: 缓存|回源|增加缓存") 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"} 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"} 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{} optionNamesMap = map[string]bool{}
interfaceName string
) )
const ( const (
_interfaceName = "_bts"
_multiTpl = 1 _multiTpl = 1
_singleTpl = 2 _singleTpl = 2
_noneTpl = 3 _noneTpl = 3
@ -52,8 +55,10 @@ func resetFlag() {
*sync = false *sync = false
*paging = false *paging = false
*batchErr = "break" *batchErr = "break"
*cacheErr = "continue"
*ignores = "" *ignores = ""
*customMethod = "" *customMethod = ""
*structName = "dao"
} }
// options options // options options
@ -91,6 +96,10 @@ type options struct {
Comment string Comment string
CustomMethod string CustomMethod string
IDName string IDName string
CacheErrContinue bool
StructName string
hasDec bool
UseBTS bool
} }
func getOptions(opt *options, comment string) { func getOptions(opt *options, comment string) {
@ -108,6 +117,7 @@ func getOptions(opt *options, comment string) {
os.Args = append(os.Args, arg) os.Args = append(os.Args, arg)
} }
} }
opt.hasDec = true
} }
resetFlag() resetFlag()
flag.Parse() flag.Parse()
@ -122,13 +132,15 @@ func getOptions(opt *options, comment string) {
opt.GroupSize = *batchSize opt.GroupSize = *batchSize
opt.MaxGroup = *maxGroup opt.MaxGroup = *maxGroup
opt.CustomMethod = *customMethod opt.CustomMethod = *customMethod
opt.CacheErrContinue = *cacheErr == "continue"
opt.StructName = *structName
} }
func processList(s *pkg.Source, list *ast.Field) (opt options) { func processList(s *pkg.Source, list *ast.Field) (opt options) {
fset := s.Fset fset := s.Fset
src := s.Src src := s.Src
lines := strings.Split(src, "\n") 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 // get comment
line := fset.Position(list.Pos()).Line - 3 line := fset.Position(list.Pos()).Line - 3
if len(lines)-1 >= line { if len(lines)-1 >= line {
@ -140,8 +152,11 @@ func processList(s *pkg.Source, list *ast.Field) (opt options) {
line = fset.Position(list.Pos()).Line - 2 line = fset.Position(list.Pos()).Line - 2
comment := lines[line] comment := lines[line]
getOptions(&opt, comment) getOptions(&opt, comment)
if !opt.hasDec {
log.Printf("%s: 无声明 忽略此方法\n", opt.name)
return
}
// get func // get func
opt.name = list.Names[0].Name
params := list.Type.(*ast.FuncType).Params.List params := list.Type.(*ast.FuncType).Params.List
if len(params) == 0 { if len(params) == 0 {
log.Fatalln(opt.name + "参数不足") log.Fatalln(opt.name + "参数不足")
@ -304,16 +319,27 @@ func processList(s *pkg.Source, list *ast.Field) (opt options) {
// parse parse options // parse parse options
func parse(s *pkg.Source) (opts []*options) { func parse(s *pkg.Source) (opts []*options) {
c := s.F.Scope.Lookup(_interfaceName) var c *ast.Object
for _, name := range []string{"_bts", "Dao"} {
c = s.F.Scope.Lookup(name)
if (c == nil) || (c.Kind != ast.Typ) { if (c == nil) || (c.Kind != ast.Typ) {
c = nil
continue
}
interfaceName = name
break
}
if c == nil {
log.Fatalln("无法找到缓存声明") log.Fatalln("无法找到缓存声明")
} }
lists := c.Decl.(*ast.TypeSpec).Type.(*ast.InterfaceType).Methods.List lists := c.Decl.(*ast.TypeSpec).Type.(*ast.InterfaceType).Methods.List
for _, list := range lists { for _, list := range lists {
opt := processList(s, list) opt := processList(s, list)
if opt.hasDec {
opt.Check() opt.Check()
opts = append(opts, &opt) opts = append(opts, &opt)
} }
}
return return
} }
@ -339,10 +365,6 @@ func (option *options) Check() {
if option.SimpleValue && option.NullCache == option.ZeroValue { if option.SimpleValue && option.NullCache == option.ZeroValue {
log.Fatalf("%s: %s 不能作为空缓存值 \n", option.name, option.NullCache) 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") { if strings.Contains(option.CheckNullCode, "len") && strings.Contains(strings.Replace(option.CheckNullCode, " ", "", -1), "==0") {
// -check_null_code=len($)==0 这种无效 // -check_null_code=len($)==0 这种无效
log.Fatalf("%s: -check_null_code=%s 错误 会有无意义的赋值\n", option.name, option.CheckNullCode) log.Fatalf("%s: -check_null_code=%s 错误 会有无意义的赋值\n", option.name, option.CheckNullCode)
@ -352,6 +374,7 @@ func (option *options) Check() {
func genHeader(opts []*options) (src string) { func genHeader(opts []*options) (src string) {
option := options{PkgName: os.Getenv("GOPACKAGE")} option := options{PkgName: os.Getenv("GOPACKAGE")}
option.UseBTS = interfaceName == "_bts"
var sfCount int var sfCount int
var packages, sfInit []string var packages, sfInit []string
packagesMap := map[string]bool{`"context"`: true} packagesMap := map[string]bool{`"context"`: true}
@ -464,7 +487,9 @@ func main() {
log.SetFlags(0) log.SetFlags(0)
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
log.Fatalf("程序解析失败, err: %+v", err) buf := make([]byte, 64*1024)
buf = buf[:runtime.Stack(buf, false)]
log.Fatalf("程序解析失败, err: %+v stack: %s", err, buf)
} }
}() }()
options := parse(pkg.NewSource(pkg.SourceText())) options := parse(pkg.NewSource(pkg.SourceText()))

@ -2,15 +2,19 @@ package main
var _multiTemplate = ` var _multiTemplate = `
// NAME {{or .Comment "get data from cache if miss will call source method, then add to cache."}} // 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 { if len({{.IDName}}) == 0 {
return return
} }
addCache := true addCache := true
if res, err = CACHEFUNC(c, {{.IDName}} {{.ExtraCacheArgs}});err != nil { if res, err = CACHEFUNC(c, {{.IDName}} {{.ExtraCacheArgs}});err != nil {
{{if .CacheErrContinue}}
addCache = false addCache = false
res = nil res = nil
err = nil err = nil
{{else}}
return
{{end}}
} }
var miss []KEY var miss []KEY
for _, key := range {{.IDName}} { for _, key := range {{.IDName}} {

@ -2,12 +2,16 @@ package main
var _noneTemplate = ` var _noneTemplate = `
// NAME {{or .Comment "get data from cache if miss will call source method, then add to cache."}} // 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 addCache := true
res, err = CACHEFUNC(c) res, err = CACHEFUNC(c)
if err != nil { if err != nil {
{{if .CacheErrContinue}}
addCache = false addCache = false
err = nil err = nil
{{else}}
return
{{end}}
} }
{{if .EnableNullCache}} {{if .EnableNullCache}}
defer func() { defer func() {

@ -2,12 +2,16 @@ package main
var _singleTemplate = ` var _singleTemplate = `
// NAME {{or .Comment "get data from cache if miss will call source method, then add to cache."}} // 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 addCache := true
res, err = CACHEFUNC(c, {{.IDName}} {{.ExtraCacheArgs}}) res, err = CACHEFUNC(c, {{.IDName}} {{.ExtraCacheArgs}})
if err != nil { if err != nil {
{{if .CacheErrContinue}}
addCache = false addCache = false
err = nil err = nil
{{else}}
return
{{end}}
} }
{{if .EnableNullCache}} {{if .EnableNullCache}}
defer func() { defer func() {

@ -27,12 +27,10 @@ import (
"github.com/bilibili/kratos/pkg/sync/errgroup" "github.com/bilibili/kratos/pkg/sync/errgroup"
) )
var ( var _ _bts
_ _bts
)
// Demos get data from cache if miss will call source method, then add to cache. // Demos get data from cache if miss will call source method, then add to cache.
func (d *Dao) Demos(c context.Context, keys []int64) (res map[int64]*Demo, err error) { func (d *dao) Demos(c context.Context, keys []int64) (res map[int64]*Demo, err error) {
if len(keys) == 0 { if len(keys) == 0 {
return return
} }
@ -111,7 +109,7 @@ func (d *Dao) Demos(c context.Context, keys []int64) (res map[int64]*Demo, err e
} }
// Demos1 get data from cache if miss will call source method, then add to cache. // Demos1 get data from cache if miss will call source method, then add to cache.
func (d *Dao) Demos1(c context.Context, keys []int64) (res map[int64]*Demo, err error) { func (d *dao) Demos1(c context.Context, keys []int64) (res map[int64]*Demo, err error) {
if len(keys) == 0 { if len(keys) == 0 {
return return
} }
@ -190,7 +188,7 @@ func (d *Dao) Demos1(c context.Context, keys []int64) (res map[int64]*Demo, err
} }
// Demo get data from cache if miss will call source method, then add to cache. // Demo get data from cache if miss will call source method, then add to cache.
func (d *Dao) Demo(c context.Context, key int64) (res *Demo, err error) { func (d *dao) Demo(c context.Context, key int64) (res *Demo, err error) {
addCache := true addCache := true
res, err = d.CacheDemo(c, key) res, err = d.CacheDemo(c, key)
if err != nil { if err != nil {
@ -223,7 +221,7 @@ func (d *Dao) Demo(c context.Context, key int64) (res *Demo, err error) {
} }
// Demo1 get data from cache if miss will call source method, then add to cache. // Demo1 get data from cache if miss will call source method, then add to cache.
func (d *Dao) Demo1(c context.Context, key int64, pn int, ps int) (res *Demo, err error) { func (d *dao) Demo1(c context.Context, key int64, pn int, ps int) (res *Demo, err error) {
addCache := true addCache := true
res, err = d.CacheDemo1(c, key, pn, ps) res, err = d.CacheDemo1(c, key, pn, ps)
if err != nil { if err != nil {
@ -250,7 +248,7 @@ func (d *Dao) Demo1(c context.Context, key int64, pn int, ps int) (res *Demo, er
} }
// None get data from cache if miss will call source method, then add to cache. // None get data from cache if miss will call source method, then add to cache.
func (d *Dao) None(c context.Context) (res *Demo, err error) { func (d *dao) None(c context.Context) (res *Demo, err error) {
addCache := true addCache := true
res, err = d.CacheNone(c) res, err = d.CacheNone(c)
if err != nil { if err != nil {

@ -13,13 +13,13 @@ type Demo struct {
} }
// Dao . // Dao .
type Dao struct { type dao struct {
cache *fanout.Fanout cache *fanout.Fanout
} }
// New . // New .
func New() *Dao { func New() *dao {
return &Dao{cache: fanout.New("cache")} return &dao{cache: fanout.New("cache")}
} }
//go:generate kratos tool genbts //go:generate kratos tool genbts

@ -12,37 +12,37 @@ var (
) )
// CacheDemos . // CacheDemos .
func (d *Dao) CacheDemos(c context.Context, keys []int64) (map[int64]*Demo, error) { func (d *dao) CacheDemos(c context.Context, keys []int64) (map[int64]*Demo, error) {
// get data from cache // get data from cache
return _multiCacheFunc(c, keys) return _multiCacheFunc(c, keys)
} }
// RawDemos . // RawDemos .
func (d *Dao) RawDemos(c context.Context, keys []int64) (map[int64]*Demo, error) { func (d *dao) RawDemos(c context.Context, keys []int64) (map[int64]*Demo, error) {
// get data from db // get data from db
return _multiRawFunc(c, keys) return _multiRawFunc(c, keys)
} }
// AddCacheDemos . // AddCacheDemos .
func (d *Dao) AddCacheDemos(c context.Context, values map[int64]*Demo) error { func (d *dao) AddCacheDemos(c context.Context, values map[int64]*Demo) error {
// add to cache // add to cache
return _multiAddCacheFunc(c, values) return _multiAddCacheFunc(c, values)
} }
// CacheDemos1 . // CacheDemos1 .
func (d *Dao) CacheDemos1(c context.Context, keys []int64) (map[int64]*Demo, error) { func (d *dao) CacheDemos1(c context.Context, keys []int64) (map[int64]*Demo, error) {
// get data from cache // get data from cache
return _multiCacheFunc(c, keys) return _multiCacheFunc(c, keys)
} }
// RawDemos . // RawDemos .
func (d *Dao) RawDemos1(c context.Context, keys []int64) (map[int64]*Demo, error) { func (d *dao) RawDemos1(c context.Context, keys []int64) (map[int64]*Demo, error) {
// get data from db // get data from db
return _multiRawFunc(c, keys) return _multiRawFunc(c, keys)
} }
// AddCacheDemos . // AddCacheDemos .
func (d *Dao) AddCacheDemos1(c context.Context, values map[int64]*Demo) error { func (d *dao) AddCacheDemos1(c context.Context, values map[int64]*Demo) error {
// add to cache // add to cache
return _multiAddCacheFunc(c, values) return _multiAddCacheFunc(c, values)
} }

@ -12,19 +12,19 @@ var (
) )
// CacheNone . // CacheNone .
func (d *Dao) CacheNone(c context.Context) (*Demo, error) { func (d *dao) CacheNone(c context.Context) (*Demo, error) {
// get data from cache // get data from cache
return _noneCacheFunc(c) return _noneCacheFunc(c)
} }
// RawNone . // RawNone .
func (d *Dao) RawNone(c context.Context) (*Demo, error) { func (d *dao) RawNone(c context.Context) (*Demo, error) {
// get data from db // get data from db
return _noneRawFunc(c) return _noneRawFunc(c)
} }
// AddCacheNone . // AddCacheNone .
func (d *Dao) AddCacheNone(c context.Context, value *Demo) error { func (d *dao) AddCacheNone(c context.Context, value *Demo) error {
// add to cache // add to cache
return _noneAddCacheFunc(c, value) return _noneAddCacheFunc(c, value)
} }

@ -12,37 +12,37 @@ var (
) )
// CacheDemo . // CacheDemo .
func (d *Dao) CacheDemo(c context.Context, key int64) (*Demo, error) { func (d *dao) CacheDemo(c context.Context, key int64) (*Demo, error) {
// get data from cache // get data from cache
return _singleCacheFunc(c, key) return _singleCacheFunc(c, key)
} }
// RawDemo . // RawDemo .
func (d *Dao) RawDemo(c context.Context, key int64) (*Demo, error) { func (d *dao) RawDemo(c context.Context, key int64) (*Demo, error) {
// get data from db // get data from db
return _singleRawFunc(c, key) return _singleRawFunc(c, key)
} }
// AddCacheDemo . // AddCacheDemo .
func (d *Dao) AddCacheDemo(c context.Context, key int64, value *Demo) error { func (d *dao) AddCacheDemo(c context.Context, key int64, value *Demo) error {
// add to cache // add to cache
return _singleAddCacheFunc(c, key, value) return _singleAddCacheFunc(c, key, value)
} }
// CacheDemo1 . // CacheDemo1 .
func (d *Dao) CacheDemo1(c context.Context, key int64, pn, ps int) (*Demo, error) { func (d *dao) CacheDemo1(c context.Context, key int64, pn, ps int) (*Demo, error) {
// get data from cache // get data from cache
return nil, nil return nil, nil
} }
// RawDemo1 . // RawDemo1 .
func (d *Dao) RawDemo1(c context.Context, key int64, pn, ps int) (*Demo, *Demo, error) { func (d *dao) RawDemo1(c context.Context, key int64, pn, ps int) (*Demo, *Demo, error) {
// get data from db // get data from db
return nil, nil, nil return nil, nil, nil
} }
// AddCacheDemo1 . // AddCacheDemo1 .
func (d *Dao) AddCacheDemo1(c context.Context, key int64, value *Demo, pn, ps int) error { func (d *dao) AddCacheDemo1(c context.Context, key int64, value *Demo, pn, ps int) error {
// add to cache // add to cache
return nil return nil
} }

@ -40,5 +40,6 @@ mc Add方法需要用注解 -type=only_add单独指定
| batch | | get(限多key模板) | 批量获取数据 每组大小 | - | 100 | | batch | | get(限多key模板) | 批量获取数据 每组大小 | - | 100 |
| max_group | | get(限多key模板) | 批量获取数据 最大组数量 | - | 10 | | max_group | | get(限多key模板) | 批量获取数据 最大组数量 | - | 10 |
| batch_err | break | get(限多key模板) | 批量获取数据回源错误的时候 降级继续请求(continue)还是直接返回(break) | break 或 continue | continue | | batch_err | break | get(限多key模板) | 批量获取数据回源错误的时候 降级继续请求(continue)还是直接返回(break) | break 或 continue | continue |
| struct_name | Dao | 全部 | 用户自定义Dao结构体名称 | | MemcacheDao | | struct_name | dao | 全部 | 用户自定义Dao结构体名称 | | MemcacheDao |
|check_null_code||add/set|(和null_expire配套使用)判断是否是空缓存的代码 用于为空缓存独立设定过期时间||$.ID==-1 或者 $=="-1"等|
|null_expire|300(5分钟)|add/set|(和check_null_code配套使用)空缓存的过期时间||d.nullExpire|

@ -1,7 +1,7 @@
package main package main
var _headerTemplate = ` var _headerTemplate = `
// Code generated by kratos tool mcgen. DO NOT EDIT. // Code generated by kratos tool genmc. DO NOT EDIT.
NEWLINE NEWLINE
/* /*
@ -25,7 +25,5 @@ NEWLINE
{{.ImportPackage}} {{.ImportPackage}}
) )
var ( var _ _mc
_ _mc
)
` `

@ -9,11 +9,12 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime"
"strconv" "strconv"
"strings" "strings"
"text/template" "text/template"
"github.com/bilibili/kratos/tool/pkg" common "github.com/bilibili/kratos/tool/pkg"
) )
var ( var (
@ -21,14 +22,16 @@ var (
mcType = flag.String("type", "", "type: get/set/del/replace/only_add") mcType = flag.String("type", "", "type: get/set/del/replace/only_add")
key = flag.String("key", "", "key name method") key = flag.String("key", "", "key name method")
expire = flag.String("expire", "", "expire time code") expire = flag.String("expire", "", "expire time code")
structName = flag.String("struct_name", "Dao", "struct name") structName = flag.String("struct_name", "dao", "struct name")
batchSize = flag.Int("batch", 0, "batch size") batchSize = flag.Int("batch", 0, "batch size")
batchErr = flag.String("batch_err", "break", "batch err to contine or break") batchErr = flag.String("batch_err", "break", "batch err to contine or break")
maxGroup = flag.Int("max_group", 0, "max group size") maxGroup = flag.Int("max_group", 0, "max group size")
checkNullCode = flag.String("check_null_code", "", "check null code")
nullExpire = flag.String("null_expire", "", "null cache expire time code")
mcValidTypes = []string{"set", "replace", "del", "get", "only_add"} mcValidTypes = []string{"set", "replace", "del", "get", "only_add"}
mcValidPrefix = []string{"set", "replace", "del", "get", "cache", "add"} mcValidPrefix = []string{"set", "replace", "del", "get", "cache", "add"}
optionNamesMap = map[string]bool{"batch": true, "max_group": true, "encode": true, "type": true, "key": true, "expire": true, "batch_err": true, "struct_name": true} optionNamesMap = map[string]bool{"batch": true, "max_group": true, "encode": true, "type": true, "key": true, "expire": true, "batch_err": true, "struct_name": true, "check_null_code": true, "null_expire": true}
simpleTypes = []string{"int", "int8", "int16", "int32", "int64", "float32", "float64", "uint", "uint8", "uint16", "uint32", "uint64", "bool", "string", "[]byte"} simpleTypes = []string{"int", "int8", "int16", "int32", "int64", "float32", "float64", "uint", "uint8", "uint16", "uint32", "uint64", "bool", "string", "[]byte"}
lenTypes = []string{"[]", "map"} lenTypes = []string{"[]", "map"}
) )
@ -51,6 +54,9 @@ func resetFlag() {
*batchSize = 0 *batchSize = 0
*maxGroup = 0 *maxGroup = 0
*batchErr = "break" *batchErr = "break"
*checkNullCode = ""
*nullExpire = ""
*structName = "dao"
} }
// options options // options options
@ -88,17 +94,20 @@ type options struct {
LenType bool LenType bool
PointType bool PointType bool
StructName string StructName string
CheckNullCode string
ExpireNullCode string
EnableNullCode bool
} }
func getOptions(opt *options, comment string) { func getOptions(opt *options, comment string) {
os.Args = []string{os.Args[0]} os.Args = []string{os.Args[0]}
if regexp.MustCompile(`\s+//\s*mc:.+`).Match([]byte(comment)) { if regexp.MustCompile(`\s+//\s*mc:.+`).Match([]byte(comment)) {
args := strings.Split(pkg.RegexpReplace(`//\s*mc:(?P<arg>.+)`, comment, "$arg"), " ") args := strings.Split(common.RegexpReplace(`//\s*mc:(?P<arg>.+)`, comment, "$arg"), " ")
for _, arg := range args { for _, arg := range args {
arg = strings.TrimSpace(arg) arg = strings.TrimSpace(arg)
if arg != "" { if arg != "" {
// validate option name // validate option name
argName := pkg.RegexpReplace(`-(?P<name>[\w_-]+)=.+`, arg, "$name") argName := common.RegexpReplace(`-(?P<name>[\w_-]+)=.+`, arg, "$name")
if !optionNamesMap[argName] { if !optionNamesMap[argName] {
log.Fatalf("选项:%s 不存在 请检查拼写\n", argName) log.Fatalf("选项:%s 不存在 请检查拼写\n", argName)
} }
@ -122,9 +131,16 @@ func getOptions(opt *options, comment string) {
opt.GroupSize = *batchSize opt.GroupSize = *batchSize
opt.MaxGroup = *maxGroup opt.MaxGroup = *maxGroup
opt.StructName = *structName opt.StructName = *structName
opt.CheckNullCode = *checkNullCode
if *nullExpire != "" {
opt.ExpireNullCode = *nullExpire
}
if opt.CheckNullCode != "" {
opt.EnableNullCode = true
}
} }
func getTypeFromPrefix(opt *options, params []*ast.Field, s *pkg.Source) { func getTypeFromPrefix(opt *options, params []*ast.Field, s *common.Source) {
if opt.MCType == "" { if opt.MCType == "" {
for _, t := range mcValidPrefix { for _, t := range mcValidPrefix {
if strings.HasPrefix(strings.ToLower(opt.name), t) { if strings.HasPrefix(strings.ToLower(opt.name), t) {
@ -160,7 +176,7 @@ func getTypeFromPrefix(opt *options, params []*ast.Field, s *pkg.Source) {
} }
} }
func processList(s *pkg.Source, list *ast.Field) (opt options) { func processList(s *common.Source, list *ast.Field) (opt options) {
src := s.Src src := s.Src
fset := s.Fset fset := s.Fset
lines := strings.Split(src, "\n") lines := strings.Split(src, "\n")
@ -168,11 +184,12 @@ func processList(s *pkg.Source, list *ast.Field) (opt options) {
opt.name = list.Names[0].Name opt.name = list.Names[0].Name
opt.KeyMethod = "key" + opt.name opt.KeyMethod = "key" + opt.name
opt.ExpireCode = "d.mc" + opt.name + "Expire" opt.ExpireCode = "d.mc" + opt.name + "Expire"
opt.ExpireNullCode = "300" // 默认5分钟
// get comment // get comment
line := fset.Position(list.Pos()).Line - 3 line := fset.Position(list.Pos()).Line - 3
if len(lines)-1 >= line { if len(lines)-1 >= line {
comment := lines[line] comment := lines[line]
opt.Comment = pkg.RegexpReplace(`\s+//(?P<name>.+)`, comment, "$name") opt.Comment = common.RegexpReplace(`\s+//(?P<name>.+)`, comment, "$name")
opt.Comment = strings.TrimSpace(opt.Comment) opt.Comment = strings.TrimSpace(opt.Comment)
} }
// get options // get options
@ -235,7 +252,7 @@ func processList(s *pkg.Source, list *ast.Field) (opt options) {
return return
} }
func getKeyValueType(opt *options, params, results []*ast.Field, s *pkg.Source) { func getKeyValueType(opt *options, params, results []*ast.Field, s *common.Source) {
// check // check
if s.ExprString(results[len(results)-1].Type) != "error" { if s.ExprString(results[len(results)-1].Type) != "error" {
log.Fatalln("最后返回值参数需为error") log.Fatalln("最后返回值参数需为error")
@ -352,7 +369,7 @@ func getKeyValueType(opt *options, params, results []*ast.Field, s *pkg.Source)
} }
} }
func parse(s *pkg.Source) (opts []*options) { func parse(s *common.Source) (opts []*options) {
c := s.F.Scope.Lookup(_interfaceName) c := s.F.Scope.Lookup(_interfaceName)
if (c == nil) || (c.Kind != ast.Typ) { if (c == nil) || (c.Kind != ast.Typ) {
log.Fatalln("无法找到缓存声明") log.Fatalln("无法找到缓存声明")
@ -476,6 +493,9 @@ func genBody(opts []*options) (res string) {
src = strings.Replace(src, "VALUE", option.ValueType, -1) src = strings.Replace(src, "VALUE", option.ValueType, -1)
src = strings.Replace(src, "GROUPSIZE", strconv.Itoa(option.GroupSize), -1) src = strings.Replace(src, "GROUPSIZE", strconv.Itoa(option.GroupSize), -1)
src = strings.Replace(src, "MAXGROUP", strconv.Itoa(option.MaxGroup), -1) src = strings.Replace(src, "MAXGROUP", strconv.Itoa(option.MaxGroup), -1)
if option.EnableNullCode {
option.CheckNullCode = strings.Replace(option.CheckNullCode, "$", "val", -1)
}
t := template.Must(template.New("cache").Parse(src)) t := template.Must(template.New("cache").Parse(src))
var buffer bytes.Buffer var buffer bytes.Buffer
err := t.Execute(&buffer, option) err := t.Execute(&buffer, option)
@ -494,13 +514,15 @@ func main() {
log.SetFlags(0) log.SetFlags(0)
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
log.Fatalf("程序解析失败, err: %+v", err) buf := make([]byte, 64*1024)
buf = buf[:runtime.Stack(buf, false)]
log.Fatalf("程序解析失败, err: %+v stack: %s", err, buf)
} }
}() }()
options := parse(pkg.NewSource(pkg.SourceText())) options := parse(common.NewSource(common.SourceText()))
header := genHeader(options) header := genHeader(options)
body := genBody(options) body := genBody(options)
code := pkg.FormatCode(header + "\n" + body) code := common.FormatCode(header + "\n" + body)
// Write to file. // Write to file.
dir := filepath.Dir(".") dir := filepath.Dir(".")
outputName := filepath.Join(dir, "mc.cache.go") outputName := filepath.Join(dir, "mc.cache.go")

@ -167,6 +167,11 @@ func (d *{{.StructName}}) NAME(c context.Context, values map[KEY]VALUE {{.ExtraA
{{else}} {{else}}
item := &memcache.Item{Key: key, Object: val, Expiration: {{.ExpireCode}}, Flags: {{.Encode}}} item := &memcache.Item{Key: key, Object: val, Expiration: {{.ExpireCode}}, Flags: {{.Encode}}}
{{end}} {{end}}
{{if .EnableNullCode}}
if {{.CheckNullCode}} {
item.Expiration = {{.ExpireNullCode}}
}
{{end}}
if err = d.mc.Set(c, item); err != nil { if err = d.mc.Set(c, item); err != nil {
log.Errorv(c, log.KV("NAME", fmt.Sprintf("%+v", err)), log.KV("key", key)) log.Errorv(c, log.KV("NAME", fmt.Sprintf("%+v", err)), log.KV("key", key))
return return

@ -72,6 +72,11 @@ func (d *{{.StructName}}) NAME(c context.Context, val VALUE) (err error) {
{{else}} {{else}}
item := &memcache.Item{Key: key, Object: val, Expiration: {{.ExpireCode}}, Flags: {{.Encode}}} item := &memcache.Item{Key: key, Object: val, Expiration: {{.ExpireCode}}, Flags: {{.Encode}}}
{{end}} {{end}}
{{if .EnableNullCode}}
if {{.CheckNullCode}} {
item.Expiration = {{.ExpireNullCode}}
}
{{end}}
if err = d.mc.Set(c, item); err != nil { if err = d.mc.Set(c, item); err != nil {
log.Errorv(c, log.KV("NAME", fmt.Sprintf("%+v", err)), log.KV("key", key)) log.Errorv(c, log.KV("NAME", fmt.Sprintf("%+v", err)), log.KV("key", key))
return return

@ -71,6 +71,11 @@ func (d *{{.StructName}}) NAME(c context.Context, id KEY, val VALUE {{.ExtraArgs
{{else}} {{else}}
item := &memcache.Item{Key: key, Object: val, Expiration: {{.ExpireCode}}, Flags: {{.Encode}}} item := &memcache.Item{Key: key, Object: val, Expiration: {{.ExpireCode}}, Flags: {{.Encode}}}
{{end}} {{end}}
{{if .EnableNullCode}}
if {{.CheckNullCode}} {
item.Expiration = {{.ExpireNullCode}}
}
{{end}}
if err = d.mc.Set(c, item); err != nil { if err = d.mc.Set(c, item); err != nil {
log.Errorv(c, log.KV("NAME", fmt.Sprintf("%+v", err)), log.KV("key", key)) log.Errorv(c, log.KV("NAME", fmt.Sprintf("%+v", err)), log.KV("key", key))
return return

@ -1,4 +1,4 @@
// Code generated by kratos tool mcgen. DO NOT EDIT. // Code generated by kratos tool genmc. DO NOT EDIT.
/* /*
Package testdata is a generated mc cache package. Package testdata is a generated mc cache package.

@ -0,0 +1,8 @@
// +build !skippackr
// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT.
// You can use the "packr clean" command to clean up this,
// and any other packr generated files.
package main
import _ "github.com/bilibili/kratos/tool/kratos-gen-project/packrd"

@ -0,0 +1,76 @@
package main
import (
"fmt"
"os"
"strings"
"github.com/urfave/cli"
)
var appHelpTemplate = `{{if .Usage}}{{.Usage}}{{end}}
USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description}}{{end}}{{if len .Authors}}
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
{{range $index, $author := .Authors}}{{if $index}}
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}{{end}}
`
func main() {
app := cli.NewApp()
app.Name = ""
app.Usage = "kratos 新项目创建工具"
app.UsageText = "name [options]"
app.HideVersion = true
app.CustomAppHelpTemplate = appHelpTemplate
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "d",
Value: "",
Usage: "指定项目所在目录",
Destination: &p.path,
},
cli.BoolFlag{
Name: "http",
Usage: "只使用http 不使用grpc",
Destination: &p.onlyHTTP,
},
cli.BoolFlag{
Name: "grpc",
Usage: "只使用grpc 不使用http",
Destination: &p.onlyHTTP,
},
cli.BoolFlag{
Name: "proto",
Usage: "废弃参数 无作用",
Destination: &p.none,
Hidden: true,
},
}
if len(os.Args) < 2 || strings.HasPrefix(os.Args[1], "-") {
fmt.Fprintf(os.Stderr, "未填写项目名称\n")
os.Exit(-1)
}
p.Name = os.Args[1]
app.Action = runNew
args := append([]string{os.Args[0]}, os.Args[2:]...)
err := app.Run(args)
if err != nil {
panic(err)
}
}

@ -0,0 +1,55 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/bilibili/kratos/tool/pkg"
"github.com/urfave/cli"
)
func runNew(ctx *cli.Context) (err error) {
if p.onlyGRPC && p.onlyHTTP {
p.onlyGRPC = false
p.onlyHTTP = false
}
if p.path != "" {
if p.path, err = filepath.Abs(p.path); err != nil {
return
}
p.path = filepath.Join(p.path, p.Name)
} else {
pwd, _ := os.Getwd()
p.path = filepath.Join(pwd, p.Name)
}
p.ModPrefix = modPath(p.path)
// creata a project
if err := create(); err != nil {
return err
}
fmt.Printf("Project: %s\n", p.Name)
fmt.Printf("OnlyGRPC: %t\n", p.onlyGRPC)
fmt.Printf("OnlyHTTP: %t\n", p.onlyHTTP)
fmt.Printf("Directory: %s\n\n", p.path)
fmt.Println("项目创建成功.")
return nil
}
func modPath(p string) string {
dir := filepath.Dir(p)
for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
content, _ := ioutil.ReadFile(filepath.Join(dir, "go.mod"))
mod := pkg.RegexpReplace(`module\s+(?P<name>[\S]+)`, string(content), "$name")
return fmt.Sprintf("%s/%s/", mod, strings.TrimPrefix(filepath.Dir(p), dir+string(os.PathSeparator)))
}
parent := filepath.Dir(dir)
if dir == parent {
return ""
}
dir = parent
}
}

@ -0,0 +1,174 @@
// +build !skippackr
// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT.
// You can use the "packr2 clean" command to clean up this,
// and any other packr generated files.
package packrd
import (
"github.com/gobuffalo/packr/v2"
"github.com/gobuffalo/packr/v2/file/resolver"
)
var _ = func() error {
const gk = "314eeeb23d475df0cf6cd2642a1621a3"
g := packr.New(gk, "")
hgr, err := resolver.NewHexGzip(map[string]string{
"14b27f88168b4f08f9d703f2a9b5027c": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece54efef9eff3fdef04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351ae6f3e9c2e430100c1d450e1e839c44d7df365f3eed6ed6ebdbdde7cbcde6ebfae66a1599e528b8fdbeba4c642f36b50dfbdad2f0a2e3e6e0f1ec6f85b9a8d83d60d418243eb64c41340592eabea8069563ef6da80cdc0d0060acb5ab6db44e30ea84a2b3678cab83fc783f9efc21e3a6b1421cce25bb4320c715ee1c8d07f176c835da466a57a37b30c73a82490cdca98fd7576a02aa9fa0ad3c050513d552d867aa751b59d871b312d7aaede96bf2c80731309ba623a420183bdb18284f30a244c294952380d113aa28bdd860cf5edb5e9ee862befc60727883a1bea0760da9c1cef6953ecfbb3f5afa77f31ebdb3aec6eae5157ce67f335196b3b2347d8437f8405773ce49aca47cf8a526002ab87c2e67cb625a4c8bb27fc8a5ffdbe6ef000000ffff0987409f7d030000",
"1769e4a13f3ecbd1dbb3698b5f8cae8a": "1f8b08000000000000ff4ccc310ec2300c05d0d93e859503547611022131710536c4109a0c969aa64a0d5c1f1918b2f9bfafefdb65d6bcd81d618925d399427c4c01616dd5aa479bd68010536a9e643c0c3cf020279151c49bc9f4e5c33d23689afd1446481ae7ab965c9ff61d32972d20b41c53c7e39fdf4d2d77befb391191ffec9a236f013f010000ffff1bfc1755b6000000",
"1794b30bcdd9584d5877963a3cb28504": "1f8b08000000000000ff8c535b6b1b3b107e5efd8a3982046d70b4e7e1701e5cfc10dc10426b3790b62fa504453bab08ebb2c8e3c4c6ec7f2f922f4dd2d2e66159edf25de69b19f54a2f9441685564ccfa3e2602c12aae63205c136715ef3c71c62abeddca596c6f1276763d0cdbad9c2b8fc3d0d8409882728d8f2dbacc30961e56f75247dfdc5b67f3d32c92a2b86cfa8569b4d20fd878f4e5f016420c5dd32ba75a1bde0077d1705633d634268e0d064c8a107600a0181d180c5e33daf408775e4349d0298db06555d380d763385fe066b2c0cd452238cfc8894162d534977c91c86a8742c3be4d72ba7b8fc0b659edffff6a1067a51f720f1e01a61453fd7b035cf736e1a4952dfa78593e5875d1b66fb51b814a042f1d6b1098d21f6c59f51e1dd241bf78fd25d333c181b16e1534ccf16936153508afe1ec305439db1f4aec3d2577f75125d09d8125a595a6fca79a3a8b819e71a73174d6b06a6095ed0a7f02fbe9cb2b24c18f488adef15a7e095ea5e583729f3fcd3e8a53dd99fa5de1fd3381605d714948ab148aa8d73001388accf149e8cec85d1d353b400f01450b67ad8a35dcd8606653a169fdba472f3a93ed8e75b7d26b798b945923383d9a5e13faed07dc8c81f736183e82afcaad700cdfbedf6f0805ef6330bc1e41590645368631fc3bfc9acb45232fb3afc8773614af9bebf955bdab469c3cd6bc0ca12ed95f65db2d82f839e125251b4c56de21a1f3246ffb64037582ab4477272dcf2b9117e047000000ffffe48ced133d040000",
"225361cfe91f8a3ee02db98f64637aa4": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece54efef9eff3fdef04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351ae6f3e9c2e430100c1d450e1e839c44d7df365f3eed6ed6ebdbdde7cbcde6ebfae66a1599e528b8fdbeba4c642f36b50dfbdad2f0a2e3e6e0f1ec6f85b9a8d83d60d418243eb64c41340592eabea8069563ef6da80cdc0d0060acb5ab6db44e30ea84a2b3678cab83fc783f9efc21e3a6b1421cce25bb4320c715ee1c8d07f176c835da466a57a37b30c73a82490cdca98fd7576a02aa9fa0ad3c050513d552d867aa751b59d871b312d7aaede96bf2c80731309ba623a420183bdb18284f30a244c294952380d113aa28bdd860cf5edb5e9ee862befc60727883a1bea0760da9c1cef6953ecfbb3f5afa77f31ebdb3aec6eae5157ce67f335196b3b2347d8437f8405773ce49aca47cf8a526002ab87c2e67cb625a4c8bb27fc8a5ffdbe6ef000000ffff0987409f7d030000",
"236ab314cd41c9b7b2c5194c0eb72bb1": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000",
"2f762fe51f2becdb8677b17926a52f03": "1f8b08000000000000ff849141ebd43010c5cf994f3116947629cd41bc547a58456ffe1156f09c4d67b361db244cd3ee4ac97797b4ab82081e8696c7bc97df6382d23765087b0b60c7e0396209a2d0de457ac4024411ed48058028d6b5f9e2fbaf4c17fb48695d9b1735524ad2ba48ecd42027e2c5ea7dd9d8789dcf8df6a33cdbc1e6913756d14f32dc8c1cbc29febfe5284a0e5ade15f7e40aa800a434be35e4885524bc5b26883f02e131049c22cf3ae20a625a341e9e38cd69ff82301c341ef6b04d25860470999dc617ba1f4328ff65acd1fce5aab05421e0e118428d7af0137dce1939a8ac6a24e63c9eab15445eecf0cd31841544066b715a740d62c369d1d42012883f29dd3327f7103a3e6ad4ca691ab0edf07996e6bb8dd76f76243fc7f297f641e99b613fbb3e33bc7d77c8876b4ea4bdeb2b10c25e36b0b643d39cae73ecfddd953a3eaaf79bfeaa436787ed513178d37cca05ca22439e78f9edd88b95af97aad88ae6e4b4176b3ee60e655676e2fc9b4030c5991d24f8190000ffffb30c321d6c020000",
"33550cc0d0a7c442ee2f7ef103747430": "1f8b08000000000000ff94525d6b1341147deefc8acbbe34817697ea5b421ea4162a88865a9f44c26473b35ddddd99ce4c164308d454a84a35554a4b3f1eaa54e98bad20546a2dfd31c926e9bf90d9ec2682ed83f3321ff79c7bce3dbb9605d1f16ef7eccdd5a7b3fede31dc29de83feee2be0822906bdadb5eef92944ed93eef9976863bdb77dda6bb70797dfc15928ce42f4711de617178b9a452c6b482ad7aa092f6ab7062bab395d816958528acb9c655530448f7114d27418733c346de65b31d566de74b956ada2901691f540d117500023aedd36f284b83e674281e1b86aa9568e890e7398950ac7b7f8129fccf868e4c7bc58700c479fabfa4d28ca5d8b06015354b92c9023583c29b59f530721fa70116dbceb5e5cf6378fa04139772b4db311a2902e0b9a3ac9ded659f4bb3d05c91b44179fa3af2d0867a620bc05a649d25615f499295184ae8d663833d479f070712e07bdfd9568e3fde0e467f4fae06ae77070b9d3fdb5d7db3ee86f1e69851f47576b6f21d369ed4f775afbd9cecbc3ceea372084716d1c1c564a350a6050ee1af9b49419e565267bc941a550c812f5bc2c14a04a3d897942126370177d060d020020b80d45377020937ec83457734ee79a0581aa26027923204f26749347b43e8f9ec720136f0bb8fcdfd4c70bf7af23274f926713cf7a8d678f1b53ee9afadfd4d38e417a39a8728645cbb62569bdb4a47b192340334f92ad49888f52ea7c530bd0201352091d4e407d9dfb0c3cf92b6c9f0954d491d9c26495093f6768940121f5dc0a559833042ed75c811563f2e9750292275613915916280cd43f3acf240b1475f46893f610336cf8270000ffff68dc4476f7030000",
"336d416ed5faa95a29de7b6afd385568": "1f8b08000000000000ff9452c18adb30103d6bbe626a285890daf41a9a43296d37870d69939ccb441e3b4364c94832ddc5f8df8b9ca56c4a0fedc1467af39ee6e98d063257ea187b120720fde043c21254d15aea0a50858fb77f1da57364f3263e4743765926e9b90050c534558fbed9076ee5699ea7a9da51cff35c8b4b1c1cd9ba91ccef245dc673657c5f9fc54afeea6ba0e4633d5cbbda78d7d603596ac4fd03ddfaae000dd08ece2c3728354ea0b2f56a4f2172a94159df555b27a9746235d635367c1e3bcca435e6622361330d942e33a8865b0e0bfac9fad7fad697059d0dc64421151ad48bcbdbd11ad48f159a2cf9323ab3420e01d71b6c64a97f1c864c9176c1df6cd089cd46d5404e4cc9216850332893353d5db9341772e8637558425fe17b0dea36806ae793b4cfa559e1cb1caac3f6ebc3697fb7ff76da1eef80e3e7ef8f77c07677d4a05a1f16233177fef0ce807a75df8e1312dedae2db58ac30568714c475a5d659f45392b9605c4e3014f9bf1dac4129f53bb69c91fa236f7e92256ea5f253ab0e9679286f4b36de354b29701a83fb8b8987d33eb768b8a5d1a6f51d77ce91cff02b0000ffff37cebd8001030000",
"348f254eb8f48eaf3d0330c83c18324c": "1f8b08000000000000ff9451c18ea3300c3de3afb038255d44be600fedf6b28756d5767f2010173c85240aa18c84f8f711d0a9462355ea9c78f8bd3cdbcf4ae1afa2e7c6e0c081d8be51194129fc5f13aef5a82b6cf5953aecfa40186bc22ef6057287d6c5451491ed425cd8ea667d9703785d5e75456818805bef424401892f301dc7fce0cc29d085dfa7691cf3a36e699a94f69c42f294661b2958dd28a3dd4bba8ec28d82aa822f7fa2af63f42febb9a41420492b8e755fe4a56b55e55cd5909a134d4102dc7440a3dd29b81b1b0af87b093b3fd270a6288c7633ccf00ef6bb07fc4786bbc7dfe18f5cacee5d9fd8ddd9d57221766c8db034085fe47b6add79d9526638d7369ffaf3fa9552025c7a5be25fcb71ebbd9028365bef339cab42664821b8207184c46bcba5589bcc47175fb6ccbecf99e19ceb3ad77c91151d69d87a2f254cf0110000ffffb4884e698c020000",
"359dcf82ea381d6901e53f88ff235896": "1f8b08000000000000ff94525d6b1341147deefc8acbbe34817697ea5b421ea4162a88865a9f44c26473b35ddddd99ce4c164308d454a84a35554a4b3f1eaa54e98bad20546a2dfd31c926e9bf90d9ec2682ed83f3321ff79c7bce3dbb9605d1f16ef7eccdd5a7b3fede31dc29de83feee2be0822906bdadb5eef92944ed93eef9976863bdb77dda6bb70797dfc15928ce42f4711de617178b9a452c6b482ad7aa092f6ab7062bab395d816958528acb9c655530448f7114d27418733c346de65b31d566de74b956ada2901691f540d117500023aedd36f284b83e674281e1b86aa9568e890e7398950ac7b7f8129fccf868e4c7bc58700c479fabfa4d28ca5d8b06015354b92c9023583c29b59f530721fa70116dbceb5e5cf6378fa04139772b4db311a2902e0b9a3ac9ded659f4bb3d05c91b44179fa3af2d0867a620bc05a649d25615f499295184ae8d663833d479f070712e07bdfd9568e3fde0e467f4fae06ae77070b9d3fdb5d7db3ee86f1e69851f47576b6f21d369ed4f775afbd9cecbc3ceea372084716d1c1c564a350a6050ee1af9b49419e565267bc941a550c812f5bc2c14a04a3d897942126370177d060d020020b80d45377020937ec83457734ee79a0581aa26027923204f26749347b43e8f9ec720136f0bb8fcdfd4c70bf7af23274f926713cf7a8d678f1b53ee9afadfd4d38e417a39a8728645cbb62569bdb4a47b192340334f92ad49888f52ea7c530bd0201352091d4e407d9dfb0c3cf92b6c9f0954d491d9c26495093f6768940121f5dc0a559833042ed75c811563f2e9750292275613915916280cd43f3acf240b1475f46893f610336cf8270000ffff68dc4476f7030000",
"39a955dfabc5df68502b59574724045e": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000",
"40aa45750f8397d706e3d8fdd82fa11f": "1f8b08000000000000ff5ccc410a02310c85e175728a210728ad8283822bafe04e5cc4268b40673a74a25e5f2a0832cbff83f76e97623afb1d61e64987f340fcc884b0b4eab5a7e7851058a4f54abb31c410433a1df6e391104c4a5fa588c0d9edf50b312e579bb43efdbb5b09a129cbd6decd5cb7d84fff2dae849f000000ffffe1039f77a9000000",
"43befbfad04c8efdf57be993ceb9e432": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000",
"46713bf4406bd2896c32e5778efb1eb5": "1f8b08000000000000ff8c53516e133110fdb64f31b144e54591f7bf281fd0464140d3aa69c527f23ab3bb56bcf6e2f5a691a21c831b803800df1ca79c03d9bb698b2a041f96ecf1cc7bf39ec7ad541b5921d421b494eaa6753e00a784590c790c324a495b00dbefc5855b5f792cf5ee70d8efc552367838e4b2d58c92bf5e6b1bd05b69f2c6add1c4cc4a87ba2f84724d5e68a3e3ca375e06d7e5eda6ca95b365de4a23d7dafe47ba7115a3a468e05f89473d7961e41a1bd905f48c66946ea5876eaba02dc439366e857e8b9ed23c8725de81c53b905034d0a5b8a0656f55bce1dd9f151970b495b6082f8b46ccd3760ae87d5cce67b0a72452714a48ada00bbe57210609190052ddb03d73b6d41525e4404946892e13ce0c465bc4020367518c08ae312c13b7b691beaba5b9b9bcf8c04f6a95bd4a259319586d12cb08327944997bbf7461bed3ddd887c7d07b3bd09281d16a43e3311a34838e9251e30c8a469c63297b13869e79adc6eeb33830e21a2b1d3d8e0ebdb9187370b4a58baaac0ed7ae0f0fe18c8ea4c351ac82f48167f4d8d7810ee63f2d7c62767218c595b6156fb5ad324a2a389d018a85777dcb592e0bc5324aa2d64a2ce6379ce55de46053a8dddd8d4b8459d47ba48a385c855da2397336e02e241e5dc2a7e1754f67717a065a1576d368d973f78daba2dfce7316318799e02fb6194b28192544859d785d381f3eea50af820c7dc7d31b0ffbe8a056786be5566a230b83c74ef31c70279bd62094cea79f0c1e3ff7d805a8a55d9b87b17d54c9d533499b28e5247d53f13efd9bd8f85b34c69d025b38236d05f75fbffffaf1e5fedb4f984c266c9a66438977abcb25df0cd2e9e177000000ffffb265211b53040000",
"468e50d126ac1e7c1a9ea44dde207990": "1f8b08000000000000ff8c53516e133110fdb64f31b144e54591f7bf281fd0464140d3aa69c527f23ab3bb56bcf6e2f5a691a21c831b803800df1ca79c03d9bb698b2a041f96ecf1cc7bf39ec7ad541b5921d421b494eaa6753e00a784590c790c324a495b00dbefc5855b5f792cf5ee70d8efc552367838e4b2d58c92bf5e6b1bd05b69f2c6add1c4cc4a87ba2f84724d5e68a3e3ca375e06d7e5eda6ca95b365de4a23d7dafe47ba7115a3a468e05f89473d7961e41a1bd905f48c66946ea5876eaba02dc439366e857e8b9ed23c8725de81c53b905034d0a5b8a0656f55bce1dd9f151970b495b6082f8b46ccd3760ae87d5cce67b0a72452714a48ada00bbe57210609190052ddb03d73b6d41525e4404946892e13ce0c465bc4020367518c08ae312c13b7b691beaba5b9b9bcf8c04f6a95bd4a259319586d12cb08327944997bbf7461bed3ddd887c7d07b3bd09281d16a43e3311a34838e9251e30c8a469c63297b13869e79adc6eeb33830e21a2b1d3d8e0ebdb9187370b4a58baaac0ed7ae0f0fe18c8ea4c351ac82f48167f4d8d7810ee63f2d7c62767218c595b6156fb5ad324a2a389d018a85777dcb592e0bc5324aa2d64a2ce6379ce55de46053a8dddd8d4b8459d47ba48a385c855da2397336e02e241e5dc2a7e1754f67717a065a1576d368d973f78daba2dfce7316318799e02fb6194b28192544859d785d381f3eea50af820c7dc7d31b0ffbe8a056786be5566a230b83c74ef31c70279bd62094cea79f0c1e3ff7d805a8a55d9b87b17d54c9d533499b28e5247d53f13efd9bd8f85b34c69d025b38236d05f75fbffffaf1e5fedb4f984c266c9a66438977abcb25df0cd2e9e177000000ffffb265211b53040000",
"470fd5cab5c7a57cec62609827d2c84f": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b4b03030325b04c49666e6a7e690948d2b058890b100000ffffb9f9177936000000",
"473893d607815c5c27cec94e0e78e437": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000",
"48e53a59007a8dda61d904d989943a09": "1f8b08000000000000ff5ccdc14ec3300cc6f1f3fc143ec2614e9c32525e827748db6022927964c98434f5dd51e15238f862fdfefa8a2e3d47bcdfe93594b8ae00a2c8c40ea0c6cf9e6ac407404494d4defb44b31633a59cb6331f3534bd6209d7162b1c764454d45caa369dfa1bde981cf13f90c359fe90811c1c7effa455cc9739c786374b96ecd1597eb1cf6ee4f1343c9d8e4be0c1cf7ef4bcf82d52c99176add4cbfc33ebc8c2237c070000ffff34bdd5b6e6000000",
"49d0cdb7406397b8e77616d290bcd94f": "1f8b08000000000000ff5492b18ed4301086ebcc530c96901294b5fb95b65836cd35b72be005bc5ec7589b782c674240e80a3a4a0a7a90780c5e0771af81622f3a5d916226ffffcdf8b7a33657ed2ceae8c18f9112630d953014d87e640195e847160095709edfcf67696854673ff8f553d7a4992615af4e05cb2a45a3169d2e361407911bac7434e8e02425a75c8a464003a014ee63bceb5082a130f1addaa17877ec8e5bdc771dee4f27bceb4416dfdbe530781b18835d70c5a0c935f473304fbf6bd33b7c557690a575a0d07bd722459e504ab99a65e7f5708cec2934587776a4a26dd1a644a9c1cf50153e6e7778c33d1b527852ca062a63b26f951653c6d7b70ce56b6dae2ed11c2e75d3623fb27c1b930fdcd7e2e227431f6cfab455ea627b3d0fac5e4ea22d71340d54becfe8173b0c7e58d7aa92e53985b5cc53a17a80ffbd7bbb3c9da536a66957193ce4081fbffff8fbf51bba37a703fef9fdebf1e71750cad1d6d96093668be5329189068c89980c6e3639eacde63cae2f44e636fc0b0000ffff940f602534020000",
"4ee76ca4d3f34ada842b90d87762fe26": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000",
"518b74b34be782fd3abced06105dfdf1": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000",
"532d363951d4f0d0c18e620c67cb7b40": "1f8b08000000000000ff94924d8fdb2c1485d7f02bae2cbd919d3782fd48594d2b75914ca34c475d5f63eca0606030ee24b2fcdf2bfc91499ba61f0bb004c7f79c877b1d8a2356121ae9bf29212955b5b33e404a4922ac09f214124a92b20e09a5c4e590741ddbda62e765a94e7ddf75ec096bd9f71c9d8aca7bd7ca04e90d6a5ea08dba4a85439b33616b9e2bade2e2478fc136dc1d2b2eac29b9438d8532d1f95a5f598da6e2cedb60f3b6e42e9c9d6cb8ac5d382734a39473781e79662e46a3e6fd34f85604e8284101b09c7cd8161d25055a28d0b20f68693fd47a926f60e41be05c0dd014e06568bd61b46c8d8892b4987fcb206d603979ad407a1f97f559346c600d8be9aea384a0780058cc09be7cde6eba7e45498cf100c58a929e9258610db3e62b06714813744e2b814159c382ad75b28286a1c82819934de19ff1fc496a6da1f24e40216b0b31f194fb2a687691a6229c606a3e7b1cbf2bf0f215962e6783642f5f3348bd74fa0ccbe1e1d9c7b8ff4c3b2ad6f1f9d22b5946495907b6f3ca84324d0e43c0ff9a64701926e61ec6cb7e0379fd771c2ffbcdbfa2bc1f36ee1ecbe25a145b38d435e101269004febf708c0dbc856dbdfe3df04e990a5cdcc24182978d6d7d9ce35bdca8fc35a7fca13719a437adbaa04567585c5d777d9ca738d173fd6c4af6a86d23410cfb9fb20dda741cfca1d874407bfa3d0000ffff0c06c20f7a040000",
"56d831af18f731847e4733aa321128cb": "1f8b08000000000000ff84914fcb9c3c14c5d7b99fe2bec25b74906451bab1b89896a7bb3e14a6d0758c77348c26215e9d29e2772fd1e99f45a18b8b7239e7e477b8419b9bee085b0b60c7e023630e2233de313d380391b11d290310d9bacacfbefd12e96a1fdbb6aef2558fb46dca3aa6e8f4a0268a8b3587b8b3dccf8d347e548d1d6c1a758b9afda4c2ad5383ef3210cd88ff123a62d53307d50cbaa5514f4c31830240a9ce571d398a9a09ef3612f0f740780e01278eb3615c414c8bc1d3934b5e8e2f881488a766942faeb38e6003b8cecee02bddcf21e47f3395d8ffe12830d721e0e91c428966f0137d4afe14921725528c697c2c56104958e39b73082b880454e1b49812c48e51615f82d840fc4ea99f39895f187e9468b433346055e3f32ef29be5feab1dc9cf9cffdc7dd0e6d6453fbb3631bc7d774a97931732deb5050861af3b5855632f2ffdccadbfbbdcf0a378bfefffabd1d9617f540cbe932fa9409e25c84b5c7e398e62f9ff4b91ed4553f27614931f53873c6d0ee2f4bb8188c47374b0c18f000000ffffadf6f33a6d020000",
"5d243c2aa906cb9527df41e508cda83d": "1f8b08000000000000ffa492516bdb3010c7dff3290ebde42572e384259b200f657d5cc9d614c6564250e55b7cd4d279d2c550d8871f72dd242bdda0ece54efef9eff3fdef04d0614cc4c1809a174b350248183b7298cc0800a0ba7fca00e4ed1e0df8c7f4b331ef8ac5805b8e929e351ae6f3e9c2e430100c1d450e1e839c44d7df365f3eed6ed6ebdbdde7cbcde6ebfae66a1599e528b8fdbeba4c642f36b50dfbdad2f0a2e3e6e0f1ec6f85b9a8d83d60d418243eb64c41340592eabea8069563ef6da80cdc0d0060acb5ab6db44e30ea84a2b3678cab83fc783f9efc21e3a6b1421cce25bb4320c715ee1c8d07f176c835da466a57a37b30c73a82490cdca98fd7576a02aa9fa0ad3c050513d552d867aa751b59d871b312d7aaede96bf2c80731309ba623a420183bdb18284f30a244c294952380d113aa28bdd860cf5edb5e9ee862befc60727883a1bea0760da9c1cef6953ecfbb3f5afa77f31ebdb3aec6eae5157ce67f335196b3b2347d8437f8405773ce49aca47cf8a526002ab87c2e67cb625a4c8bb27fc8a5ffdbe6ef000000ffff0987409f7d030000",
"5d2e61f4f8ab5957f172a990d9fb3baf": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2de202040000ffffbe75c21514000000",
"5e8471dec0685b7154cd71dcf0444643": "1f8b08000000000000ff94525d6b1341147deefc8acbbe34817697ea5b421ea4162a88865a9f44c26473b35ddddd99ce4c164308d454a84a35554a4b3f1eaa54e98bad20546a2dfd31c926e9bf90d9ec2682ed83f3321ff79c7bce3dbb9605d1f16ef7eccdd5a7b3fede31dc29de83feee2be0822906bdadb5eef92944ed93eef9976863bdb77dda6bb70797dfc15928ce42f4711de617178b9a452c6b482ad7aa092f6ab7062bab395d816958528acb9c655530448f7114d27418733c346de65b31d566de74b956ada2901691f540d117500023aedd36f284b83e674281e1b86aa9568e890e7398950ac7b7f8129fccf868e4c7bc58700c479fabfa4d28ca5d8b06015354b92c9023583c29b59f530721fa70116dbceb5e5cf6378fa04139772b4db311a2902e0b9a3ac9ded659f4bb3d05c91b44179fa3af2d0867a620bc05a649d25615f499295184ae8d663833d479f070712e07bdfd9568e3fde0e467f4fae06ae77070b9d3fdb5d7db3ee86f1e69851f47576b6f21d369ed4f775afbd9cecbc3ceea372084716d1c1c564a350a6050ee1af9b49419e565267bc941a550c812f5bc2c14a04a3d897942126370177d060d020020b80d45377020937ec83457734ee79a0581aa26027923204f26749347b43e8f9ec720136f0bb8fcdfd4c70bf7af23274f926713cf7a8d678f1b53ee9afadfd4d38e417a39a8728645cbb62569bdb4a47b192340334f92ad49888f52ea7c530bd0201352091d4e407d9dfb0c3cf92b6c9f0954d491d9c26495093f6768940121f5dc0a559833042ed75c811563f2e9750292275613915916280cd43f3acf240b1475f46893f610336cf8270000ffff68dc4476f7030000",
"64f157c0a5aaef8684ce174785fdb08b": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2de202040000ffffbe75c21514000000",
"65c9c5ceead4379a32ef56fe8044a9a7": "1f8b08000000000000ff8451cb8adc30103cabbfa2f121486191be604ec9924b7612f2f8008da6ed15634ba2255b0bc6ff1e641b1672d9435fbaaabaaae864ddc30e84032707e0a714b9a004916ed8adab7e89f79f4cbd7fdbb675d5573bd1b6199b7c0720bac197d7f9a65d9ccccd8fbe8d79b02d319bf4188c8ba137c98ef6ee43f7313d50319c9ca996ef143a5000c6e0952a06aa68f784988917620dfd1c5cc3645e1ca69bfe4a53fcbd630a65cdf8f9b8a28fdd1312739bc80a57108b656487b9f0ec4a5b8883f79fec4b0cbd1f406c209afe826719fd8d8aec5a1e5de234764aff0d93e5fc6ac73f3f5ebecb4fec1408dfefae9777d933f33596e7379f0fd3e368f0e36e51335ef0f4bf523d2248766718d57ea27fd1e073217eef2b6b3e19523d615e9a75cd47e30b36b0582e5281602a3307d8e05f000000ffff90051aa3f4010000",
"6640f2771831eddce9f1132a8ffa02b1": "1f8b08000000000000ff8c90cd8adb3010c7cfd6534c75285258a44be9a5e4d0dd855e36e9f7038cf515115972e4719362fceec58e0ba5a73d0c0231bff97ff468ce181c582c8cc5ae2f9540b0869b92c9dd8833d6f069528762bf54e7e36d9ea7491db173f3ac6326573326dd15eb12670d0f914e63ab4ce9741b535c469f2b5219747f0eda94ec758f096dccaf58b748d8e2e0f470499c49c6fc980d1cddf5f9514810b685dd7049eaf9f1015cadcb942a6162cd2fac607c8081ea6868f9699e527499eec053c93e06d6ccac897e45f7b0b9529f1c096e5b45a54b5caa9fb9c33a9c30fdf87c78116f8d0ff2c34abcd9438e693d5d1d8d35afe76c0b7b58248eee7af8fdfdeb8b303ea8bbb6647f37e72d89b0b0b358247cc3ebc74ad124270cdd60eb7ef1b9bc0f102dc44cefdf49105809766bdf6a43fe0faf350447b09407be960e6cfb8ff29f000000ffffed2515fbf0010000",
"676482aadd24e9539226c67ebd8b5d04": "1f8b08000000000000ff8c90cd8adb3010c7cfd6534c75285258a44be9a5e4d0dd855e36e9f7038cf515115972e4719362fceec58e0ba5a73d0c0231bff97ff468ce181c582c8cc5ae2f9540b0869b92c9dd8833d6f069528762bf54e7e36d9ea7491db173f3ac6326573326dd15eb12670d0f914e63ab4ce9741b535c469f2b5219747f0eda94ec758f096dccaf58b748d8e2e0f470499c49c6fc980d1cddf5f9514810b685dd7049eaf9f1015cadcb942a6162cd2fac607c8081ea6868f9699e527499eec053c93e06d6ccac897e45f7b0b9529f1c096e5b45a54b5caa9fb9c33a9c30fdf87c78116f8d0ff2c34abcd9438e693d5d1d8d35afe76c0b7b58248eee7af8fdfdeb8b303ea8bbb6647f37e72d89b0b0b358247cc3ebc74ad124270cdd60eb7ef1b9bc0f102dc44cefdf49105809766bdf6a43fe0faf350447b09407be960e6cfb8ff29f000000ffffed2515fbf0010000",
"6cc24b961eaafa6a5726c5e875dd92ae": "1f8b08000000000000ff4ccc310ec2300c05d0d93e859503547611022131710536c4109a0c969aa64a0d5c1f1918b2f9bfafefdb65d6bcd81d618925d399427c4c01616dd5aa479bd68010536a9e643c0c3cf020279151c49bc9f4e5c33d23689afd1446481ae7ab965c9ff61d32972d20b41c53c7e39fdf4d2d77befb391191ffec9a236f013f010000ffff1bfc1755b6000000",
"7a53e746d0de690c8b20ca83292508c5": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000",
"80a49866e2154ebe00c57fd7c80a4cab": "1f8b08000000000000ff8c51416e8330103cb3af5871b253845fd043d25c7a481435fd80c11bb20dd89631a112e2ef15904655a54839793d339edd1d2b852f45c7b5c19e03b1fda2328252f879265cf0a82b6cf4855a6cbb4018cf846dec0ae416ad8bb32822db9938b1d5f5f22e07f0babce88ad0300037de858802125f603a0cf9ce9943a0137f8fe330e47bddd0382aed3985e421cd3652b0ba5646bba7742d852b0555055f3eade792528024ad389ebb222f5da32ae7aa9ad494500a12e0aa031aed0ec15dd950c0d739bc7c4ffd91a230da4d6586b762bbb9971f64b8bddf766f72b6ba757d60776317cb99d8b035c2522f7c916fa971c7794b99e184ad7ef5c7e59452029c3a5be2bbe5b8f65e4814abb5f7194ea8901952082e481c20f1da72299626d3278a3f5b66ffe7cc70ca75996b4ffdda7b2961849f000000ffff98b3536b52020000",
"885a5148286f0720126cd2a540b56564": "1f8b08000000000000ff4ccc310ec2300c05d0d93e859503547611022131710536c4109a0c969aa64a0d5c1f1918b2f9bfafefdb65d6bcd81d618925d399427c4c01616dd5aa479bd68010536a9e643c0c3cf020279151c49bc9f4e5c33d23689afd1446481ae7ab965c9ff61d32972d20b41c53c7e39fdf4d2d77befb391191ffec9a236f013f010000ffff1bfc1755b6000000",
"89e787ea2b6d77d3061b5e56a50c6e36": "1f8b08000000000000ff8c91cd6ae33010c7cfd653cc0a769182911f60c9291bc2c26e1a9af45c14595244648d91e53450f2ee45b25328bde42004c3ffe3374c2fd5595a0dad44425cd7634cc048451586a4af89125251ebd2693c0a855d7374dee5d79ca34c3834fdd9364aaa936ea26edd401f5063304d2fbd6c5d7840eed152c209316350b0d56fcfb98671601116a55294490d3ac6fc30727827d5454650c6c290e2a8529e542bef744877d70a8371965437523953cc4b98a9c44627462759c2ce532e5e4227e37092fef0f4ff1ffba58ce5bf8be9c71282f3253fea34c6501273d8e4ff2456c68a898093bbf436afc55a58b41239ec5cb0b33c5d613e4146cd3f07f6754767e0b59ed15b31f5fdc16cad81eed7075a03ed5db0e5c760e977668f56ac7320cb070f62af13dbfddd6ef854c37e5e382d157cda6be6fe080000ffffb73c6a1735020000",
"8f2519501a642ae50acf464ad3acb9f9": "1f8b08000000000000ff8c51c16eab30103cb35fb1e264e721fc05ef90bc5cde2151d4f4070cdec036605bc6844a887faf8034aa2a45cac9eb99f1ecee5829fc53f4dc181c3810db0f2a232885ef35e18a475d61abafd461d707c2581376b12f903bb42e2ea2886c17e2c25637ebbb1cc0ebf2aa2b42c300dc7a17220a487c81e938e607674e812efc394de3981f754bd3a4b4e71492a734db48c1ea4619ed5ed275146e14541da37f59cf25a500495a71acfb222f5dab2ae7aa86d49c500a12e0a6031aed4ec1ddd850c0bf4b78f99186334561b49bcb0cefc57ef728dfc870f7b81dfec9c5eadef589dd9d5d2d1762c7d6084b83f045bea7d69d972d658633b6f9d69fd7534a0970e96d89ff2dc7adf742a2d86cbdcf704685cc90427041e20889d7964bb136993f51fcd832fb3d678673aeeb5c471ab6de4b09137c050000ffffe1cf2bb052020000",
"959fd518960ea8b397538a6f7b1bdd3a": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"95d28ebee82ae43dfc0c8b16b6088b2d": "1f8b08000000000000ff5ccdc14ec3300cc6f1f3fc143ec2614e9c32525e827748db6022927964c98434f5dd51e15238f862fdfefa8a2e3d47bcdfe93594b8ae00a2c8c40ea0c6cf9e6ac407404494d4defb44b31633a59cb6331f3534bd6209d7162b1c764454d45caa369dfa1bde981cf13f90c359fe90811c1c7effa455cc9739c786374b96ecd1597eb1cf6ee4f1343c9d8e4be0c1cf7ef4bcf82d52c99176add4cbfc33ebc8c2237c070000ffff34bdd5b6e6000000",
"97e4f2cf9f4ad4fc842f20a7fb124f91": "1f8b08000000000000ff94924f8bdb3010c5cf9a4f3135b4d8c14887d28b4b0e69d9deba1452e859916765115b12f2d84931feee454efa97c2b687c1c3f0e6e7f7c68eda9cb5256c1d801b62488c2588c204cf74e50244c16ea0024014cb223f86f653a227775dd765918f7aa07555ce3325af7b35529a9db989ade36e3a4913067572bdcba5ce497318553c5bd5075b80380df89cd013ab8e39aa53af5b1af4c8948ae7f9792d45a32e3ab5e40ba80094b2a1b1e4296926bcb844c05f23e121461c394d86710131ce0677f720f2787b82c80e70771ae483b7ce13089ba2c1dd8dbec928c10af03479838f7439c458fe8d5463f70ba646fb07a3c252c788bb438c359a3e8cf4211333b6ac6aa4947285542d20b2708faf0e312e20b2ef06c7d9d42036b70d76b9cd3e1bb4358815c44fe0fe8ecc8985e16b8d467b433d367bbc7f7af9c571f7d90d14262ebfcfde6973b6294cbecd765ebfd9e59f431ec904df5620847bda3c367bb4f2d84ddc868b2f0d5fabb7dbfcc51ebdebb7978a3e58f990b3944536794cf38f8d5bc6f2e55c155be64c5e7fa377ff41cfd7f817fa381bf93e5fa8cc93db3d72bb8248c453f2b0c2b7000000ffff73be5e8b2e030000",
"984dd6df0bfb1684d6d188b40962ca7b": "1f8b08000000000000ff8451cb8adc30103cabbfa2f121486191be604ec9924b7612f2f8008da6ed15634ba2255b0bc6ff1e641b1672d9435fbaaabaaae864ddc30e84032707e0a714b9a004916ed8adab7e89f79f4cbd7fdbb675d5573bd1b6199b7c0720bac197d7f9a65d9ccccd8fbe8d79b02d319bf4188c8ba137c98ef6ee43f7313d50319c9ca996ef143a5000c6e0952a06aa68f784988917620dfd1c5cc3645e1ca69bfe4a53fcbd630a65cdf8f9b8a28fdd1312739bc80a57108b656487b9f0ec4a5b8883f79fec4b0cbd1f406c209afe826719fd8d8aec5a1e5de234764aff0d93e5fc6ac73f3f5ebecb4fec1408dfefae9777d933f33596e7379f0fd3e368f0e36e51335ef0f4bf523d2248766718d57ea27fd1e073217eef2b6b3e19523d615e9a75cd47e30b36b0582e5281602a3307d8e05f000000ffff90051aa3f4010000",
"a17964c54f014a0dd59c42b49123a941": "1f8b08000000000000ff5492b18ed4301086ebcc530c96901294b5fb95b65836cd35b72be005bc5ec7589b782c674240e80a3a4a0a7a90780c5e0771af81622f3a5d916226ffffcdf8b7a33657ed2ceae8c18f9112630d953014d87e640195e847160095709edfcf67696854673ff8f553d7a4992615af4e05cb2a45a3169d2e361407911bac7434e8e02425a75c8a464003a014ee63bceb5082a130f1addaa17877ec8e5bdc771dee4f27bceb4416dfdbe530781b18835d70c5a0c935f473304fbf6bd33b7c557690a575a0d07bd722459e504ab99a65e7f5708cec2934587776a4a26dd1a644a9c1cf50153e6e7778c33d1b527852ca062a63b26f951653c6d7b70ce56b6dae2ed11c2e75d3623fb27c1b930fdcd7e2e227431f6cfab455ea627b3d0fac5e4ea22d71340d54becfe8173b0c7e58d7aa92e53985b5cc53a17a80ffbd7bbb3c9da536a66957193ce4081fbffff8fbf51bba37a703fef9fdebf1e71750cad1d6d96093668be5329189068c89980c6e3639eacde63cae2f44e636fc0b0000ffff940f602534020000",
"a2cb44570c3d3285165729786d5f1def": "1f8b08000000000000ff9452c18adb30103d6bbe626a285890daf41a9a43296d37870d69939ccb441e3b4364c94832ddc5f8df8b9ca56c4a0fedc1467af39ee6e98d063257ea187b120720fde043c21254d15aea0a50858fb77f1da57364f3263e4743765926e9b90050c534558fbed9076ee5699ea7a9da51cff35c8b4b1c1cd9ba91ccef245dc673657c5f9fc54afeea6ba0e4633d5cbbda78d7d603596ac4fd03ddfaae000dd08ece2c3728354ea0b2f56a4f2172a94159df555b27a9746235d635367c1e3bcca435e6622361330d942e33a8865b0e0bfac9fad7fad697059d0dc64421151ad48bcbdbd11ad48f159a2cf9323ab3420e01d71b6c64a97f1c864c9176c1df6cd089cd46d5404e4cc9216850332893353d5db9341772e8637558425fe17b0dea36806ae793b4cfa559e1cb1caac3f6ebc3697fb7ff76da1eef80e3e7ef8f77c07677d4a05a1f16233177fef0ce807a75df8e1312dedae2db58ac30568714c475a5d659f45392b9605c4e3014f9bf1dac4129f53bb69c91fa236f7e92256ea5f253ab0e9679286f4b36de354b29701a83fb8b8987d33eb768b8a5d1a6f51d77ce91cff02b0000ffff37cebd8001030000",
"a416686e4cfcf5ed8366cfcf264e48e0": "1f8b08000000000000ff8c53dd6ef3360cbd969e82358ac00e1209dd865d78f0c5d66c4381b52bf6735dc812ed0891255796d71481df7d90ecf46718be2f01624914299e7348f6421e448ba084a35477bdf301724a32e96cc063c828c982ee30a39464a713bb77ead163a38fd3743ab107d1e134716d037a2b0cef9c4213435a1df663cda4eb78ad8d8e7f7ef022b881f787964b21f7c83becd2e6e2008f4a0f97783bdbf05e18a1b4bdc05d89206a31201f9e2f013fbc5ac97bdda3d1167923ac1ba34cc728137c2d78d6b2a094f3d6952d5af42220cc1e109c33d0a2adc34039879d70b12e90f46d84441a5e7b4ce637139c28b9356ec0bca0e451db3697e1084bf5d8edbc1690a3f780de3b5f50c239d46128616b476392b4d52a958efde88396064f77bb727b33c156ee511e9ea2db93740aabebabca6ab35a5db3bb5d556d6f28592272f9df9c1bd02ac2fcfebb02f2f5a7e737672453d4215154c2b1995d3c0dc18f32446aaa86b7df7a78366cf71325a90fcec674607fc42f259dfce07eee2f76bf6c28490bace7a2b15fd24289c2cefd7cecb5c708f8db6f165c0ff802165f40244cc22af018466f196d462be375ee3fe5df4027ff27ed06547d065f40ae620193048b0c91e73fc2836cda85f98912b27b07955a8bed462f827696928912dda4072a58da9cfd8a21cf44df1b2d93170bae3359c1feb69df0c35e98bf7ebfff2d5fc9a62d7e48a15715586d626e32d34aef2aa860a5848b665597a0ea4d72507a28c1c77d274be864dc2572252c624639b2799e8b78fb2e6a39ab9a7f6291cba665ef1c0be090eeff44e9ac8a2f4cf40c6c2e47ea7290e91bf6081e07377a894b3972056b255c01cb34a4ee619d646fd3a1d85cab0f06557f3ccd653b1be6ac71a4a08f9f2fe5bc68f022a29951549e4ef4df000000ffff20759cb67c050000",
"a7f82d82b0fbcd0d7a86744fc49b7173": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000",
"a833afd1c2dfd51f0ba59a8bf977cc1b": "1f8b08000000000000ffbc91bd4a04311485ebe429428a416118333fa82c04052dc546bbc5229b5cd9c0fc7973e32ac3bcbb44071dabadb4ca395fc2e1836c6f5a0f3d3d71669c43a1852cab8b4215aa283775adce25672ef4894f3100ce9b6934211c0674f335d9f1e4f7ebd3b3c919323b1360be22dfc1104997214330eef1a71ed013acfa68307c764d18216b07abef066bdacceed30de948cf97ddaec9d329394b73b70ff7428bed11adeaffb4f2232af59fabe48b8f4cbf69c9bf82d0a2529c79d7a6582e71d9155a367bc9d94b047cff6642564a754172066f6057b85e30a1e957b8f9c21f010000ffff57d7944148020000",
"aa6f74a5b61f4cf11f0d49914680fd21": "1f8b08000000000000ff8c91cd6ae33010c7cfd653cc0a769182911f60c9291bc2c26e1a9af45c14595244648d91e53450f2ee45b25328bde42004c3ffe3374c2fd5595a0dad44425cd7634cc048451586a4af89125251ebd2693c0a855d7374dee5d79ca34c3834fdd9364aaa936ea26edd401f5063304d2fbd6c5d7840eed152c209316350b0d56fcfb98671601116a55294490d3ac6fc30727827d5454650c6c290e2a8529e542bef744877d70a8371965437523953cc4b98a9c44627462759c2ce532e5e4227e37092fef0f4ff1ffba58ce5bf8be9c71282f3253fea34c6501273d8e4ff2456c68a898093bbf436afc55a58b41239ec5cb0b33c5d613e4146cd3f07f6754767e0b59ed15b31f5fdc16cad81eed7075a03ed5db0e5c760e977668f56ac7320cb070f62af13dbfddd6ef854c37e5e382d157cda6be6fe080000ffffb73c6a1735020000",
"aaa0e84aef1077c2699e21ba05d51c7f": "1f8b08000000000000ff5ccc410a02310c85e175728a210728ad8283822bafe04e5cc4268b40673a74a25e5f2a0832cbff83f76e97623afb1d61e64987f340fcc884b0b4eab5a7e7851058a4f54abb31c410433a1df6e391104c4a5fa588c0d9edf50b312e579bb43efdbb5b09a129cbd6decd5cb7d84fff2dae849f000000ffffe1039f77a9000000",
"aaf0b28d854f8d677257bc26f4a6e22d": "1f8b08000000000000ff94924d8fdb2c1485d7f02bae2cbd919d3782fd48594d2b75914ca34c475d5f63eca0606030ee24b2fcdf2bfc91499ba61f0bb004c7f79c877b1d8a2356121ae9bf29212955b5b33e404a4922ac09f214124a92b20e09a5c4e590741ddbda62e765a94e7ddf75ec096bd9f71c9d8aca7bd7ca04e90d6a5ea08dba4a85439b33616b9e2bade2e2478fc136dc1d2b2eac29b9438d8532d1f95a5f598da6e2cedb60f3b6e42e9c9d6cb8ac5d382734a39473781e79662e46a3e6fd34f85604e8284101b09c7cd8161d25055a28d0b20f68693fd47a926f60e41be05c0dd014e06568bd61b46c8d8892b4987fcb206d603979ad407a1f97f559346c600d8be9aea384a0780058cc09be7cde6eba7e45498cf100c58a929e9258610db3e62b06714813744e2b814159c382ad75b28286a1c82819934de19ff1fc496a6da1f24e40216b0b31f194fb2a687691a6229c606a3e7b1cbf2bf0f215962e6783642f5f3348bd74fa0ccbe1e1d9c7b8ff4c3b2ad6f1f9d22b5946495907b6f3ca84324d0e43c0ff9a64701926e61ec6cb7e0379fd771c2ffbcdbfa2bc1f36ee1ecbe25a145b38d435e101269004febf708c0dbc856dbdfe3df04e990a5cdcc24182978d6d7d9ce35bdca8fc35a7fca13719a437adbaa04567585c5d777d9ca738d173fd6c4af6a86d23410cfb9fb20dda741cfca1d874407bfa3d0000ffff0c06c20f7a040000",
"aeab2b2b2dab4699657654469ca5b02b": "1f8b08000000000000ff5ccc410a02310c85e175728a210728ad8283822bafe04e5cc4268b40673a74a25e5f2a0832cbff83f76e97623afb1d61e64987f340fcc884b0b4eab5a7e7851058a4f54abb31c410433a1df6e391104c4a5fa588c0d9edf50b312e579bb43efdbb5b09a129cbd6decd5cb7d84fff2dae849f000000ffffe1039f77a9000000",
"b07da232bbd50bea80db83a2cb2ca45e": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000",
"c20ee81720733a2f96a9b0df3a23a7a2": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000",
"caf71f0f0cbb53c27c2bbcd00a648fd9": "1f8b08000000000000ff9452c18adb30103d6bbe626a285890daf41a9a43296d37870d69939ccb441e3b4364c94832ddc5f8df8b9ca56c4a0fedc1467af39ee6e98d063257ea187b120720fde043c21254d15aea0a50858fb77f1da57364f3263e4743765926e9b90050c534558fbed9076ee5699ea7a9da51cff35c8b4b1c1cd9ba91ccef245dc673657c5f9fc54afeea6ba0e4633d5cbbda78d7d603596ac4fd03ddfaae000dd08ece2c3728354ea0b2f56a4f2172a94159df555b27a9746235d635367c1e3bcca435e6622361330d942e33a8865b0e0bfac9fad7fad697059d0dc64421151ad48bcbdbd11ad48f159a2cf9323ab3420e01d71b6c64a97f1c864c9176c1df6cd089cd46d5404e4cc9216850332893353d5db9341772e8637558425fe17b0dea36806ae793b4cfa559e1cb1caac3f6ebc3697fb7ff76da1eef80e3e7ef8f77c07677d4a05a1f16233177fef0ce807a75df8e1312dedae2db58ac30568714c475a5d659f45392b9605c4e3014f9bf1dac4129f53bb69c91fa236f7e92256ea5f253ab0e9679286f4b36de354b29701a83fb8b8987d33eb768b8a5d1a6f51d77ce91cff02b0000ffff37cebd8001030000",
"cbfa81bf4d53c8a610fcbb7932ed95a3": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"cca1a28dc237a0b1a6d7768c4454036a": "1f8b08000000000000ff5491b18ed4301086ebcc530c96901294b3fb95b65836cd35b72be0057cde89b136f158ce8405a12be82829e841e231781dc4bd064abce874858b19ffff37e3dfc9bab3f58436050863e22c5843a51c47a18fa2a052fd280aa0523ec8fbf95e3b1ecd7d18c272cc395be1c9a4b33791c4e4e4ccc5e613c5e260f60369cf838d5e73f6c6e7e4143400c6e02ea5db0e35388e935cab2daa7787eeb0c15dd7e1ee78c4db4eade23bbaec87405130d205170cbab5867e8eeee9ba76bdc75765075d5a7b8e7df02d729209b5d68b5977c10e8724816383754723176d8b9433e7063f4355f8b8d9e215f76c48e169ad1ba89c5b7d8bb498567c7dcd50bfb6eeec33cff154372df6a3e8b72987287dad4e6172fc81f2a78d3127eaed3c887939a9b6c4d13450857e45bfd8620cc3b2569549e61c97729d0ad503fcefddd1e5e92db5734dbbc8e0618df0f1fb8fbf5fbfa17f73dce39fdfbf1e7f7e01633c6f3c45ca5608cb67a2300f98320b3bbcb959a3b629e8b503ff020000ffffb1117d162f020000",
"cdc9702cf3b30ddc315510a28df1ff83": "1f8b08000000000000ff8c535b6b1b3b107e5efd8a3982046d70b4e7e1701e5cfc10dc10426b3790b62fa504453bab08ebb2c8e3c4c6ec7f2f922f4dd2d2e66159edf25de69b19f54a2f9441685564ccfa3e2602c12aae63205c136715ef3c71c62abeddca596c6f1276763d0cdbad9c2b8fc3d0d8409882728d8f2dbacc30961e56f75247dfdc5b67f3d32c92a2b86cfa8569b4d20fd878f4e5f016420c5dd32ba75a1bde0077d1705633d634268e0d064c8a107600a0181d180c5e33daf408775e4349d0298db06555d380d763385fe066b2c0cd452238cfc8894162d534977c91c86a8742c3be4d72ba7b8fc0b659edffff6a1067a51f720f1e01a61453fd7b035cf736e1a4952dfa78593e5875d1b66fb51b814a042f1d6b1098d21f6c59f51e1dd241bf78fd25d333c181b16e1534ccf16936153508afe1ec305439db1f4aec3d2577f75125d09d8125a595a6fca79a3a8b819e71a73174d6b06a6095ed0a7f02fbe9cb2b24c18f488adef15a7e095ea5e583729f3fcd3e8a53dd99fa5de1fd3381605d714948ab148aa8d73001388accf149e8cec85d1d353b400f01450b67ad8a35dcd8606653a169fdba472f3a93ed8e75b7d26b798b945923383d9a5e13faed07dc8c81f736183e82afcaad700cdfbedf6f0805ef6330bc1e41590645368631fc3bfc9acb45232fb3afc8773614af9bebf955bdab469c3cd6bc0ca12ed95f65db2d82f839e125251b4c56de21a1f3246ffb64037582ab4477272dcf2b9117e047000000ffffe48ced133d040000",
"d1ce3e717c8a1e9830e9e1626ff88fa8": "1f8b08000000000000ff8c53dd6ef3360cbd969e82358ac00e1209dd865d78f0c5d66c4381b52bf6735dc812ed0891255796d71481df7d90ecf46718be2f01624914299e7348f6421e448ba084a35477bdf301724a32e96cc063c828c982ee30a39464a713bb77ead163a38fd3743ab107d1e134716d037a2b0cef9c4213435a1df663cda4eb78ad8d8e7f7ef022b881f787964b21f7c83becd2e6e2008f4a0f97783bdbf05e18a1b4bdc05d89206a31201f9e2f013fbc5ac97bdda3d1167923ac1ba34cc728137c2d78d6b2a094f3d6952d5af42220cc1e109c33d0a2adc34039879d70b12e90f46d84441a5e7b4ce637139c28b9356ec0bca0e451db3697e1084bf5d8edbc1690a3f780de3b5f50c239d46128616b476392b4d52a958efde88396064f77bb727b33c156ee511e9ea2db93740aabebabca6ab35a5db3bb5d556d6f28592272f9df9c1bd02ac2fcfebb02f2f5a7e737672453d4215154c2b1995d3c0dc18f32446aaa86b7df7a78366cf71325a90fcec674607fc42f259dfce07eee2f76bf6c28490bace7a2b15fd24289c2cefd7cecb5c708f8db6f165c0ff802165f40244cc22af018466f196d462be375ee3fe5df4027ff27ed06547d065f40ae620193048b0c91e73fc2836cda85f98912b27b07955a8bed462f827696928912dda4072a58da9cfd8a21cf44df1b2d93170bae3359c1feb69df0c35e98bf7ebfff2d5fc9a62d7e48a15715586d626e32d34aef2aa860a5848b665597a0ea4d72507a28c1c77d274be864dc2572252c624639b2799e8b78fb2e6a39ab9a7f6291cba665ef1c0be090eeff44e9ac8a2f4cf40c6c2e47ea7290e91bf6081e07377a894b3972056b255c01cb34a4ee619d646fd3a1d85cab0f06557f3ccd653b1be6ac71a4a08f9f2fe5bc68f022a29951549e4ef4df000000ffff20759cb67c050000",
"d34aa8c5fcb453998edcaa9594393f70": "1f8b08000000000000ff8c535b6b1b3b107e5efd8a3982046d70b4e7e1701e5cfc10dc10426b3790b62fa504453bab08ebb2c8e3c4c6ec7f2f922f4dd2d2e66159edf25de69b19f54a2f9441685564ccfa3e2602c12aae63205c136715ef3c71c62abeddca596c6f1276763d0cdbad9c2b8fc3d0d8409882728d8f2dbacc30961e56f75247dfdc5b67f3d32c92a2b86cfa8569b4d20fd878f4e5f016420c5dd32ba75a1bde0077d1705633d634268e0d064c8a107600a0181d180c5e33daf408775e4349d0298db06555d380d763385fe066b2c0cd452238cfc8894162d534977c91c86a8742c3be4d72ba7b8fc0b659edffff6a1067a51f720f1e01a61453fd7b035cf736e1a4952dfa78593e5875d1b66fb51b814a042f1d6b1098d21f6c59f51e1dd241bf78fd25d333c181b16e1534ccf16936153508afe1ec305439db1f4aec3d2577f75125d09d8125a595a6fca79a3a8b819e71a73174d6b06a6095ed0a7f02fbe9cb2b24c18f488adef15a7e095ea5e583729f3fcd3e8a53dd99fa5de1fd3381605d714948ab148aa8d73001388accf149e8cec85d1d353b400f01450b67ad8a35dcd8606653a169fdba472f3a93ed8e75b7d26b798b945923383d9a5e13faed07dc8c81f736183e82afcaad700cdfbedf6f0805ef6330bc1e41590645368631fc3bfc9acb45232fb3afc8773614af9bebf955bdab469c3cd6bc0ca12ed95f65db2d82f839e125251b4c56de21a1f3246ffb64037582ab4477272dcf2b9117e047000000ffffe48ced133d040000",
"d3a9bc220c8ae2d4e01680157e65d694": "1f8b08000000000000ffe2525608c9c82c56c82c56485408f1f7f55148c94f2ecd4dcd2bd15370cacfcfade34a49cdcd77ad28c82c4a55b055503232c950e202040000ffffc36ed62935000000",
"d5f9b4870ad447f7ef808033db2803ad": "1f8b08000000000000ff94924d8fdb2c1485d7f02bae2cbd919d3782fd48594d2b75914ca34c475d5f63eca0606030ee24b2fcdf2bfc91499ba61f0bb004c7f79c877b1d8a2356121ae9bf29212955b5b33e404a4922ac09f214124a92b20e09a5c4e590741ddbda62e765a94e7ddf75ec096bd9f71c9d8aca7bd7ca04e90d6a5ea08dba4a85439b33616b9e2bade2e2478fc136dc1d2b2eac29b9438d8532d1f95a5f598da6e2cedb60f3b6e42e9c9d6cb8ac5d382734a39473781e79662e46a3e6fd34f85604e8284101b09c7cd8161d25055a28d0b20f68693fd47a926f60e41be05c0dd014e06568bd61b46c8d8892b4987fcb206d603979ad407a1f97f559346c600d8be9aea384a0780058cc09be7cde6eba7e45498cf100c58a929e9258610db3e62b06714813744e2b814159c382ad75b28286a1c82819934de19ff1fc496a6da1f24e40216b0b31f194fb2a687691a6229c606a3e7b1cbf2bf0f215962e6783642f5f3348bd74fa0ccbe1e1d9c7b8ff4c3b2ad6f1f9d22b5946495907b6f3ca84324d0e43c0ff9a64701926e61ec6cb7e0379fd771c2ffbcdbfa2bc1f36ee1ecbe25a145b38d435e101269004febf708c0dbc856dbdfe3df04e990a5cdcc24182978d6d7d9ce35bdca8fc35a7fca13719a437adbaa04567585c5d777d9ca738d173fd6c4af6a86d23410cfb9fb20dda741cfca1d874407bfa3d0000ffff0c06c20f7a040000",
"d81923e98881c369f957c7d15decf26f": "1f8b08000000000000ff8c91cd6ae33010c7cfd653cc0a769182911f60c9291bc2c26e1a9af45c14595244648d91e53450f2ee45b25328bde42004c3ffe3374c2fd5595a0dad44425cd7634cc048451586a4af89125251ebd2693c0a855d7374dee5d79ca34c3834fdd9364aaa936ea26edd401f5063304d2fbd6c5d7840eed152c209316350b0d56fcfb98671601116a55294490d3ac6fc30727827d5454650c6c290e2a8529e542bef744877d70a8371965437523953cc4b98a9c44627462759c2ce532e5e4227e37092fef0f4ff1ffba58ce5bf8be9c71282f3253fea34c6501273d8e4ff2456c68a898093bbf436afc55a58b41239ec5cb0b33c5d613e4146cd3f07f6754767e0b59ed15b31f5fdc16cad81eed7075a03ed5db0e5c760e977668f56ac7320cb070f62af13dbfddd6ef854c37e5e382d157cda6be6fe080000ffffb73c6a1735020000",
"de469d397e894ad53241ccaa67354d77": "1f8b08000000000000ff5256702c2dc9c82fe25256084a2dcb4c2d4f2d02040000ffff7187321713000000",
"e507552ddfbcbf9862edb00a6a06942e": "1f8b08000000000000ff8c53dd6ef3360cbd969e82358ac00e1209dd865d78f0c5d66c4381b52bf6735dc812ed0891255796d71481df7d90ecf46718be2f01624914299e7348f6421e448ba084a35477bdf301724a32e96cc063c828c982ee30a39464a713bb77ead163a38fd3743ab107d1e134716d037a2b0cef9c4213435a1df663cda4eb78ad8d8e7f7ef022b881f787964b21f7c83becd2e6e2008f4a0f97783bdbf05e18a1b4bdc05d89206a31201f9e2f013fbc5ac97bdda3d1167923ac1ba34cc728137c2d78d6b2a094f3d6952d5af42220cc1e109c33d0a2adc34039879d70b12e90f46d84441a5e7b4ce637139c28b9356ec0bca0e451db3697e1084bf5d8edbc1690a3f780de3b5f50c239d46128616b476392b4d52a958efde88396064f77bb727b33c156ee511e9ea2db93740aabebabca6ab35a5db3bb5d556d6f28592272f9df9c1bd02ac2fcfebb02f2f5a7e737672453d4215154c2b1995d3c0dc18f32446aaa86b7df7a78366cf71325a90fcec674607fc42f259dfce07eee2f76bf6c28490bace7a2b15fd24289c2cefd7cecb5c708f8db6f165c0ff802165f40244cc22af018466f196d462be375ee3fe5df4027ff27ed06547d065f40ae620193048b0c91e73fc2836cda85f98912b27b07955a8bed462f827696928912dda4072a58da9cfd8a21cf44df1b2d93170bae3359c1feb69df0c35e98bf7ebfff2d5fc9a62d7e48a15715586d626e32d34aef2aa860a5848b665597a0ea4d72507a28c1c77d274be864dc2572252c624639b2799e8b78fb2e6a39ab9a7f6291cba665ef1c0be090eeff44e9ac8a2f4cf40c6c2e47ea7290e91bf6081e07377a894b3972056b255c01cb34a4ee619d646fd3a1d85cab0f06557f3ccd653b1be6ac71a4a08f9f2fe5bc68f022a29951549e4ef4df000000ffff20759cb67c050000",
"ee89e1856fc911f261533efa462e6867": "1f8b08000000000000ff8c90cd8adb3010c7cfd6534c75285258a44be9a5e4d0dd855e36e9f7038cf515115972e4719362fceec58e0ba5a73d0c0231bff97ff468ce181c582c8cc5ae2f9540b0869b92c9dd8833d6f069528762bf54e7e36d9ea7491db173f3ac6326573326dd15eb12670d0f914e63ab4ce9741b535c469f2b5219747f0eda94ec758f096dccaf58b748d8e2e0f470499c49c6fc980d1cddf5f9514810b685dd7049eaf9f1015cadcb942a6162cd2fac607c8081ea6868f9699e527499eec053c93e06d6ccac897e45f7b0b9529f1c096e5b45a54b5caa9fb9c33a9c30fdf87c78116f8d0ff2c34abcd9438e693d5d1d8d35afe76c0b7b58248eee7af8fdfdeb8b303ea8bbb6647f37e72d89b0b0b358247cc3ebc74ad124270cdd60eb7ef1b9bc0f102dc44cefdf49105809766bdf6a43fe0faf350447b09407be960e6cfb8ff29f000000ffffed2515fbf0010000",
"f14888b9e73b4709f9f661ca025578a5": "1f8b08000000000000ff52567049cdcde7e252565678b970e7f3d9eb9eaf6b78b2bb9bcb508f0b100000ffff24c85b041b000000",
"f6819875960d317b08fedcef244fc640": "1f8b08000000000000ff5256567049cdcde7e2525656562833d433d033e032d45378b2a3ebf9aefd4fbbe6bf68de5b5151c105080000ffff79fbc41327000000",
"f6e84ad3fd70355fca59f33e23639704": "1f8b08000000000000ff5ccdc14ec3300cc6f1f3fc143ec2614e9c32525e827748db6022927964c98434f5dd51e15238f862fdfefa8a2e3d47bcdfe93594b8ae00a2c8c40ea0c6cf9e6ac407404494d4defb44b31633a59cb6331f3534bd6209d7162b1c764454d45caa369dfa1bde981cf13f90c359fe90811c1c7effa455cc9739c786374b96ecd1597eb1cf6ee4f1343c9d8e4be0c1cf7ef4bcf82d52c99176add4cbfc33ebc8c2237c070000ffff34bdd5b6e6000000",
"faef00ce61dfdd11dc5b0198e8cb4d24": "1f8b08000000000000ff8a0e4e2d2a4b2d8ae552505050484c492952b0555032d003432b0b03030325b04c49666e6a7e690948d2b058890b100000ffffb7699cdc36000000",
"fe2a9fe5f84f01e208243862890c2182": "1f8b08000000000000ff2a484cce4e4c4f55c8cd4f49cde1e2d2d757f02e4a2cc92f56c848cdc9c957c80673f4b84a2a0b526132c52545a5c9250ad55c9c1e6035c525459979e95cb55c10558e452599c939a948ca3c5d1432f34acc4cb8389df3f34a52f34a605a381d4b4b32f28be02600020000ffffcb8696638d000000",
})
if err != nil {
panic(err)
}
g.DefaultResolver = hgr
func() {
b := packr.New("all", "./templates/all")
b.SetResolver("CHANGELOG.md", packr.Pointer{ForwardBox: gk, ForwardPath: "518b74b34be782fd3abced06105dfdf1"})
b.SetResolver("OWNERS", packr.Pointer{ForwardBox: gk, ForwardPath: "5d2e61f4f8ab5957f172a990d9fb3baf"})
b.SetResolver("README.md", packr.Pointer{ForwardBox: gk, ForwardPath: "f14888b9e73b4709f9f661ca025578a5"})
b.SetResolver("api/api.proto", packr.Pointer{ForwardBox: gk, ForwardPath: "5e8471dec0685b7154cd71dcf0444643"})
b.SetResolver("api/client.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "a17964c54f014a0dd59c42b49123a941"})
b.SetResolver("cmd/main.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "336d416ed5faa95a29de7b6afd385568"})
b.SetResolver("configs/application.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "cbfa81bf4d53c8a610fcbb7932ed95a3"})
b.SetResolver("configs/db.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "4ee76ca4d3f34ada842b90d87762fe26"})
b.SetResolver("configs/grpc.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "470fd5cab5c7a57cec62609827d2c84f"})
b.SetResolver("configs/http.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "7a53e746d0de690c8b20ca83292508c5"})
b.SetResolver("configs/memcache.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "6cc24b961eaafa6a5726c5e875dd92ae"})
b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "aeab2b2b2dab4699657654469ca5b02b"})
b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "95d28ebee82ae43dfc0c8b16b6088b2d"})
b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "a416686e4cfcf5ed8366cfcf264e48e0"})
b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "ee89e1856fc911f261533efa462e6867"})
b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d34aa8c5fcb453998edcaa9594393f70"})
b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "89e787ea2b6d77d3061b5e56a50c6e36"})
b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "97e4f2cf9f4ad4fc842f20a7fb124f91"})
b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "348f254eb8f48eaf3d0330c83c18324c"})
b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "b07da232bbd50bea80db83a2cb2ca45e"})
b.SetResolver("internal/server/grpc/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "984dd6df0bfb1684d6d188b40962ca7b"})
b.SetResolver("internal/server/http/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "468e50d126ac1e7c1a9ea44dde207990"})
b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "aaf0b28d854f8d677257bc26f4a6e22d"})
b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "5d243c2aa906cb9527df41e508cda83d"})
}()
func() {
b := packr.New("grpc", "./templates/grpc")
b.SetResolver("CHANGELOG.md", packr.Pointer{ForwardBox: gk, ForwardPath: "39a955dfabc5df68502b59574724045e"})
b.SetResolver("OWNERS", packr.Pointer{ForwardBox: gk, ForwardPath: "de469d397e894ad53241ccaa67354d77"})
b.SetResolver("README.md", packr.Pointer{ForwardBox: gk, ForwardPath: "473893d607815c5c27cec94e0e78e437"})
b.SetResolver("api/api.proto", packr.Pointer{ForwardBox: gk, ForwardPath: "359dcf82ea381d6901e53f88ff235896"})
b.SetResolver("api/client.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "cca1a28dc237a0b1a6d7768c4454036a"})
b.SetResolver("cmd/main.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "a2cb44570c3d3285165729786d5f1def"})
b.SetResolver("configs/application.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "959fd518960ea8b397538a6f7b1bdd3a"})
b.SetResolver("configs/db.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "a7f82d82b0fbcd0d7a86744fc49b7173"})
b.SetResolver("configs/grpc.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "43befbfad04c8efdf57be993ceb9e432"})
b.SetResolver("configs/memcache.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "885a5148286f0720126cd2a540b56564"})
b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "aaa0e84aef1077c2699e21ba05d51c7f"})
b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "48e53a59007a8dda61d904d989943a09"})
b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "e507552ddfbcbf9862edb00a6a06942e"})
b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "6640f2771831eddce9f1132a8ffa02b1"})
b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "1794b30bcdd9584d5877963a3cb28504"})
b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d81923e98881c369f957c7d15decf26f"})
b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "2f762fe51f2becdb8677b17926a52f03"})
b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "80a49866e2154ebe00c57fd7c80a4cab"})
b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "c20ee81720733a2f96a9b0df3a23a7a2"})
b.SetResolver("internal/server/grpc/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "65c9c5ceead4379a32ef56fe8044a9a7"})
b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "532d363951d4f0d0c18e620c67cb7b40"})
b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "225361cfe91f8a3ee02db98f64637aa4"})
}()
func() {
b := packr.New("http", "./templates/http")
b.SetResolver("CHANGELOG.md", packr.Pointer{ForwardBox: gk, ForwardPath: "f6819875960d317b08fedcef244fc640"})
b.SetResolver("OWNERS", packr.Pointer{ForwardBox: gk, ForwardPath: "64f157c0a5aaef8684ce174785fdb08b"})
b.SetResolver("README.md", packr.Pointer{ForwardBox: gk, ForwardPath: "236ab314cd41c9b7b2c5194c0eb72bb1"})
b.SetResolver("api/api.proto", packr.Pointer{ForwardBox: gk, ForwardPath: "33550cc0d0a7c442ee2f7ef103747430"})
b.SetResolver("api/client.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "49d0cdb7406397b8e77616d290bcd94f"})
b.SetResolver("cmd/main.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "caf71f0f0cbb53c27c2bbcd00a648fd9"})
b.SetResolver("configs/application.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "d3a9bc220c8ae2d4e01680157e65d694"})
b.SetResolver("configs/db.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "a833afd1c2dfd51f0ba59a8bf977cc1b"})
b.SetResolver("configs/http.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "faef00ce61dfdd11dc5b0198e8cb4d24"})
b.SetResolver("configs/memcache.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "1769e4a13f3ecbd1dbb3698b5f8cae8a"})
b.SetResolver("configs/redis.toml", packr.Pointer{ForwardBox: gk, ForwardPath: "40aa45750f8397d706e3d8fdd82fa11f"})
b.SetResolver("go.mod.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "f6e84ad3fd70355fca59f33e23639704"})
b.SetResolver("internal/dao/dao.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d1ce3e717c8a1e9830e9e1626ff88fa8"})
b.SetResolver("internal/dao/db.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "676482aadd24e9539226c67ebd8b5d04"})
b.SetResolver("internal/dao/mc.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "cdc9702cf3b30ddc315510a28df1ff83"})
b.SetResolver("internal/dao/redis.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "aa6f74a5b61f4cf11f0d49914680fd21"})
b.SetResolver("internal/di/app.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "56d831af18f731847e4733aa321128cb"})
b.SetResolver("internal/di/wire.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "8f2519501a642ae50acf464ad3acb9f9"})
b.SetResolver("internal/model/model.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "fe2a9fe5f84f01e208243862890c2182"})
b.SetResolver("internal/server/http/server.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "46713bf4406bd2896c32e5778efb1eb5"})
b.SetResolver("internal/service/service.go.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "d5f9b4870ad447f7ef808033db2803ad"})
b.SetResolver("test/docker-compose.yaml", packr.Pointer{ForwardBox: gk, ForwardPath: "14b27f88168b4f08f9d703f2a9b5027c"})
}()
return nil
}()

@ -0,0 +1,93 @@
package main
import (
"bytes"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"text/template"
"github.com/gobuffalo/packr/v2"
)
// project project config
type project struct {
// project name
Name string
// mod prefix
ModPrefix string
// project dir
path string
none bool
onlyGRPC bool
onlyHTTP bool
}
var p project
//go:generate packr2
func create() (err error) {
box := packr.New("all", "./templates/all")
if p.onlyHTTP {
box = packr.New("http", "./templates/http")
} else if p.onlyGRPC {
box = packr.New("grpc", "./templates/grpc")
}
if err = os.MkdirAll(p.path, 0755); err != nil {
return
}
for _, name := range box.List() {
if p.ModPrefix != "" && name == "go.mod.tmpl" {
continue
}
tmpl, _ := box.FindString(name)
i := strings.LastIndex(name, string(os.PathSeparator))
if i > 0 {
dir := name[:i]
if err = os.MkdirAll(filepath.Join(p.path, dir), 0755); err != nil {
return
}
}
if strings.HasSuffix(name, ".tmpl") {
name = strings.TrimSuffix(name, ".tmpl")
}
if err = write(filepath.Join(p.path, name), tmpl); err != nil {
return
}
}
if err = generate(); err != nil {
return
}
return
}
func generate() error {
cmd := exec.Command("go", "generate", "./...")
cmd.Dir = p.path
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
func write(path, tpl string) (err error) {
data, err := parse(tpl)
if err != nil {
return
}
return ioutil.WriteFile(path, data, 0644)
}
func parse(s string) ([]byte, error) {
t, err := template.New("").Parse(s)
if err != nil {
return nil, err
}
var buf bytes.Buffer
if err = t.Execute(&buf, p); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

@ -0,0 +1,4 @@
## Demo
### v1.0.0
1. 上线功能xxx

@ -0,0 +1,34 @@
// API proto gRPC HTTP API
// protobuf :
// - https://developers.google.com/protocol-buffers/
syntax = "proto3";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "google/protobuf/empty.proto";
import "google/api/annotations.proto";
// package 使 {appid}.{version} , version v1, v2 ..
package demo.service.v1;
// NOTE: (-)
option go_package = "api";
option (gogoproto.goproto_getters_all) = false;
service Demo {
rpc Ping (.google.protobuf.Empty) returns (.google.protobuf.Empty);
rpc SayHello (HelloReq) returns (.google.protobuf.Empty);
rpc SayHelloURL(HelloReq) returns (HelloResp) {
option (google.api.http) = {
get:"/abc/say_hello"
};
};
}
message HelloReq {
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"'];
}
message HelloResp {
string Content = 1 [(gogoproto.jsontag) = 'content'];
}

@ -0,0 +1,25 @@
package api
import (
"context"
"fmt"
"github.com/bilibili/kratos/pkg/net/rpc/warden"
"google.golang.org/grpc"
)
// AppID .
const AppID = "TODO: ADD APP ID"
// NewClient new grpc client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (DemoClient, error) {
client := warden.NewClient(cfg, opts...)
cc, err := client.Dial(context.Background(), fmt.Sprintf("discovery://default/%s", AppID))
if err != nil {
return nil, err
}
return NewDemoClient(cc), nil
}
// 生成 gRPC 代码
//go:generate kratos tool protoc --grpc --bm api.proto

@ -0,0 +1,41 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"{{.ModPrefix}}{{.Name}}/internal/di"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
func main() {
flag.Parse()
log.Init(nil) // debug flag: log.dir={path}
defer log.Close()
log.Info("abc start")
paladin.Init()
_, closeFunc, err := di.InitApp()
if err != nil {
panic(err)
}
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
closeFunc()
log.Info("abc exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

@ -0,0 +1,3 @@
# This is a TOML document. Boom~
demoExpire = "24h"

@ -0,0 +1,10 @@
[Client]
addr = "127.0.0.1:3306"
dsn = "{user}:{password}@tcp(127.0.0.1:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
readDSN = ["{user}:{password}@tcp(127.0.0.2:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8","{user}:{password}@tcp(127.0.0.3:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"]
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:9000"
timeout = "1s"

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:8000"
timeout = "1s"

@ -0,0 +1,10 @@
[Client]
name = "abc"
proto = "tcp"
addr = "127.0.0.1:11211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

@ -0,0 +1,10 @@
[Client]
name = "abc"
proto = "tcp"
addr = "127.0.0.1:6379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

@ -0,0 +1,11 @@
module {{.Name}}
go 1.12
require (
github.com/bilibili/kratos master
github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.3.2
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
google.golang.org/grpc v1.22.0
)

@ -0,0 +1,63 @@
package dao
import (
"context"
"time"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/cache/memcache"
"github.com/bilibili/kratos/pkg/cache/redis"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/database/sql"
"github.com/bilibili/kratos/pkg/sync/pipeline/fanout"
xtime "github.com/bilibili/kratos/pkg/time"
)
//go:generate kratos tool genbts
// Dao dao interface
type Dao interface {
Close()
Ping(ctx context.Context) (err error)
// bts: -nullcache=&model.Article{ID:-1} -check_null_code=$!=nil&&$.ID==-1
Article(c context.Context, id int64) (*model.Article, error)
}
// dao dao.
type dao struct {
db *sql.DB
redis *redis.Redis
mc *memcache.Memcache
cache *fanout.Fanout
demoExpire int32
}
// New new a dao and return.
func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) {
var cfg struct{
DemoExpire xtime.Duration
}
if err = paladin.Get("application.toml").UnmarshalTOML(&cfg); err != nil {
return
}
d = &dao{
db: db,
redis: r,
mc: mc,
cache: fanout.New("cache"),
demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second),
}
return
}
// Close close the resource.
func (d *dao) Close() {
d.mc.Close()
d.redis.Close()
d.db.Close()
d.cache.Close()
}
// Ping ping the resource.
func (d *dao) Ping(ctx context.Context) (err error) {
return nil
}

@ -0,0 +1,25 @@
package dao
import (
"context"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/database/sql"
)
func NewDB() (db *sql.DB, err error) {
var cfg struct {
Client *sql.Config
}
if err = paladin.Get("db.toml").UnmarshalTOML(&cfg); err != nil {
return
}
db = sql.NewMySQL(cfg.Client)
return
}
func (d *dao) RawArticle(ctx context.Context, id int64) (art *model.Article, err error) {
// get data from db
return
}

@ -0,0 +1,43 @@
package dao
import (
"context"
"fmt"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/cache/memcache"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
//go:generate kratos tool genmc
type _mc interface {
// mc: -key=keyArt -type=get
CacheArticle(c context.Context, id int64) (*model.Article, error)
// mc: -key=keyArt -expire=d.demoExpire
AddCacheArticle(c context.Context, id int64, art *model.Article) (err error)
// mc: -key=keyArt
DeleteArticleCache(c context.Context, id int64) (err error)
}
func NewMC() (mc *memcache.Memcache, err error) {
var cfg struct {
Client *memcache.Config
}
if err = paladin.Get("memcache.toml").UnmarshalTOML(&cfg); err != nil {
return
}
mc = memcache.New(cfg.Client)
return
}
func (d *dao) PingMC(ctx context.Context) (err error) {
if err = d.mc.Set(ctx, &memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}
func keyArt(id int64) string {
return fmt.Sprintf("art_%d", id)
}

@ -0,0 +1,27 @@
package dao
import (
"context"
"github.com/bilibili/kratos/pkg/cache/redis"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
func NewRedis() (r *redis.Redis, err error) {
var cfg struct {
Client *redis.Config
}
if err = paladin.Get("redis.toml").UnmarshalTOML(&cfg); err != nil {
return
}
r = redis.NewRedis(cfg.Client)
return
}
func (d *dao) PingRedis(ctx context.Context) (err error) {
if _, err = d.redis.Do(ctx, "SET", "ping", "pong"); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}

@ -0,0 +1,39 @@
package di
import (
"context"
"time"
"{{.ModPrefix}}{{.Name}}/internal/service"
"github.com/bilibili/kratos/pkg/log"
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
"github.com/bilibili/kratos/pkg/net/rpc/warden"
)
//go:generate wire
type App struct {
svc *service.Service
http *bm.Engine
grpc *warden.Server
}
func NewApp(svc *service.Service, h *bm.Engine, g *warden.Server) (app *App, closeFunc func(), err error){
app = &App{
svc: svc,
http: h,
grpc: g,
}
closeFunc = func() {
ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
if err := g.Shutdown(ctx); err != nil {
log.Error("grpcSrv.Shutdown error(%v)", err)
}
if err := h.Shutdown(ctx); err != nil {
log.Error("httpSrv.Shutdown error(%v)", err)
}
svc.Close()
cancel()
}
return
}

@ -0,0 +1,21 @@
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package di
import (
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao"
"{{.ModPrefix}}{{.Name}}/internal/server/grpc"
"{{.ModPrefix}}{{.Name}}/internal/server/http"
"{{.ModPrefix}}{{.Name}}/internal/service"
"github.com/google/wire"
)
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC)
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, http.New, grpc.New, NewApp))
}

@ -0,0 +1,12 @@
package model
// Kratos hello kratos.
type Kratos struct {
Hello string
}
type Article struct {
ID int64
Content string
Author string
}

@ -0,0 +1,23 @@
package grpc
import (
pb "{{.ModPrefix}}{{.Name}}/api"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/net/rpc/warden"
)
// New new a grpc server.
func New(svc pb.DemoServer) (ws *warden.Server, err error) {
var rc struct {
Server *warden.ServerConfig
}
err = paladin.Get("grpc.toml").UnmarshalTOML(&rc)
if err == paladin.ErrNotExist {
err = nil
}
ws = warden.NewServer(rc.Server)
pb.RegisterDemoServer(ws.Server(), svc)
ws, err = ws.Start()
return
}

@ -0,0 +1,57 @@
package http
import (
"net/http"
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
)
var svc pb.DemoServer
// New new a bm server.
func New(s pb.DemoServer) (engine *bm.Engine, err error) {
var (
hc struct {
Server *bm.ServerConfig
}
)
if err = paladin.Get("http.toml").UnmarshalTOML(&hc); err != nil {
if err != paladin.ErrNotExist {
return
}
err = nil
}
svc = s
engine = bm.DefaultServer(hc.Server)
pb.RegisterDemoBMServer(engine, s)
initRouter(engine)
err = engine.Start()
return
}
func initRouter(e *bm.Engine) {
e.Ping(ping)
g := e.Group("/abc")
{
g.GET("/start", howToStart)
}
}
func ping(ctx *bm.Context) {
if _, err := svc.Ping(ctx, nil); err != nil {
log.Error("ping error(%v)", err)
ctx.AbortWithStatus(http.StatusServiceUnavailable)
}
}
// example for http request handler.
func howToStart(c *bm.Context) {
k := &model.Kratos{
Hello: "Golang 大法好 !!!",
}
c.JSON(k, nil)
}

@ -0,0 +1,54 @@
package service
import (
"context"
"fmt"
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/golang/protobuf/ptypes/empty"
)
// Service service.
type Service struct {
ac *paladin.Map
dao dao.Dao
}
// New new a service and return.
func New(d dao.Dao) (s *Service, err error) {
s = &Service{
ac: &paladin.TOML{},
dao: d,
}
err = paladin.Watch("application.toml", s.ac)
return
}
// SayHello grpc demo func.
func (s *Service) SayHello(ctx context.Context, req *pb.HelloReq) (reply *empty.Empty, err error) {
reply = new(empty.Empty)
fmt.Printf("hello %s", req.Name)
return
}
// SayHelloURL bm demo func.
func (s *Service) SayHelloURL(ctx context.Context, req *pb.HelloReq) (reply *pb.HelloResp, err error) {
reply = &pb.HelloResp{
Content: "hello " + req.Name,
}
fmt.Printf("hello url %s", req.Name)
return
}
// Ping ping the resource.
func (s *Service) Ping(ctx context.Context, e *empty.Empty) (*empty.Empty, error) {
return &empty.Empty{}, s.dao.Ping(ctx)
}
// Close close the resource.
func (s *Service) Close() {
s.dao.Close()
}

@ -0,0 +1,40 @@
version: "3.7"
services:
db:
image: mysql:5.6
ports:
- 3306:3306
environment:
- MYSQL_ROOT_PASSWORD=root
- TZ=Asia/Shanghai
volumes:
- .:/docker-entrypoint-initdb.d
command: [
'--character-set-server=utf8',
'--collation-server=utf8_unicode_ci'
]
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "--protocol=tcp"]
timeout: 20s
interval: 1s
retries: 20
redis:
image: redis
ports:
- 6379:6379
healthcheck:
test: ["CMD", "redis-cli","ping"]
interval: 20s
timeout: 1s
retries: 20
memcached:
image: memcached
ports:
- 11211:11211
healthcheck:
test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"]
interval: 20s
timeout: 1s
retries: 20

@ -0,0 +1,4 @@
## Demo
### v1.0.0
1. 上线功能xxx

@ -0,0 +1,34 @@
// API proto gRPC HTTP API
// protobuf :
// - https://developers.google.com/protocol-buffers/
syntax = "proto3";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "google/protobuf/empty.proto";
import "google/api/annotations.proto";
// package 使 {appid}.{version} , version v1, v2 ..
package demo.service.v1;
// NOTE: (-)
option go_package = "api";
option (gogoproto.goproto_getters_all) = false;
service Demo {
rpc Ping (.google.protobuf.Empty) returns (.google.protobuf.Empty);
rpc SayHello (HelloReq) returns (.google.protobuf.Empty);
rpc SayHelloURL(HelloReq) returns (HelloResp) {
option (google.api.http) = {
get:"/abc/say_hello"
};
};
}
message HelloReq {
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"'];
}
message HelloResp {
string Content = 1 [(gogoproto.jsontag) = 'content'];
}

@ -0,0 +1,25 @@
package api
import (
"context"
"fmt"
"github.com/bilibili/kratos/pkg/net/rpc/warden"
"google.golang.org/grpc"
)
// AppID .
const AppID = "TODO: ADD APP ID"
// NewClient new grpc client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (DemoClient, error) {
client := warden.NewClient(cfg, opts...)
cc, err := client.Dial(context.Background(), fmt.Sprintf("discovery://default/%s", AppID))
if err != nil {
return nil, err
}
return NewDemoClient(cc), nil
}
// 生成 gRPC 代码
//go:generate kratos tool protoc --grpc api.proto

@ -0,0 +1,41 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"{{.ModPrefix}}{{.Name}}/internal/di"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
func main() {
flag.Parse()
log.Init(nil) // debug flag: log.dir={path}
defer log.Close()
log.Info("abc start")
paladin.Init()
_, closeFunc, err := di.InitApp()
if err != nil {
panic(err)
}
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
closeFunc()
log.Info("abc exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

@ -0,0 +1,3 @@
# This is a TOML document. Boom~
demoExpire = "24h"

@ -0,0 +1,10 @@
[Client]
addr = "127.0.0.1:3306"
dsn = "{user}:{password}@tcp(127.0.0.1:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
readDSN = ["{user}:{password}@tcp(127.0.0.2:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8","{user}:{password}@tcp(127.0.0.3:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"]
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:9000"
timeout = "1s"

@ -0,0 +1,10 @@
[Client]
name = "abc"
proto = "tcp"
addr = "127.0.0.1:11211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

@ -0,0 +1,10 @@
[Client]
name = "abc"
proto = "tcp"
addr = "127.0.0.1:6379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

@ -0,0 +1,11 @@
module {{.Name}}
go 1.12
require (
github.com/bilibili/kratos master
github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.3.2
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
google.golang.org/grpc v1.22.0
)

@ -0,0 +1,63 @@
package dao
import (
"context"
"time"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/cache/memcache"
"github.com/bilibili/kratos/pkg/cache/redis"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/database/sql"
"github.com/bilibili/kratos/pkg/sync/pipeline/fanout"
xtime "github.com/bilibili/kratos/pkg/time"
)
//go:generate kratos tool genbts
// Dao dao interface
type Dao interface {
Close()
Ping(ctx context.Context) (err error)
// bts: -nullcache=&model.Article{ID:-1} -check_null_code=$!=nil&&$.ID==-1
Article(c context.Context, id int64) (*model.Article, error)
}
// dao dao.
type dao struct {
db *sql.DB
redis *redis.Redis
mc *memcache.Memcache
cache *fanout.Fanout
demoExpire int32
}
// New new a dao and return.
func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) {
var cfg struct{
DemoExpire xtime.Duration
}
if err = paladin.Get("application.toml").UnmarshalTOML(&cfg); err != nil {
return
}
d = &dao{
db: db,
redis: r,
mc: mc,
cache: fanout.New("cache"),
demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second),
}
return
}
// Close close the resource.
func (d *dao) Close() {
d.mc.Close()
d.redis.Close()
d.db.Close()
d.cache.Close()
}
// Ping ping the resource.
func (d *dao) Ping(ctx context.Context) (err error) {
return nil
}

@ -0,0 +1,25 @@
package dao
import (
"context"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/database/sql"
)
func NewDB() (db *sql.DB, err error) {
var cfg struct {
Client *sql.Config
}
if err = paladin.Get("db.toml").UnmarshalTOML(&cfg); err != nil {
return
}
db = sql.NewMySQL(cfg.Client)
return
}
func (d *dao) RawArticle(ctx context.Context, id int64) (art *model.Article, err error) {
// get data from db
return
}

@ -0,0 +1,43 @@
package dao
import (
"context"
"fmt"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/cache/memcache"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
//go:generate kratos tool genmc
type _mc interface {
// mc: -key=keyArt -type=get
CacheArticle(c context.Context, id int64) (*model.Article, error)
// mc: -key=keyArt -expire=d.demoExpire
AddCacheArticle(c context.Context, id int64, art *model.Article) (err error)
// mc: -key=keyArt
DeleteArticleCache(c context.Context, id int64) (err error)
}
func NewMC() (mc *memcache.Memcache, err error) {
var cfg struct {
Client *memcache.Config
}
if err = paladin.Get("memcache.toml").UnmarshalTOML(&cfg); err != nil {
return
}
mc = memcache.New(cfg.Client)
return
}
func (d *dao) PingMC(ctx context.Context) (err error) {
if err = d.mc.Set(ctx, &memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}
func keyArt(id int64) string {
return fmt.Sprintf("art_%d", id)
}

@ -0,0 +1,27 @@
package dao
import (
"context"
"github.com/bilibili/kratos/pkg/cache/redis"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
func NewRedis() (r *redis.Redis, err error) {
var cfg struct {
Client *redis.Config
}
if err = paladin.Get("redis.toml").UnmarshalTOML(&cfg); err != nil {
return
}
r = redis.NewRedis(cfg.Client)
return
}
func (d *dao) PingRedis(ctx context.Context) (err error) {
if _, err = d.redis.Do(ctx, "SET", "ping", "pong"); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}

@ -0,0 +1,33 @@
package di
import (
"context"
"time"
"{{.ModPrefix}}{{.Name}}/internal/service"
"github.com/bilibili/kratos/pkg/log"
"github.com/bilibili/kratos/pkg/net/rpc/warden"
)
//go:generate wire
type App struct {
svc *service.Service
grpc *warden.Server
}
func NewApp(svc *service.Service, g *warden.Server) (app *App, closeFunc func(), err error){
app = &App{
svc: svc,
grpc: g,
}
closeFunc = func() {
ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
if err := g.Shutdown(ctx); err != nil {
log.Error("grpcSrv.Shutdown error(%v)", err)
}
svc.Close()
cancel()
}
return
}

@ -0,0 +1,20 @@
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package di
import (
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao"
"{{.ModPrefix}}{{.Name}}/internal/server/grpc"
"{{.ModPrefix}}{{.Name}}/internal/service"
"github.com/google/wire"
)
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC)
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, grpc.New, NewApp))
}

@ -0,0 +1,12 @@
package model
// Kratos hello kratos.
type Kratos struct {
Hello string
}
type Article struct {
ID int64
Content string
Author string
}

@ -0,0 +1,23 @@
package grpc
import (
pb "{{.ModPrefix}}{{.Name}}/api"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/net/rpc/warden"
)
// New new a grpc server.
func New(svc pb.DemoServer) (ws *warden.Server, err error) {
var rc struct {
Server *warden.ServerConfig
}
err = paladin.Get("grpc.toml").UnmarshalTOML(&rc)
if err == paladin.ErrNotExist {
err = nil
}
ws = warden.NewServer(rc.Server)
pb.RegisterDemoServer(ws.Server(), svc)
ws, err = ws.Start()
return
}

@ -0,0 +1,54 @@
package service
import (
"context"
"fmt"
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/golang/protobuf/ptypes/empty"
)
// Service service.
type Service struct {
ac *paladin.Map
dao dao.Dao
}
// New new a service and return.
func New(d dao.Dao) (s *Service, err error) {
s = &Service{
ac: &paladin.TOML{},
dao: d,
}
err = paladin.Watch("application.toml", s.ac)
return
}
// SayHello grpc demo func.
func (s *Service) SayHello(ctx context.Context, req *pb.HelloReq) (reply *empty.Empty, err error) {
reply = new(empty.Empty)
fmt.Printf("hello %s", req.Name)
return
}
// SayHelloURL bm demo func.
func (s *Service) SayHelloURL(ctx context.Context, req *pb.HelloReq) (reply *pb.HelloResp, err error) {
reply = &pb.HelloResp{
Content: "hello " + req.Name,
}
fmt.Printf("hello url %s", req.Name)
return
}
// Ping ping the resource.
func (s *Service) Ping(ctx context.Context, e *empty.Empty) (*empty.Empty, error) {
return &empty.Empty{}, s.dao.Ping(ctx)
}
// Close close the resource.
func (s *Service) Close() {
s.dao.Close()
}

@ -0,0 +1,40 @@
version: "3.7"
services:
db:
image: mysql:5.6
ports:
- 3306:3306
environment:
- MYSQL_ROOT_PASSWORD=root
- TZ=Asia/Shanghai
volumes:
- .:/docker-entrypoint-initdb.d
command: [
'--character-set-server=utf8',
'--collation-server=utf8_unicode_ci'
]
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "--protocol=tcp"]
timeout: 20s
interval: 1s
retries: 20
redis:
image: redis
ports:
- 6379:6379
healthcheck:
test: ["CMD", "redis-cli","ping"]
interval: 20s
timeout: 1s
retries: 20
memcached:
image: memcached
ports:
- 11211:11211
healthcheck:
test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"]
interval: 20s
timeout: 1s
retries: 20

@ -0,0 +1,4 @@
## Demo
### v1.0.0
1. 上线功能xxx

@ -0,0 +1,34 @@
// API proto gRPC HTTP API
// protobuf :
// - https://developers.google.com/protocol-buffers/
syntax = "proto3";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "google/protobuf/empty.proto";
import "google/api/annotations.proto";
// package 使 {appid}.{version} , version v1, v2 ..
package demo.service.v1;
// NOTE: (-)
option go_package = "api";
option (gogoproto.goproto_getters_all) = false;
service Demo {
rpc Ping (.google.protobuf.Empty) returns (.google.protobuf.Empty);
rpc SayHello (HelloReq) returns (.google.protobuf.Empty);
rpc SayHelloURL(HelloReq) returns (HelloResp) {
option (google.api.http) = {
get:"/abc/say_hello"
};
};
}
message HelloReq {
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"'];
}
message HelloResp {
string Content = 1 [(gogoproto.jsontag) = 'content'];
}

@ -0,0 +1,25 @@
package api
import (
"context"
"fmt"
"github.com/bilibili/kratos/pkg/net/rpc/warden"
"google.golang.org/grpc"
)
// AppID .
const AppID = "TODO: ADD APP ID"
// NewClient new grpc client
func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (DemoClient, error) {
client := warden.NewClient(cfg, opts...)
cc, err := client.Dial(context.Background(), fmt.Sprintf("discovery://default/%s", AppID))
if err != nil {
return nil, err
}
return NewDemoClient(cc), nil
}
// 生成 gRPC 代码
//go:generate kratos tool protoc --grpc --bm api.proto

@ -0,0 +1,41 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"{{.ModPrefix}}{{.Name}}/internal/di"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
func main() {
flag.Parse()
log.Init(nil) // debug flag: log.dir={path}
defer log.Close()
log.Info("abc start")
paladin.Init()
_, closeFunc, err := di.InitApp()
if err != nil {
panic(err)
}
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
closeFunc()
log.Info("abc exit")
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

@ -0,0 +1,3 @@
# This is a TOML document. Boom~
demoExpire = "24h"

@ -0,0 +1,10 @@
[Client]
addr = "127.0.0.1:3306"
dsn = "{user}:{password}@tcp(127.0.0.1:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
readDSN = ["{user}:{password}@tcp(127.0.0.2:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8","{user}:{password}@tcp(127.0.0.3:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"]
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

@ -0,0 +1,3 @@
[Server]
addr = "0.0.0.0:8000"
timeout = "1s"

@ -0,0 +1,10 @@
[Client]
name = "abc"
proto = "tcp"
addr = "127.0.0.1:11211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

@ -0,0 +1,10 @@
[Client]
name = "abc"
proto = "tcp"
addr = "127.0.0.1:6379"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

@ -0,0 +1,11 @@
module {{.Name}}
go 1.12
require (
github.com/bilibili/kratos master
github.com/gogo/protobuf v1.2.1
github.com/golang/protobuf v1.3.2
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
google.golang.org/grpc v1.22.0
)

@ -0,0 +1,63 @@
package dao
import (
"context"
"time"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/cache/memcache"
"github.com/bilibili/kratos/pkg/cache/redis"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/database/sql"
"github.com/bilibili/kratos/pkg/sync/pipeline/fanout"
xtime "github.com/bilibili/kratos/pkg/time"
)
//go:generate kratos tool genbts
// Dao dao interface
type Dao interface {
Close()
Ping(ctx context.Context) (err error)
// bts: -nullcache=&model.Article{ID:-1} -check_null_code=$!=nil&&$.ID==-1
Article(c context.Context, id int64) (*model.Article, error)
}
// dao dao.
type dao struct {
db *sql.DB
redis *redis.Redis
mc *memcache.Memcache
cache *fanout.Fanout
demoExpire int32
}
// New new a dao and return.
func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, err error) {
var cfg struct{
DemoExpire xtime.Duration
}
if err = paladin.Get("application.toml").UnmarshalTOML(&cfg); err != nil {
return
}
d = &dao{
db: db,
redis: r,
mc: mc,
cache: fanout.New("cache"),
demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second),
}
return
}
// Close close the resource.
func (d *dao) Close() {
d.mc.Close()
d.redis.Close()
d.db.Close()
d.cache.Close()
}
// Ping ping the resource.
func (d *dao) Ping(ctx context.Context) (err error) {
return nil
}

@ -0,0 +1,25 @@
package dao
import (
"context"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/database/sql"
)
func NewDB() (db *sql.DB, err error) {
var cfg struct {
Client *sql.Config
}
if err = paladin.Get("db.toml").UnmarshalTOML(&cfg); err != nil {
return
}
db = sql.NewMySQL(cfg.Client)
return
}
func (d *dao) RawArticle(ctx context.Context, id int64) (art *model.Article, err error) {
// get data from db
return
}

@ -0,0 +1,43 @@
package dao
import (
"context"
"fmt"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/cache/memcache"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
//go:generate kratos tool genmc
type _mc interface {
// mc: -key=keyArt -type=get
CacheArticle(c context.Context, id int64) (*model.Article, error)
// mc: -key=keyArt -expire=d.demoExpire
AddCacheArticle(c context.Context, id int64, art *model.Article) (err error)
// mc: -key=keyArt
DeleteArticleCache(c context.Context, id int64) (err error)
}
func NewMC() (mc *memcache.Memcache, err error) {
var cfg struct {
Client *memcache.Config
}
if err = paladin.Get("memcache.toml").UnmarshalTOML(&cfg); err != nil {
return
}
mc = memcache.New(cfg.Client)
return
}
func (d *dao) PingMC(ctx context.Context) (err error) {
if err = d.mc.Set(ctx, &memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}
func keyArt(id int64) string {
return fmt.Sprintf("art_%d", id)
}

@ -0,0 +1,27 @@
package dao
import (
"context"
"github.com/bilibili/kratos/pkg/cache/redis"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
)
func NewRedis() (r *redis.Redis, err error) {
var cfg struct {
Client *redis.Config
}
if err = paladin.Get("redis.toml").UnmarshalTOML(&cfg); err != nil {
return
}
r = redis.NewRedis(cfg.Client)
return
}
func (d *dao) PingRedis(ctx context.Context) (err error) {
if _, err = d.redis.Do(ctx, "SET", "ping", "pong"); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}

@ -0,0 +1,33 @@
package di
import (
"context"
"time"
"{{.ModPrefix}}{{.Name}}/internal/service"
"github.com/bilibili/kratos/pkg/log"
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
)
//go:generate wire
type App struct {
svc *service.Service
http *bm.Engine
}
func NewApp(svc *service.Service, h *bm.Engine) (app *App, closeFunc func(), err error){
app = &App{
svc: svc,
http: h,
}
closeFunc = func() {
ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
if err := h.Shutdown(ctx); err != nil {
log.Error("httpSrv.Shutdown error(%v)", err)
}
svc.Close()
cancel()
}
return
}

@ -0,0 +1,20 @@
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package di
import (
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao"
"{{.ModPrefix}}{{.Name}}/internal/server/http"
"{{.ModPrefix}}{{.Name}}/internal/service"
"github.com/google/wire"
)
var daoProvider = wire.NewSet(dao.New, dao.NewDB, dao.NewRedis, dao.NewMC)
var serviceProvider = wire.NewSet(service.New, wire.Bind(new(pb.DemoServer), new(*service.Service)))
func InitApp() (*App, func(), error) {
panic(wire.Build(daoProvider, serviceProvider, http.New, NewApp))
}

@ -0,0 +1,12 @@
package model
// Kratos hello kratos.
type Kratos struct {
Hello string
}
type Article struct {
ID int64
Content string
Author string
}

@ -0,0 +1,57 @@
package http
import (
"net/http"
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/model"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/bilibili/kratos/pkg/log"
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
)
var svc pb.DemoServer
// New new a bm server.
func New(s pb.DemoServer) (engine *bm.Engine, err error) {
var (
hc struct {
Server *bm.ServerConfig
}
)
if err = paladin.Get("http.toml").UnmarshalTOML(&hc); err != nil {
if err != paladin.ErrNotExist {
return
}
err = nil
}
svc = s
engine = bm.DefaultServer(hc.Server)
pb.RegisterDemoBMServer(engine, s)
initRouter(engine)
err = engine.Start()
return
}
func initRouter(e *bm.Engine) {
e.Ping(ping)
g := e.Group("/abc")
{
g.GET("/start", howToStart)
}
}
func ping(ctx *bm.Context) {
if _, err := svc.Ping(ctx, nil); err != nil {
log.Error("ping error(%v)", err)
ctx.AbortWithStatus(http.StatusServiceUnavailable)
}
}
// example for http request handler.
func howToStart(c *bm.Context) {
k := &model.Kratos{
Hello: "Golang 大法好 !!!",
}
c.JSON(k, nil)
}

@ -0,0 +1,54 @@
package service
import (
"context"
"fmt"
pb "{{.ModPrefix}}{{.Name}}/api"
"{{.ModPrefix}}{{.Name}}/internal/dao"
"github.com/bilibili/kratos/pkg/conf/paladin"
"github.com/golang/protobuf/ptypes/empty"
)
// Service service.
type Service struct {
ac *paladin.Map
dao dao.Dao
}
// New new a service and return.
func New(d dao.Dao) (s *Service, err error) {
s = &Service{
ac: &paladin.TOML{},
dao: d,
}
err = paladin.Watch("application.toml", s.ac)
return
}
// SayHello grpc demo func.
func (s *Service) SayHello(ctx context.Context, req *pb.HelloReq) (reply *empty.Empty, err error) {
reply = new(empty.Empty)
fmt.Printf("hello %s", req.Name)
return
}
// SayHelloURL bm demo func.
func (s *Service) SayHelloURL(ctx context.Context, req *pb.HelloReq) (reply *pb.HelloResp, err error) {
reply = &pb.HelloResp{
Content: "hello " + req.Name,
}
fmt.Printf("hello url %s", req.Name)
return
}
// Ping ping the resource.
func (s *Service) Ping(ctx context.Context, e *empty.Empty) (*empty.Empty, error) {
return &empty.Empty{}, s.dao.Ping(ctx)
}
// Close close the resource.
func (s *Service) Close() {
s.dao.Close()
}

@ -0,0 +1,40 @@
version: "3.7"
services:
db:
image: mysql:5.6
ports:
- 3306:3306
environment:
- MYSQL_ROOT_PASSWORD=root
- TZ=Asia/Shanghai
volumes:
- .:/docker-entrypoint-initdb.d
command: [
'--character-set-server=utf8',
'--collation-server=utf8_unicode_ci'
]
healthcheck:
test: ["CMD", "mysqladmin" ,"ping", "--protocol=tcp"]
timeout: 20s
interval: 1s
retries: 20
redis:
image: redis
ports:
- 6379:6379
healthcheck:
test: ["CMD", "redis-cli","ping"]
interval: 20s
timeout: 1s
retries: 20
memcached:
image: memcached
ports:
- 11211:11211
healthcheck:
test: ["CMD", "echo", "stats", "|", "nc", "127.0.0.1", "11211"]
interval: 20s
timeout: 1s
retries: 20

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save