mgrpc: generate first example service

With this changeset, we have the first end to end generated server and
client. Most of the necessary types are in place and working. There are
a lot of details to work out, but this would be enough for to exercise
the end to end flow.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
Stephen J Day 2017-11-14 18:56:09 -08:00
parent 71e9170d05
commit f32bbe9f11
No known key found for this signature in database
GPG Key ID: 67B3DED84EDC823F
3 changed files with 153 additions and 2 deletions

View File

@ -1,6 +1,6 @@
version = "unstable"
generator = "gogomgrpc"
plugins = []
plugins = ["mgrpc"]
# Control protoc include paths. Below are usually some good defaults, but feel
# free to try it without them if it works for your project.
@ -24,6 +24,7 @@ plugins = []
[packages]
"gogoproto/gogo.proto" = "github.com/gogo/protobuf/gogoproto"
"google/protobuf/any.proto" = "github.com/gogo/protobuf/types"
"google/protobuf/empty.proto" = "github.com/gogo/protobuf/types"
"google/protobuf/descriptor.proto" = "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"google/protobuf/field_mask.proto" = "github.com/gogo/protobuf/types"
"google/protobuf/timestamp.proto" = "github.com/gogo/protobuf/types"

View File

@ -18,10 +18,13 @@ import proto "github.com/gogo/protobuf/proto"
import fmt "fmt"
import math "math"
import _ "github.com/gogo/protobuf/types"
import _ "github.com/golang/protobuf/ptypes/empty"
import google_protobuf1 "github.com/gogo/protobuf/types"
import _ "github.com/gogo/protobuf/gogoproto"
import _ "github.com/gogo/protobuf/types"
import context "context"
import github_com_stevvooe_mgrpc "github.com/stevvooe/mgrpc"
import strings "strings"
import reflect "reflect"
@ -180,6 +183,42 @@ func encodeVarintExample(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v)
return offset + 1
}
type ExampleService interface {
Method1(ctx context.Context, req *Method1Request) (*Method1Response, error)
Method2(ctx context.Context, req *Method1Request) (*google_protobuf1.Empty, error)
}
func RegisterExampleService(srv *github_com_stevvooe_mgrpc.Server, svc ExampleService) error {
return srv.Register("mgrpc.example.v1.Example", map[string]github_com_stevvooe_mgrpc.Handler{
"Method1": github_com_stevvooe_mgrpc.HandlerFunc(func(ctx context.Context, req interface{}) (interface{}, error) {
return svc.Method1(ctx, req.(*Method1Request))
}),
"Method2": github_com_stevvooe_mgrpc.HandlerFunc(func(ctx context.Context, req interface{}) (interface{}, error) {
return svc.Method2(ctx, req.(*Method1Request))
}),
})
}
type ExampleClient struct {
client *github_com_stevvooe_mgrpc.Client
}
func (c *ExampleClient) Method1(ctx context.Context, req *Method1Request) (*Method1Response, error) {
resp, err := c.client.Call(ctx, "mgrpc.example.v1.Example", "Method1", req)
if err != nil {
return nil, err
}
return resp.(*Method1Response), nil
}
func (c *ExampleClient) Method2(ctx context.Context, req *Method1Request) (*google_protobuf1.Empty, error) {
resp, err := c.client.Call(ctx, "mgrpc.example.v1.Example", "Method2", req)
if err != nil {
return nil, err
}
return resp.(*google_protobuf1.Empty), nil
}
func (m *Method1Request) Size() (n int) {
var l int
_ = l

111
generator.go Normal file
View File

@ -0,0 +1,111 @@
package mgrpc
import (
"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type mgrpcGenerator struct {
*generator.Generator
generator.PluginImports
typeurlPkg generator.Single
mgrpcPkg generator.Single
contextPkg generator.Single
}
func init() {
generator.RegisterPlugin(new(mgrpcGenerator))
}
func (p *mgrpcGenerator) Name() string {
return "mgrpc"
}
func (p *mgrpcGenerator) Init(g *generator.Generator) {
p.Generator = g
}
func (p *mgrpcGenerator) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.contextPkg = p.NewImport("context")
p.typeurlPkg = p.NewImport("github.com/containerd/typeurl")
p.mgrpcPkg = p.NewImport("github.com/stevvooe/mgrpc")
for _, service := range file.GetService() {
serviceName := service.GetName()
if pkg := file.GetPackage(); pkg != "" {
serviceName = pkg + "." + serviceName
}
p.genService(serviceName, service)
}
}
func (p *mgrpcGenerator) genService(fullName string, service *descriptor.ServiceDescriptorProto) {
serviceName := service.GetName() + "Service"
p.P()
p.P("type ", serviceName, " interface{")
p.In()
for _, method := range service.Method {
p.P(method.GetName(),
"(ctx ", p.contextPkg.Use(), ".Context, ",
"req *", p.typeName(method.GetInputType()), ") ",
"(*", p.typeName(method.GetOutputType()), ", error)")
}
p.Out()
p.P("}")
p.P()
// registration method
p.P("func Register", serviceName, "(srv *", p.mgrpcPkg.Use(), ".Server, svc ", serviceName, ") error {")
p.In()
p.P(`return srv.Register("`, fullName, `", map[string]`, p.mgrpcPkg.Use(), ".Handler{")
p.In()
for _, method := range service.Method {
p.P(`"`, method.GetName(), `": `, p.mgrpcPkg.Use(), `.HandlerFunc(func(ctx context.Context, req interface{}) (interface{}, error) {`)
p.In()
p.P("return svc.", method.GetName(), "(ctx, req.(*", p.typeName(method.GetInputType()), "))")
p.Out()
p.P("}),")
}
p.Out()
p.P("})")
p.Out()
p.P("}")
clientType := service.GetName() + "Client"
p.P()
p.P("type ", clientType, " struct{")
p.In()
p.P("client *", p.mgrpcPkg.Use(), ".Client")
p.Out()
p.P("}")
for _, method := range service.Method {
p.P()
p.P("func (c *", clientType, ") ", method.GetName(),
"(ctx ", p.contextPkg.Use(), ".Context, ",
"req *", p.typeName(method.GetInputType()), ") ",
"(*", p.typeName(method.GetOutputType()), ", error) {")
p.In()
p.P("resp, err := c.client.Call(ctx, ", `"`+fullName+`", `, `"`+method.GetName()+`"`, ", req)")
p.P("if err != nil {")
p.In()
p.P("return nil, err")
p.Out()
p.P("}")
p.P("return resp.(*", p.typeName(method.GetOutputType()), "), nil")
p.Out()
p.P("}")
}
}
func (p *mgrpcGenerator) objectNamed(name string) generator.Object {
p.Generator.RecordTypeUse(name)
return p.Generator.ObjectNamed(name)
}
func (p *mgrpcGenerator) typeName(str string) string {
return p.Generator.TypeName(p.objectNamed(str))
}