Skip to content

Commit

Permalink
Added flag in order to get proto names on autodoc. Also added autodoc…
Browse files Browse the repository at this point in the history
… to cluster example
  • Loading branch information
gabrielerzinger committed Aug 24, 2018
1 parent 45608d1 commit 49b3d69
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 397 deletions.
6 changes: 3 additions & 3 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -524,12 +524,12 @@ func ExtractSpan(ctx context.Context) (opentracing.SpanContext, error) {
}

// Documentation returns handler and remotes documentacion
func Documentation() (map[string]interface{}, error) {
handlerDocs, err := handlerService.Docs()
func Documentation(getPtrNames bool) (map[string]interface{}, error) {
handlerDocs, err := handlerService.Docs(getPtrNames)
if err != nil {
return nil, err
}
remoteDocs, err := remoteService.Docs()
remoteDocs, err := remoteService.Docs(getPtrNames)
if err != nil {
return nil, err
}
Expand Down
72 changes: 71 additions & 1 deletion app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ func TestExtractSpan(t *testing.T) {
}

func TestDocumentation(t *testing.T) {
doc, err := Documentation()
doc, err := Documentation(false)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"handlers": map[string]interface{}{},
Expand Down Expand Up @@ -538,3 +538,73 @@ func TestDocumentation(t *testing.T) {
},
}, doc)
}

func TestDocumentationTrue(t *testing.T) {
doc, err := Documentation(true)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"remotes": map[string]interface{}{
"testtype.sys.bindsession": map[string]interface{}{
"input": map[string]interface{}{
"*protos.Session": map[string]interface{}{
"data": "[]byte",
"id": "int64",
"uid": "string",
},
},
"output": []interface{}{map[string]interface{}{
"*protos.Response": map[string]interface{}{
"data": "[]byte",
"error": map[string]interface{}{
"*protos.Error": map[string]interface{}{
"code": "string",
"metadata": "map[string]string",
"msg": "string",
},
},
},
},
"error",
},
},
"testtype.sys.kick": map[string]interface{}{
"input": map[string]interface{}{
"*protos.KickMsg": map[string]interface{}{
"userId": "string",
},
},
"output": []interface{}{map[string]interface{}{
"*protos.KickAnswer": map[string]interface{}{
"kicked": "bool",
},
},
"error",
},
},
"testtype.sys.pushsession": map[string]interface{}{
"input": map[string]interface{}{
"*protos.Session": map[string]interface{}{
"data": "[]byte",
"id": "int64",
"uid": "string",
},
},
"output": []interface{}{map[string]interface{}{
"*protos.Response": map[string]interface{}{
"data": "[]byte",
"error": map[string]interface{}{
"*protos.Error": map[string]interface{}{
"code": "string",
"metadata": "map[string]string",
"msg": "string",
},
},
},
},
"error",
},
},
},
"handlers": map[string]interface{}{},
}, doc)
}
36 changes: 23 additions & 13 deletions docgenerator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,31 @@ type doc struct {
}

