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:
		| @@ -1,6 +1,6 @@ | |||||||
| version = "unstable" | version = "unstable" | ||||||
| generator = "gogomgrpc" | generator = "gogomgrpc" | ||||||
| plugins = [] | plugins = ["mgrpc"] | ||||||
|  |  | ||||||
| # Control protoc include paths. Below are usually some good defaults, but feel | # Control protoc include paths. Below are usually some good defaults, but feel | ||||||
| # free to try it without them if it works for your project. | # free to try it without them if it works for your project. | ||||||
| @@ -24,6 +24,7 @@ plugins = [] | |||||||
| [packages] | [packages] | ||||||
|   "gogoproto/gogo.proto" = "github.com/gogo/protobuf/gogoproto" |   "gogoproto/gogo.proto" = "github.com/gogo/protobuf/gogoproto" | ||||||
|   "google/protobuf/any.proto" = "github.com/gogo/protobuf/types" |   "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/descriptor.proto" = "github.com/gogo/protobuf/protoc-gen-gogo/descriptor" | ||||||
|   "google/protobuf/field_mask.proto" = "github.com/gogo/protobuf/types" |   "google/protobuf/field_mask.proto" = "github.com/gogo/protobuf/types" | ||||||
|   "google/protobuf/timestamp.proto" = "github.com/gogo/protobuf/types" |   "google/protobuf/timestamp.proto" = "github.com/gogo/protobuf/types" | ||||||
|   | |||||||
| @@ -18,10 +18,13 @@ import proto "github.com/gogo/protobuf/proto" | |||||||
| import fmt "fmt" | import fmt "fmt" | ||||||
| import math "math" | import math "math" | ||||||
| import _ "github.com/gogo/protobuf/types" | 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/gogoproto" | ||||||
| import _ "github.com/gogo/protobuf/types" | import _ "github.com/gogo/protobuf/types" | ||||||
|  |  | ||||||
|  | import context "context" | ||||||
|  | import github_com_stevvooe_mgrpc "github.com/stevvooe/mgrpc" | ||||||
|  |  | ||||||
| import strings "strings" | import strings "strings" | ||||||
| import reflect "reflect" | import reflect "reflect" | ||||||
|  |  | ||||||
| @@ -180,6 +183,42 @@ func encodeVarintExample(dAtA []byte, offset int, v uint64) int { | |||||||
| 	dAtA[offset] = uint8(v) | 	dAtA[offset] = uint8(v) | ||||||
| 	return offset + 1 | 	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) { | func (m *Method1Request) Size() (n int) { | ||||||
| 	var l int | 	var l int | ||||||
| 	_ = l | 	_ = l | ||||||
|   | |||||||
							
								
								
									
										111
									
								
								generator.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								generator.go
									
									
									
									
									
										Normal 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)) | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Stephen J Day
					Stephen J Day