Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95aa65efb9 | ||
|
|
3806e66cf1 | ||
|
|
bd430baf52 | ||
|
|
48f4154ea8 | ||
|
|
2599e0d28d | ||
|
|
12327fa07d | ||
|
|
57079bf4a4 | ||
|
|
7f6eceb5a3 | ||
|
|
7d7cb836af | ||
|
|
f87d9d1dda |
@@ -82,6 +82,7 @@ func (pe *PeriodicalExecutor) Sync(fn func()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pe *PeriodicalExecutor) Wait() {
|
func (pe *PeriodicalExecutor) Wait() {
|
||||||
|
pe.Flush()
|
||||||
pe.wgBarrier.Guard(func() {
|
pe.wgBarrier.Guard(func() {
|
||||||
pe.waitGroup.Wait()
|
pe.waitGroup.Wait()
|
||||||
})
|
})
|
||||||
|
|||||||
8
core/stores/cache/cachenode.go
vendored
8
core/stores/cache/cachenode.go
vendored
@@ -175,12 +175,12 @@ func (c cacheNode) doTake(v interface{}, key string, query func(v interface{}) e
|
|||||||
}
|
}
|
||||||
if fresh {
|
if fresh {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
|
||||||
// got the result from previous ongoing query
|
|
||||||
c.stat.IncrementTotal()
|
|
||||||
c.stat.IncrementHit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// got the result from previous ongoing query
|
||||||
|
c.stat.IncrementTotal()
|
||||||
|
c.stat.IncrementHit()
|
||||||
|
|
||||||
return jsonx.Unmarshal(val.([]byte), v)
|
return jsonx.Unmarshal(val.([]byte), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -43,7 +43,7 @@ require (
|
|||||||
github.com/spaolacci/murmur3 v1.1.0
|
github.com/spaolacci/murmur3 v1.1.0
|
||||||
github.com/stretchr/testify v1.5.1
|
github.com/stretchr/testify v1.5.1
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6 // indirect
|
||||||
github.com/urfave/cli v1.22.4
|
github.com/urfave/cli v1.22.5
|
||||||
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
|
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
|
||||||
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect
|
github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb // indirect
|
||||||
go.etcd.io/etcd v0.0.0-20200402134248-51bdeb39e698
|
go.etcd.io/etcd v0.0.0-20200402134248-51bdeb39e698
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -277,6 +277,8 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20171017195756-830351dc03c6/go.mod h1
|
|||||||
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.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
|
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
|
||||||
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
|
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU=
|
||||||
|
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
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/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6 h1:YdYsPAZ2pC6Tow/nPZOPQ96O3hm/ToAkGsPLzedXERk=
|
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6 h1:YdYsPAZ2pC6Tow/nPZOPQ96O3hm/ToAkGsPLzedXERk=
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package internal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -10,43 +9,27 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func StartHttp(host string, port int, handler http.Handler) error {
|
func StartHttp(host string, port int, handler http.Handler) error {
|
||||||
addr := fmt.Sprintf("%s:%d", host, port)
|
return start(host, port, handler, func(srv *http.Server) error {
|
||||||
server := buildHttpServer(addr, handler)
|
return srv.ListenAndServe()
|
||||||
gracefulOnShutdown(server)
|
})
|
||||||
return server.ListenAndServe()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartHttps(host string, port int, certFile, keyFile string, handler http.Handler) error {
|
func StartHttps(host string, port int, certFile, keyFile string, handler http.Handler) error {
|
||||||
addr := fmt.Sprintf("%s:%d", host, port)
|
return start(host, port, handler, func(srv *http.Server) error {
|
||||||
if server, err := buildHttpsServer(addr, handler, certFile, keyFile); err != nil {
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
gracefulOnShutdown(server)
|
|
||||||
// certFile and keyFile are set in buildHttpsServer
|
// certFile and keyFile are set in buildHttpsServer
|
||||||
return server.ListenAndServeTLS("", "")
|
return srv.ListenAndServeTLS(certFile, keyFile)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildHttpServer(addr string, handler http.Handler) *http.Server {
|
|
||||||
return &http.Server{Addr: addr, Handler: handler}
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildHttpsServer(addr string, handler http.Handler, certFile, keyFile string) (*http.Server, error) {
|
|
||||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
config := tls.Config{Certificates: []tls.Certificate{cert}}
|
|
||||||
return &http.Server{
|
|
||||||
Addr: addr,
|
|
||||||
Handler: handler,
|
|
||||||
TLSConfig: &config,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func gracefulOnShutdown(srv *http.Server) {
|
|
||||||
proc.AddWrapUpListener(func() {
|
|
||||||
srv.Shutdown(context.Background())
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func start(host string, port int, handler http.Handler, run func(srv *http.Server) error) error {
|
||||||
|
server := &http.Server{
|
||||||
|
Addr: fmt.Sprintf("%s:%d", host, port),
|
||||||
|
Handler: handler,
|
||||||
|
}
|
||||||
|
waitForCalled := proc.AddWrapUpListener(func() {
|
||||||
|
server.Shutdown(context.Background())
|
||||||
|
})
|
||||||
|
defer waitForCalled()
|
||||||
|
|
||||||
|
return run(server)
|
||||||
|
}
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ func ApiFormatByPath(apiFilePath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func apiFormat(data string) (string, error) {
|
func apiFormat(data string) (string, error) {
|
||||||
|
|
||||||
r := reg.ReplaceAllStringFunc(data, func(m string) string {
|
r := reg.ReplaceAllStringFunc(data, func(m string) string {
|
||||||
parts := reg.FindStringSubmatch(m)
|
parts := reg.FindStringSubmatch(m)
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package gogen
|
package gogen
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -60,7 +58,6 @@ func DoGenProject(apiFile, dir string, force bool) error {
|
|||||||
logx.Must(genHandlers(dir, api))
|
logx.Must(genHandlers(dir, api))
|
||||||
logx.Must(genRoutes(dir, api, force))
|
logx.Must(genRoutes(dir, api, force))
|
||||||
logx.Must(genLogic(dir, api))
|
logx.Must(genLogic(dir, api))
|
||||||
createGoModFileIfNeed(dir)
|
|
||||||
|
|
||||||
if err := backupAndSweep(apiFile); err != nil {
|
if err := backupAndSweep(apiFile); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -129,34 +126,3 @@ func sweep() error {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createGoModFileIfNeed(dir string) {
|
|
||||||
absDir, err := filepath.Abs(dir)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, hasGoMod := util.FindGoModPath(dir)
|
|
||||||
if hasGoMod {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
gopath := os.Getenv("GOPATH")
|
|
||||||
parent := path.Join(gopath, "src")
|
|
||||||
pos := strings.Index(absDir, parent)
|
|
||||||
if pos >= 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleName := absDir[len(filepath.Dir(absDir))+1:]
|
|
||||||
cmd := exec.Command("go", "mod", "init", moduleName)
|
|
||||||
cmd.Dir = dir
|
|
||||||
var stdout, stderr bytes.Buffer
|
|
||||||
cmd.Stdout = &stdout
|
|
||||||
cmd.Stderr = &stderr
|
|
||||||
if err = cmd.Run(); err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
}
|
|
||||||
outStr, errStr := string(stdout.Bytes()), string(stderr.Bytes())
|
|
||||||
fmt.Printf(outStr + "\n" + errStr)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/api/parser"
|
"github.com/tal-tech/go-zero/tools/goctl/api/parser"
|
||||||
|
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
|
||||||
)
|
)
|
||||||
|
|
||||||
const testApiTemplate = `
|
const testApiTemplate = `
|
||||||
@@ -29,6 +30,9 @@ type Response struct {
|
|||||||
Message string ` + "`" + `json:"message"` + "`" + `
|
Message string ` + "`" + `json:"message"` + "`" + `
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@server(
|
||||||
|
group: greet
|
||||||
|
)
|
||||||
service A-api {
|
service A-api {
|
||||||
@server(
|
@server(
|
||||||
handler: GreetHandler
|
handler: GreetHandler
|
||||||
@@ -37,6 +41,7 @@ service A-api {
|
|||||||
|
|
||||||
@server(
|
@server(
|
||||||
handler: NoResponseHandler
|
handler: NoResponseHandler
|
||||||
|
|
||||||
)
|
)
|
||||||
get /greet/get(Request) returns
|
get /greet/get(Request) returns
|
||||||
}
|
}
|
||||||
@@ -204,6 +209,75 @@ service A-api {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const hasCommentApiTest = `
|
||||||
|
type Inline struct {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
Inline
|
||||||
|
Name string ` + "`" + `path:"name,options=you|me"` + "`" + ` // name in path
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Message string ` + "`" + `json:"msg"` + "`" + ` // message
|
||||||
|
}
|
||||||
|
|
||||||
|
service A-api {
|
||||||
|
@doc(helloworld)
|
||||||
|
@server(
|
||||||
|
handler: GreetHandler
|
||||||
|
)
|
||||||
|
get /greet/from/:name(Request) returns (Response)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const hasInlineNoExistTest = `
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
Inline
|
||||||
|
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Message string ` + "`" + `json:"message"` + "`" + ` // message
|
||||||
|
}
|
||||||
|
|
||||||
|
service A-api {
|
||||||
|
@doc(helloworld)
|
||||||
|
@server(
|
||||||
|
handler: GreetHandler
|
||||||
|
)
|
||||||
|
get /greet/from/:name(Request) returns (Response)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const importApi = `
|
||||||
|
type ImportData struct {
|
||||||
|
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
|
||||||
|
}
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
const hasImportApi = `
|
||||||
|
import "importApi.api"
|
||||||
|
|
||||||
|
type Request struct {
|
||||||
|
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
|
||||||
|
}
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
Message string ` + "`" + `json:"message"` + "`" + ` // message
|
||||||
|
}
|
||||||
|
|
||||||
|
service A-api {
|
||||||
|
@server(
|
||||||
|
handler: GreetHandler
|
||||||
|
)
|
||||||
|
get /greet/from/:name(Request) returns (Response)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
func TestParser(t *testing.T) {
|
func TestParser(t *testing.T) {
|
||||||
filename := "greet.api"
|
filename := "greet.api"
|
||||||
err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
|
err := ioutil.WriteFile(filename, []byte(testApiTemplate), os.ModePerm)
|
||||||
@@ -367,6 +441,64 @@ func TestApiRoutes(t *testing.T) {
|
|||||||
validate(t, filename)
|
validate(t, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHasCommentRoutes(t *testing.T) {
|
||||||
|
filename := "greet.api"
|
||||||
|
err := ioutil.WriteFile(filename, []byte(hasCommentApiTest), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(filename)
|
||||||
|
|
||||||
|
parser, err := parser.NewParser(filename)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = parser.Parse()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
validate(t, filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInlineTypeNotExist(t *testing.T) {
|
||||||
|
filename := "greet.api"
|
||||||
|
err := ioutil.WriteFile(filename, []byte(hasInlineNoExistTest), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(filename)
|
||||||
|
|
||||||
|
parser, err := parser.NewParser(filename)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
_, err = parser.Parse()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
validate(t, filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHasImportApi(t *testing.T) {
|
||||||
|
filename := "greet.api"
|
||||||
|
err := ioutil.WriteFile(filename, []byte(hasImportApi), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(filename)
|
||||||
|
|
||||||
|
importApiName := "importApi.api"
|
||||||
|
err = ioutil.WriteFile(importApiName, []byte(importApi), os.ModePerm)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer os.Remove(importApiName)
|
||||||
|
|
||||||
|
parser, err := parser.NewParser(filename)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
api, err := parser.Parse()
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
var hasInline bool
|
||||||
|
for _, ty := range api.Types {
|
||||||
|
if ty.Name == "ImportData" {
|
||||||
|
hasInline = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.True(t, hasInline)
|
||||||
|
validate(t, filename)
|
||||||
|
}
|
||||||
|
|
||||||
func validate(t *testing.T, api string) {
|
func validate(t *testing.T, api string) {
|
||||||
dir := "_go"
|
dir := "_go"
|
||||||
err := DoGenProject(api, dir, true)
|
err := DoGenProject(api, dir, true)
|
||||||
@@ -380,6 +512,9 @@ func validate(t *testing.T, api string) {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
_, err = execx.Run("go test ./...", dir)
|
||||||
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateCode(code string) error {
|
func validateCode(code string) error {
|
||||||
|
|||||||
@@ -60,8 +60,9 @@ func genConfig(dir string, api *spec.ApiSpec) error {
|
|||||||
"auth": strings.Join(auths, "\n"),
|
"auth": strings.Join(auths, "\n"),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
_, err = fp.WriteString(formatCode)
|
_, err = fp.WriteString(formatCode)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ func genEtc(dir string, api *spec.ApiSpec) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
_, err = fp.WriteString(formatCode)
|
_, err = fp.WriteString(formatCode)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ func doGenToFile(dir, handler string, group spec.Group, route spec.Route, handle
|
|||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
err = template.Must(template.New("handlerTemplate").Parse(text)).Execute(buffer, handleObj)
|
err = template.Must(template.New("handlerTemplate").Parse(text)).Execute(buffer, handleObj)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
|
|||||||
@@ -72,8 +72,9 @@ func genMain(dir string, api *spec.ApiSpec) error {
|
|||||||
"serviceName": api.Service.Name,
|
"serviceName": api.Service.Name,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
_, err = fp.WriteString(formatCode)
|
_, err = fp.WriteString(formatCode)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -49,8 +49,9 @@ func genMiddleware(dir string, middlewares []string) error {
|
|||||||
"name": strings.Title(name),
|
"name": strings.Title(name),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
_, err = fp.WriteString(formatCode)
|
_, err = fp.WriteString(formatCode)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ type (
|
|||||||
jwtEnabled bool
|
jwtEnabled bool
|
||||||
signatureEnabled bool
|
signatureEnabled bool
|
||||||
authName string
|
authName string
|
||||||
middleware []string
|
middlewares []string
|
||||||
}
|
}
|
||||||
route struct {
|
route struct {
|
||||||
method string
|
method string
|
||||||
@@ -92,9 +92,9 @@ func genRoutes(dir string, api *spec.ApiSpec, force bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var routes string
|
var routes string
|
||||||
if len(g.middleware) > 0 {
|
if len(g.middlewares) > 0 {
|
||||||
gbuilder.WriteString("\n}...,")
|
gbuilder.WriteString("\n}...,")
|
||||||
var params = g.middleware
|
var params = g.middlewares
|
||||||
for i := range params {
|
for i := range params {
|
||||||
params[i] = "serverCtx." + params[i]
|
params[i] = "serverCtx." + params[i]
|
||||||
}
|
}
|
||||||
@@ -143,8 +143,9 @@ func genRoutes(dir string, api *spec.ApiSpec, force bool) error {
|
|||||||
"routesAdditions": strings.TrimSpace(builder.String()),
|
"routesAdditions": strings.TrimSpace(builder.String()),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
_, err = fp.WriteString(formatCode)
|
_, err = fp.WriteString(formatCode)
|
||||||
return err
|
return err
|
||||||
@@ -206,7 +207,7 @@ func getRoutes(api *spec.ApiSpec) ([]group, error) {
|
|||||||
}
|
}
|
||||||
if value, ok := apiutil.GetAnnotationValue(g.Annotations, "server", "middleware"); ok {
|
if value, ok := apiutil.GetAnnotationValue(g.Annotations, "server", "middleware"); ok {
|
||||||
for _, item := range strings.Split(value, ",") {
|
for _, item := range strings.Split(value, ",") {
|
||||||
groupedRoutes.middleware = append(groupedRoutes.middleware, item)
|
groupedRoutes.middlewares = append(groupedRoutes.middlewares, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
routes = append(routes, groupedRoutes)
|
routes = append(routes, groupedRoutes)
|
||||||
|
|||||||
@@ -90,8 +90,9 @@ func genServiceContext(dir string, api *spec.ApiSpec) error {
|
|||||||
"middlewareAssignment": middlewareAssignment,
|
"middlewareAssignment": middlewareAssignment,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
_, err = fp.WriteString(formatCode)
|
_, err = fp.WriteString(formatCode)
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -71,8 +71,9 @@ func genTypes(dir string, api *spec.ApiSpec, force bool) error {
|
|||||||
"containsTime": api.ContainsTime(),
|
"containsTime": api.ContainsTime(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
formatCode := formatCode(buffer.String())
|
formatCode := formatCode(buffer.String())
|
||||||
_, err = fp.WriteString(formatCode)
|
_, err = fp.WriteString(formatCode)
|
||||||
return err
|
return err
|
||||||
@@ -90,12 +91,6 @@ func convertTypeCase(types []spec.Type, t string) (string, error) {
|
|||||||
if typ.Name == tp {
|
if typ.Name == tp {
|
||||||
defTypes = append(defTypes, tp)
|
defTypes = append(defTypes, tp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(typ.Annotations) > 0 {
|
|
||||||
if value, ok := apiutil.GetAnnotationValue(typ.Annotations, "serverReplacer", tp); ok {
|
|
||||||
t = strings.ReplaceAll(t, tp, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
const apiTemplate = `
|
const apiTemplate = `
|
||||||
type Request struct {
|
type Request struct {
|
||||||
Name string ` + "`" + `path:"name,options=you|me"` + "`" + ` // 框架自动验证请求参数是否合法
|
Name string ` + "`" + `path:"name,options=you|me"` + "`" + `
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ func NewParser(filename string) (*Parser, error) {
|
|||||||
if len(ip) > 0 {
|
if len(ip) > 0 {
|
||||||
item := strings.TrimPrefix(item, "import")
|
item := strings.TrimPrefix(item, "import")
|
||||||
item = strings.TrimSpace(item)
|
item = strings.TrimSpace(item)
|
||||||
|
item = strings.TrimPrefix(item, `"`)
|
||||||
|
item = strings.TrimSuffix(item, `"`)
|
||||||
var path = item
|
var path = item
|
||||||
if !util.FileExists(item) {
|
if !util.FileExists(item) {
|
||||||
path = filepath.Join(filepath.Dir(apiAbsPath), item)
|
path = filepath.Join(filepath.Dir(apiAbsPath), item)
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func ParseApi(api string) (*ApiStruct, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isImportBeginLine(line string) bool {
|
func isImportBeginLine(line string) bool {
|
||||||
return strings.HasPrefix(line, "import") && strings.HasSuffix(line, ".api")
|
return strings.HasPrefix(line, "import") && (strings.HasSuffix(line, ".api") || strings.HasSuffix(line, `.api"`))
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTypeBeginLine(line string) bool {
|
func isTypeBeginLine(line string) bool {
|
||||||
|
|||||||
@@ -2,16 +2,58 @@ package docker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/gen"
|
"github.com/tal-tech/go-zero/tools/goctl/gen"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
etcDir = "etc"
|
||||||
|
yamlEtx = ".yaml"
|
||||||
|
)
|
||||||
|
|
||||||
func DockerCommand(c *cli.Context) error {
|
func DockerCommand(c *cli.Context) error {
|
||||||
goFile := c.String("go")
|
goFile := c.String("go")
|
||||||
if len(goFile) == 0 {
|
if len(goFile) == 0 {
|
||||||
return errors.New("-go can't be empty")
|
return errors.New("-go can't be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
return gen.GenerateDockerfile(goFile, "-f", "etc/config.yaml")
|
cfg, err := findConfig(goFile, etcDir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gen.GenerateDockerfile(goFile, "-f", "etc/"+cfg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func findConfig(file, dir string) (string, error) {
|
||||||
|
var files []string
|
||||||
|
err := filepath.Walk(dir, func(path string, f os.FileInfo, _ error) error {
|
||||||
|
if !f.IsDir() {
|
||||||
|
if filepath.Ext(f.Name()) == yamlEtx {
|
||||||
|
files = append(files, f.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) == 0 {
|
||||||
|
return "", errors.New("no yaml file")
|
||||||
|
}
|
||||||
|
|
||||||
|
name := strings.TrimSuffix(filepath.Base(file), ".go")
|
||||||
|
for _, f := range files {
|
||||||
|
if strings.Index(f, name) == 0 {
|
||||||
|
return f, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files[0], nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/util"
|
"github.com/tal-tech/go-zero/tools/goctl/util"
|
||||||
"github.com/tal-tech/go-zero/tools/goctl/vars"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenerateDockerfile(goFile string, args ...string) error {
|
func GenerateDockerfile(goFile string, args ...string) error {
|
||||||
@@ -33,10 +32,9 @@ func GenerateDockerfile(goFile string, args ...string) error {
|
|||||||
|
|
||||||
t := template.Must(template.New("dockerfile").Parse(dockerTemplate))
|
t := template.Must(template.New("dockerfile").Parse(dockerTemplate))
|
||||||
return t.Execute(out, map[string]string{
|
return t.Execute(out, map[string]string{
|
||||||
"projectName": vars.ProjectName,
|
"goRelPath": projPath,
|
||||||
"goRelPath": projPath,
|
"goFile": goFile,
|
||||||
"goFile": goFile,
|
"exeFile": util.FileNameWithoutExt(filepath.Base(goFile)),
|
||||||
"exeFile": util.FileNameWithoutExt(goFile),
|
"argument": builder.String(),
|
||||||
"argument": builder.String(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ ENV CGO_ENABLED 0
|
|||||||
ENV GOOS linux
|
ENV GOOS linux
|
||||||
ENV GOPROXY https://goproxy.cn,direct
|
ENV GOPROXY https://goproxy.cn,direct
|
||||||
|
|
||||||
WORKDIR $GOPATH/src/{{.projectName}}
|
WORKDIR /build/zero
|
||||||
COPY . .
|
COPY . .
|
||||||
|
COPY {{.goRelPath}}/etc /app/etc
|
||||||
RUN go build -ldflags="-s -w" -o /app/{{.exeFile}} {{.goRelPath}}/{{.goFile}}
|
RUN go build -ldflags="-s -w" -o /app/{{.exeFile}} {{.goRelPath}}/{{.goFile}}
|
||||||
|
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ ENV TZ Asia/Shanghai
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /app/{{.exeFile}} /app/{{.exeFile}}
|
COPY --from=builder /app/{{.exeFile}} /app/{{.exeFile}}
|
||||||
|
COPY --from=builder /app/etc /app/etc
|
||||||
|
|
||||||
CMD ["./{{.exeFile}}"{{.argument}}]
|
CMD ["./{{.exeFile}}"{{.argument}}]
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BuildVersion = "20201021"
|
BuildVersion = "20201108"
|
||||||
commands = []cli.Command{
|
commands = []cli.Command{
|
||||||
{
|
{
|
||||||
Name: "api",
|
Name: "api",
|
||||||
@@ -188,16 +188,12 @@ var (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "docker",
|
Name: "docker",
|
||||||
Usage: "generate Dockerfile and Makefile",
|
Usage: "generate Dockerfile",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "go",
|
Name: "go",
|
||||||
Usage: "the file that contains main function",
|
Usage: "the file that contains main function",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "namespace, n",
|
|
||||||
Usage: "which namespace of kubernetes to deploy the service",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Action: docker.DockerCommand,
|
Action: docker.DockerCommand,
|
||||||
},
|
},
|
||||||
@@ -224,10 +220,6 @@ var (
|
|||||||
Name: "out, o",
|
Name: "out, o",
|
||||||
Usage: "the target path of proto",
|
Usage: "the target path of proto",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "idea",
|
|
||||||
Usage: "whether the command execution environment is from idea plugin. [optional]",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Action: rpc.RpcTemplate,
|
Action: rpc.RpcTemplate,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
|
|
||||||
* 生成代码示例
|
* 生成代码示例
|
||||||
|
|
||||||
``` go
|
```go
|
||||||
|
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -48,9 +49,9 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
|
userRowsExpectAutoSet = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), ",")
|
||||||
userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
|
userRowsWithPlaceHolder = strings.Join(stringx.Remove(userFieldNames, "id", "create_time", "update_time"), "=?,") + "=?"
|
||||||
|
|
||||||
cacheUserMobilePrefix = "cache#User#mobile#"
|
|
||||||
cacheUserIdPrefix = "cache#User#id#"
|
cacheUserIdPrefix = "cache#User#id#"
|
||||||
cacheUserNamePrefix = "cache#User#name#"
|
cacheUserNamePrefix = "cache#User#name#"
|
||||||
|
cacheUserMobilePrefix = "cache#User#mobile#"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -71,23 +72,28 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf, table string) *UserModel {
|
func NewUserModel(conn sqlx.SqlConn, c cache.CacheConf) *UserModel {
|
||||||
return &UserModel{
|
return &UserModel{
|
||||||
CachedConn: sqlc.NewConn(conn, c),
|
CachedConn: sqlc.NewConn(conn, c),
|
||||||
table: table,
|
table: "user",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UserModel) Insert(data User) (sql.Result, error) {
|
func (m *UserModel) Insert(data User) (sql.Result, error) {
|
||||||
query := `insert into ` + m.table + `(` + userRowsExpectAutoSet + `) value (?, ?, ?, ?, ?)`
|
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
|
||||||
return m.ExecNoCache(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
|
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
|
||||||
|
ret, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, userRowsExpectAutoSet)
|
||||||
|
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname)
|
||||||
|
}, userNameKey, userMobileKey)
|
||||||
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *UserModel) FindOne(id int64) (*User, error) {
|
func (m *UserModel) FindOne(id int64) (*User, error) {
|
||||||
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
||||||
var resp User
|
var resp User
|
||||||
err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
|
err := m.QueryRow(&resp, userIdKey, func(conn sqlx.SqlConn, v interface{}) error {
|
||||||
query := `select ` + userRows + ` from ` + m.table + ` where id = ? limit 1`
|
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
|
||||||
return conn.QueryRow(v, query, id)
|
return conn.QueryRow(v, query, id)
|
||||||
})
|
})
|
||||||
switch err {
|
switch err {
|
||||||
@@ -103,18 +109,13 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
func (m *UserModel) FindOneByName(name string) (*User, error) {
|
func (m *UserModel) FindOneByName(name string) (*User, error) {
|
||||||
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
|
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, name)
|
||||||
var resp User
|
var resp User
|
||||||
err := m.QueryRowIndex(&resp, userNameKey, func(primary interface{}) string {
|
err := m.QueryRowIndex(&resp, userNameKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||||
return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
|
query := fmt.Sprintf("select %s from %s where name = ? limit 1", userRows, m.table)
|
||||||
}, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
|
||||||
query := `select ` + userRows + ` from ` + m.table + ` where name = ? limit 1`
|
|
||||||
if err := conn.QueryRow(&resp, query, name); err != nil {
|
if err := conn.QueryRow(&resp, query, name); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return resp.Id, nil
|
return resp.Id, nil
|
||||||
}, func(conn sqlx.SqlConn, v, primary interface{}) error {
|
}, m.queryPrimary)
|
||||||
query := `select ` + userRows + ` from ` + m.table + ` where id = ? limit 1`
|
|
||||||
return conn.QueryRow(v, query, primary)
|
|
||||||
})
|
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
@@ -128,18 +129,13 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
func (m *UserModel) FindOneByMobile(mobile string) (*User, error) {
|
func (m *UserModel) FindOneByMobile(mobile string) (*User, error) {
|
||||||
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
|
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, mobile)
|
||||||
var resp User
|
var resp User
|
||||||
err := m.QueryRowIndex(&resp, userMobileKey, func(primary interface{}) string {
|
err := m.QueryRowIndex(&resp, userMobileKey, m.formatPrimary, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
||||||
return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
|
query := fmt.Sprintf("select %s from %s where mobile = ? limit 1", userRows, m.table)
|
||||||
}, func(conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
|
|
||||||
query := `select ` + userRows + ` from ` + m.table + ` where mobile = ? limit 1`
|
|
||||||
if err := conn.QueryRow(&resp, query, mobile); err != nil {
|
if err := conn.QueryRow(&resp, query, mobile); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return resp.Id, nil
|
return resp.Id, nil
|
||||||
}, func(conn sqlx.SqlConn, v, primary interface{}) error {
|
}, m.queryPrimary)
|
||||||
query := `select ` + userRows + ` from ` + m.table + ` where id = ? limit 1`
|
|
||||||
return conn.QueryRow(v, query, primary)
|
|
||||||
})
|
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
@@ -153,7 +149,7 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
func (m *UserModel) Update(data User) error {
|
func (m *UserModel) Update(data User) error {
|
||||||
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
|
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, data.Id)
|
||||||
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
_, err := m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := `update ` + m.table + ` set ` + userRowsWithPlaceHolder + ` where id = ?`
|
query := fmt.Sprintf("update %s set %s where id = ?", m.table, userRowsWithPlaceHolder)
|
||||||
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
|
return conn.Exec(query, data.Name, data.Password, data.Mobile, data.Gender, data.Nickname, data.Id)
|
||||||
}, userIdKey)
|
}, userIdKey)
|
||||||
return err
|
return err
|
||||||
@@ -164,16 +160,26 @@ goctl model 为go-zero下的工具模块中的组件之一,目前支持识别m
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
|
||||||
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
userIdKey := fmt.Sprintf("%s%v", cacheUserIdPrefix, id)
|
||||||
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
|
userNameKey := fmt.Sprintf("%s%v", cacheUserNamePrefix, data.Name)
|
||||||
userMobileKey := fmt.Sprintf("%s%v", cacheUserMobilePrefix, data.Mobile)
|
|
||||||
_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
_, err = m.Exec(func(conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||||
query := `delete from ` + m.table + ` where id = ?`
|
query := fmt.Sprintf("delete from %s where id = ?", m.table)
|
||||||
return conn.Exec(query, id)
|
return conn.Exec(query, id)
|
||||||
}, userIdKey, userNameKey, userMobileKey)
|
}, userMobileKey, userIdKey, userNameKey)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
func (m *UserModel) formatPrimary(primary interface{}) string {
|
||||||
|
return fmt.Sprintf("%s%v", cacheUserIdPrefix, primary)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *UserModel) queryPrimary(conn sqlx.SqlConn, v, primary interface{}) error {
|
||||||
|
query := fmt.Sprintf("select %s from %s where id = ? limit 1", userRows, m.table)
|
||||||
|
return conn.QueryRow(v, query, primary)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 用法
|
## 用法
|
||||||
|
|
||||||
@@ -212,16 +218,18 @@ OPTIONS:
|
|||||||
|
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
goctl model mysql ddl - generate mysql model from ddl
|
goctl model mysql ddl - generate mysql model from ddl
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
goctl model mysql ddl [command options] [arguments...]
|
goctl model mysql ddl [command options] [arguments...]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--src value, -s value the path or path globbing patterns of the ddl
|
||||||
|
--dir value, -d value the target dir
|
||||||
|
--style value the file naming style, lower|camel|underline,default is lower
|
||||||
|
--cache, -c generate code with cache [optional]
|
||||||
|
--idea for idea plugin [optional]
|
||||||
|
|
||||||
OPTIONS:
|
|
||||||
--src value, -s value the path or path globbing patterns of the ddl
|
|
||||||
--dir value, -d value the target dir
|
|
||||||
--cache, -c generate code with cache [optional]
|
|
||||||
--idea for idea plugin [optional]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* datasource
|
* datasource
|
||||||
@@ -233,22 +241,26 @@ OPTIONS:
|
|||||||
help
|
help
|
||||||
|
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
goctl model mysql datasource - generate model from datasource
|
goctl model mysql datasource - generate model from datasource
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
goctl model mysql datasource [command options] [arguments...]
|
goctl model mysql datasource [command options] [arguments...]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--url value the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
|
||||||
|
--table value, -t value the table or table globbing patterns in the database
|
||||||
|
--cache, -c generate code with cache [optional]
|
||||||
|
--dir value, -d value the target dir
|
||||||
|
--style value the file naming style, lower|camel|snake, default is lower
|
||||||
|
--idea for idea plugin [optional]
|
||||||
|
|
||||||
OPTIONS:
|
|
||||||
--url value the data source of database,like "root:password@tcp(127.0.0.1:3306)/database
|
|
||||||
--table value, -t value the table or table globbing patterns in the database
|
|
||||||
--cache, -c generate code with cache [optional]
|
|
||||||
--dir value, -d value the target dir
|
|
||||||
--idea for idea plugin [optional]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
示例用法请参考[用法](./example/generator.sh)
|
示例用法请参考[用法](./example/generator.sh)
|
||||||
|
|
||||||
|
> NOTE: goctl model mysql ddl/datasource 均新增了一个`--style`参数,用于标记文件命名风格。
|
||||||
|
|
||||||
目前仅支持redis缓存,如果选择带缓存模式,即生成的`FindOne(ByXxx)`&`Delete`代码会生成带缓存逻辑的代码,目前仅支持单索引字段(除全文索引外),对于联合索引我们默认认为不需要带缓存,且不属于通用型代码,因此没有放在代码生成行列,如example中user表中的`id`、`name`、`mobile`字段均属于单字段索引。
|
目前仅支持redis缓存,如果选择带缓存模式,即生成的`FindOne(ByXxx)`&`Delete`代码会生成带缓存逻辑的代码,目前仅支持单索引字段(除全文索引外),对于联合索引我们默认认为不需要带缓存,且不属于通用型代码,因此没有放在代码生成行列,如example中user表中的`id`、`name`、`mobile`字段均属于单字段索引。
|
||||||
|
|
||||||
* 不带缓存模式
|
* 不带缓存模式
|
||||||
|
|||||||
@@ -26,26 +26,49 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块,支持prot
|
|||||||
|
|
||||||
```golang
|
```golang
|
||||||
.
|
.
|
||||||
├── etc // 配置文件
|
├── etc // yaml配置文件
|
||||||
│ └── greet.yaml
|
│ └── greet.yaml
|
||||||
├── go.mod
|
├── go.mod
|
||||||
├── greet // client call
|
├── greet // pb.go文件夹①
|
||||||
│ └── greet.go
|
│ └── greet.pb.go
|
||||||
├── greet.go // main entry
|
├── greet.go // main函数
|
||||||
├── greet.proto
|
├── greet.proto // proto 文件
|
||||||
└── internal
|
├── greetclient // call logic ②
|
||||||
├── config // 配置声明
|
│ └── greet.go
|
||||||
│ └── config.go
|
└── internal
|
||||||
├── greet // pb.go
|
├── config // yaml配置对应的实体
|
||||||
│ └── greet.pb.go
|
│ └── config.go
|
||||||
├── logic // logic
|
├── logic // 业务代码
|
||||||
│ └── pinglogic.go
|
│ └── pinglogic.go
|
||||||
├── server // pb invoker
|
├── server // rpc server
|
||||||
│ └── greetserver.go
|
│ └── greetserver.go
|
||||||
└── svc // resource dependency
|
└── svc // 依赖资源
|
||||||
└── servicecontext.go
|
└── servicecontext.go
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> ① pb文件夹名(老版本文件夹固定为pb)称取自于proto文件中option go_package的值最后一层级按照一定格式进行转换,若无此声明,则取自于package的值,大致代码如下:
|
||||||
|
|
||||||
|
```go
|
||||||
|
if option.Name == "go_package" {
|
||||||
|
ret.GoPackage = option.Constant.Source
|
||||||
|
}
|
||||||
|
...
|
||||||
|
if len(ret.GoPackage) == 0 {
|
||||||
|
ret.GoPackage = ret.Package.Name
|
||||||
|
}
|
||||||
|
ret.PbPackage = GoSanitized(filepath.Base(ret.GoPackage))
|
||||||
|
...
|
||||||
|
```
|
||||||
|
> GoSanitized方法请参考google.golang.org/protobuf@v1.25.0/internal/strs/strings.go:71
|
||||||
|
|
||||||
|
> ② call 层文件夹名称取自于proto中service的名称,如该sercice的名称和pb文件夹名称相等,则会在srervice后面补充client进行区分,使pb和call分隔。
|
||||||
|
|
||||||
|
```go
|
||||||
|
if strings.ToLower(proto.Service.Name) == strings.ToLower(proto.GoPackage) {
|
||||||
|
callDir = filepath.Join(ctx.WorkDir, strings.ToLower(stringx.From(proto.Service.Name+"_client").ToCamel()))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
rpc一键生成常见问题解决,见 <a href="#常见问题解决">常见问题解决</a>
|
rpc一键生成常见问题解决,见 <a href="#常见问题解决">常见问题解决</a>
|
||||||
|
|
||||||
### 方式二:通过指定proto生成rpc服务
|
### 方式二:通过指定proto生成rpc服务
|
||||||
@@ -110,8 +133,8 @@ USAGE:
|
|||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
--src value, -s value the file path of the proto source file
|
--src value, -s value the file path of the proto source file
|
||||||
--proto_path value, -I value native command of protoc,specify the directory in which to search for imports. [optional]
|
--proto_path value, -I value native command of protoc, specify the directory in which to search for imports. [optional]
|
||||||
--dir value, -d value the target path of the code,default path is "${pwd}". [optional]
|
--dir value, -d value the target path of the code
|
||||||
--idea whether the command execution environment is from idea plugin. [optional]
|
--idea whether the command execution environment is from idea plugin. [optional]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -59,9 +59,10 @@ func RpcNew(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RpcTemplate(c *cli.Context) error {
|
func RpcTemplate(c *cli.Context) error {
|
||||||
name := c.Args().First()
|
protoFile := c.String("o")
|
||||||
if len(name) == 0 {
|
if len(protoFile) == 0 {
|
||||||
name = "greet.proto"
|
return errors.New("missing -o")
|
||||||
}
|
}
|
||||||
return generator.ProtoTmpl(name)
|
|
||||||
|
return generator.ProtoTmpl(protoFile)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,13 +68,12 @@ func (s *rpcServer) Start(register RegisterFn) error {
|
|||||||
register(server)
|
register(server)
|
||||||
// we need to make sure all others are wrapped up
|
// we need to make sure all others are wrapped up
|
||||||
// so we do graceful stop at shutdown phase instead of wrap up phase
|
// so we do graceful stop at shutdown phase instead of wrap up phase
|
||||||
shutdownCalled := proc.AddShutdownListener(func() {
|
waitForCalled := proc.AddWrapUpListener(func() {
|
||||||
server.GracefulStop()
|
server.GracefulStop()
|
||||||
})
|
})
|
||||||
err = server.Serve(lis)
|
defer waitForCalled()
|
||||||
shutdownCalled()
|
|
||||||
|
|
||||||
return err
|
return server.Serve(lis)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithMetrics(metrics *stat.Metrics) ServerOption {
|
func WithMetrics(metrics *stat.Metrics) ServerOption {
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ import (
|
|||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const envPodIp = "POD_IP"
|
const (
|
||||||
|
allEths = "0.0.0.0"
|
||||||
|
envPodIp = "POD_IP"
|
||||||
|
)
|
||||||
|
|
||||||
type RpcServer struct {
|
type RpcServer struct {
|
||||||
server internal.Server
|
server internal.Server
|
||||||
@@ -96,7 +99,7 @@ func figureOutListenOn(listenOn string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
host := fields[0]
|
host := fields[0]
|
||||||
if len(host) > 0 && host != "0.0.0.0" {
|
if len(host) > 0 && host != allEths {
|
||||||
return listenOn
|
return listenOn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user