// HandlersDocs returns a map from route to input and output
func HandlersDocs(serverType string, services map[string]*component.Service) (map[string]interface{}, error) {
func HandlersDocs(serverType string, services map[string]*component.Service, getPtrNames bool) (map[string]interface{}, error) {
docs := &docs{
Handlers: map[string]*doc{},
}

for serviceName, service := range services {
for name, handler := range service.Handlers {
routeName := route.NewRoute(serverType, serviceName, name)
docs.Handlers[routeName.String()] = docForMethod(handler.Method)
docs.Handlers[routeName.String()] = docForMethod(handler.Method, getPtrNames)
}
}

return docs.Handlers.toMap()
}

// RemotesDocs returns a map from route to input and output
func RemotesDocs(serverType string, services map[string]*component.Service) (map[string]interface{}, error) {
func RemotesDocs(serverType string, services map[string]*component.Service, getPtrNames bool) (map[string]interface{}, error) {
docs := &docs{
Remotes: map[string]*doc{},
}

for serviceName, service := range services {
for name, remote := range service.Remotes {
routeName := route.NewRoute(serverType, serviceName, name)
docs.Remotes[routeName.String()] = docForMethod(remote.Method)
docs.Remotes[routeName.String()] = docForMethod(remote.Method, getPtrNames)
}
}

Expand All @@ -87,19 +87,19 @@ func (d docMap) toMap() (map[string]interface{}, error) {
return m, nil
}

func docForMethod(method reflect.Method) *doc {
func docForMethod(method reflect.Method, getPtrNames bool) *doc {
doc := &doc{
Output: []interface{}{},
}

if method.Type.NumIn() > 2 {
isOutput := false
doc.Input = docForType(method.Type.In(2), isOutput)
doc.Input = docForType(method.Type.In(2), isOutput, getPtrNames)
}

for i := 0; i < method.Type.NumOut(); i++ {
isOutput := true
doc.Output = append(doc.Output, docForType(method.Type.Out(i), isOutput))
doc.Output = append(doc.Output, docForType(method.Type.Out(i), isOutput, getPtrNames))
}

return doc
Expand All @@ -114,19 +114,24 @@ func parseStruct(typ reflect.Type) reflect.Type {
}
}

func docForType(typ reflect.Type, isOutput bool) interface{} {
func docForType(typ reflect.Type, isOutput bool, getPtrNames bool) interface{} {
if typ.Kind() == reflect.Ptr {
fields := map[string]interface{}{}
elm := typ.Elem()
for i := 0; i < elm.NumField(); i++ {
if name, valid := getName(elm.Field(i), isOutput); valid {
fields[name] = parseType(elm.Field(i).Type, isOutput)
fields[name] = parseType(elm.Field(i).Type, isOutput, getPtrNames)
}
}
if getPtrNames {
composite := map[string]interface{}{}
composite[typ.String()] = fields
return composite
}
return fields
}

return parseType(typ, isOutput)
return parseType(typ, isOutput, getPtrNames)
}

func validName(field reflect.StructField) bool {
Expand Down Expand Up @@ -170,7 +175,7 @@ func getName(field reflect.StructField, isOutput bool) (name string, valid bool)
return strings.Split(name, ",")[0], true
}

func parseType(typ reflect.Type, isOutput bool) interface{} {
func parseType(typ reflect.Type, isOutput bool, getPtrNames bool) interface{} {
var elm reflect.Type

switch typ.Kind() {
Expand All @@ -182,7 +187,7 @@ func parseType(typ reflect.Type, isOutput bool) interface{} {
return typ.String()
}
case reflect.Slice:
parsed := parseType(typ.Elem(), isOutput)
parsed := parseType(typ.Elem(), isOutput, getPtrNames)
if parsed == "uint8" {
return "[]byte"
}
Expand All @@ -194,8 +199,13 @@ func parseType(typ reflect.Type, isOutput bool) interface{} {
fields := map[string]interface{}{}
for i := 0; i < elm.NumField(); i++ {
if name, valid := getName(elm.Field(i), isOutput); valid {
fields[name] = parseType(elm.Field(i).Type, isOutput)
fields[name] = parseType(elm.Field(i).Type, isOutput, getPtrNames)
}
}
if getPtrNames {
composite := map[string]interface{}{}
composite[typ.String()] = fields
return composite
}
return fields
}
120 changes: 118 additions & 2 deletions docgenerator/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestHandlersDoc(t *testing.T) {
assert.NoError(t, err)
handlerServices[s.Name] = s

doc, err := HandlersDocs("metagame", handlerServices)
doc, err := HandlersDocs("metagame", handlerServices, false)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"metagame.MyComp.HandlerEmpty": map[string]interface{}{
Expand Down Expand Up @@ -164,6 +164,92 @@ func TestHandlersDoc(t *testing.T) {
}, doc)
}

func TestHandlersDocTrue(t *testing.T) {
t.Parallel()

handlerServices := map[string]*component.Service{}
s := component.NewService(&MyComp{}, []component.Option{})
err := s.ExtractHandler()
assert.NoError(t, err)
handlerServices[s.Name] = s

doc, err := HandlersDocs("metagame", handlerServices, false)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"metagame.MyComp.HandlerOrRemoteStruct": map[string]interface{}{
"input": map[string]interface{}{
"time": "time.Time",
"bytes": "[]byte",
"int": "int",
"notPointer": map[string]interface{}{
"int": "int",
"str": "string",
},
"slice": []interface{}{map[string]interface{}{
"int": "int",
"str": "string",
},
},
"str": "string",
"struct": map[string]interface{}{
"int": "int",
"notPointer": map[string]interface{}{
"int": "int",
"str": "string",
},
},
},
"output": []interface{}{map[string]interface{}{
"Str": "string",
"bytes": "[]byte",
"int": "int",
"notPointer": map[string]interface{}{
"Int": "int",
"str": "string",
},
"slice": []interface{}{map[string]interface{}{
"Str": "string",
"int": "int",
},
},
"struct": map[string]interface{}{
"int": "int",
"notPointer": map[string]interface{}{
"Int": "int",
"str": "string",
},
},
"time": "time.Time",
},
"error",
},
},
"metagame.MyComp.HandlerRaw": map[string]interface{}{
"input": "[]byte",
"output": []interface{}{
"[]byte",
"error",
},
},
"metagame.MyComp.RemoteStruct": map[string]interface{}{
"input": map[string]interface{}{
"A": "int32",
"B": "string",
},
"output": []interface{}{map[string]interface{}{
"A": "int32",
"B": "string",
},
"error",
},
},
"metagame.MyComp.HandlerEmpty": map[string]interface{}{
"output": []interface{}{},
"input": interface{}(nil),
},
}, doc)
}

func TestRemotesDoc(t *testing.T) {
t.Parallel()

Expand All @@ -173,7 +259,7 @@ func TestRemotesDoc(t *testing.T) {
assert.NoError(t, err)
remoteServices[s.Name] = s

doc, err := RemotesDocs("metagame", remoteServices)
doc, err := RemotesDocs("metagame", remoteServices, false)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"metagame.MyComp.RemoteStruct": map[string]interface{}{
Expand All @@ -191,3 +277,33 @@ func TestRemotesDoc(t *testing.T) {
},
}, doc)
}

func TestRemotesDocTrue(t *testing.T) {
t.Parallel()
remoteServices := map[string]*component.Service{}
s := component.NewService(&MyComp{}, []component.Option{})
err := s.ExtractRemote()
assert.NoError(t, err)
remoteServices[s.Name] = s
doc, err := RemotesDocs("metagame", remoteServices, true)
assert.NoError(t, err)
assert.Equal(t, map[string]interface{}{
"metagame.MyComp.RemoteStruct": map[string]interface{}{
"input": map[string]interface{}{
"*test.SomeStruct": map[string]interface{}{

"A": "int32",
"B": "string",
},
},
"output": []interface{}{
map[string]interface{}{
"*test.SomeStruct": map[string]interface{}{
"A": "int32",
"B": "string",
}},
"error",
},
},
}, doc)
}
16 changes: 16 additions & 0 deletions examples/demo/cluster/services/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package services

import (
"context"
"encoding/json"
"fmt"

"github.com/topfreegames/pitaya"
Expand Down Expand Up @@ -73,3 +74,18 @@ func (c *ConnectorRemote) RemoteFunc(ctx context.Context, msg *protos.RPCMsg) (*
Msg: msg.GetMsg(),
}, nil
}

// Docs returns documentation
func (c *ConnectorRemote) Docs(ctx context.Context, ddd *protos.Doc) (*protos.Doc, error) {
d, err := pitaya.Documentation(true)
if err != nil {
return nil, err
}
doc, err := json.Marshal(d)

if err != nil {
return nil, err
}

return &protos.Doc{Doc: string(doc)}, nil
}
Loading

0 comments on commit 49b3d69

Please sign in to comment.