mirror of
				https://github.com/go-micro/go-micro.git
				synced 2025-10-30 23:27:41 +02:00 
			
		
		
		
	[feature] stream CloseSend (#2323)
* support stream CloseSend * move CloseSend into Closer
This commit is contained in:
		| @@ -64,6 +64,7 @@ type Response interface { | ||||
|  | ||||
| // Stream is the inteface for a bidirectional synchronous stream | ||||
| type Stream interface { | ||||
| 	Closer | ||||
| 	// Context for the stream | ||||
| 	Context() context.Context | ||||
| 	// The request made | ||||
| @@ -80,6 +81,12 @@ type Stream interface { | ||||
| 	Close() error | ||||
| } | ||||
|  | ||||
| // Closer handle client close | ||||
| type Closer interface { | ||||
| 	// CloseSend closes the send direction of the stream. | ||||
| 	CloseSend() error | ||||
| } | ||||
|  | ||||
| // Option used by the Client | ||||
| type Option func(*Options) | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
| 	"sync/atomic" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/google/uuid" | ||||
| 	"go-micro.dev/v4/broker" | ||||
| 	"go-micro.dev/v4/codec" | ||||
| 	raw "go-micro.dev/v4/codec/bytes" | ||||
| @@ -17,7 +18,6 @@ import ( | ||||
| 	"go-micro.dev/v4/util/buf" | ||||
| 	"go-micro.dev/v4/util/net" | ||||
| 	"go-micro.dev/v4/util/pool" | ||||
| 	"github.com/google/uuid" | ||||
| ) | ||||
|  | ||||
| type rpcClient struct { | ||||
| @@ -60,7 +60,7 @@ func (r *rpcClient) newCodec(contentType string) (codec.NewCodec, error) { | ||||
| 	if cf, ok := DefaultCodecs[contentType]; ok { | ||||
| 		return cf, nil | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) | ||||
| 	return nil, fmt.Errorf("unsupported Content-Type: %s", contentType) | ||||
| } | ||||
|  | ||||
| func (r *rpcClient) call(ctx context.Context, node *registry.Node, req Request, resp interface{}, opts CallOptions) error { | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package client | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"sync" | ||||
|  | ||||
| @@ -129,6 +130,10 @@ func (r *rpcStream) Error() error { | ||||
| 	return r.err | ||||
| } | ||||
|  | ||||
| func (r *rpcStream) CloseSend() error { | ||||
| 	return errors.New("streamer not implemented") | ||||
| } | ||||
|  | ||||
| func (r *rpcStream) Close() error { | ||||
| 	r.Lock() | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,7 @@ module github.com/asim/go-micro/cmd/protoc-gen-micro/v4 | ||||
| go 1.16 | ||||
|  | ||||
| require ( | ||||
| 	go-micro.dev/v4 v4.1.0 | ||||
| 	google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8 | ||||
| 	go-micro.dev/v4 v4.2.1 | ||||
| 	google.golang.org/genproto v0.0.0-20211021150943-2b146023228c | ||||
| 	google.golang.org/protobuf v1.27.1 | ||||
| ) | ||||
|   | ||||
| @@ -301,11 +301,9 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv | ||||
| github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= | ||||
| github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= | ||||
| github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||||
| github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= | ||||
| github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= | ||||
| github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||||
| github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||||
| github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||||
| github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | ||||
| github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA= | ||||
| github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w= | ||||
| @@ -490,9 +488,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ | ||||
| github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= | ||||
| github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
| github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
| github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= | ||||
| go-micro.dev/v4 v4.1.0 h1:XXZWlKhSpkQZTvPKcXRP5JvJoqbVhV+p/UUIfdVgN7E= | ||||
| go-micro.dev/v4 v4.1.0/go.mod h1:XTEJj5ILOBW+2ndGDG56r8fBXZ8hmsVaIaS1K5zwj+s= | ||||
| go-micro.dev/v4 v4.2.1 h1:1E+zymteWxvDLpo4EDixRmXC+ELOAyFGfOdO60ScVbU= | ||||
| go-micro.dev/v4 v4.2.1/go.mod h1:XTEJj5ILOBW+2ndGDG56r8fBXZ8hmsVaIaS1K5zwj+s= | ||||
| go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= | ||||
| go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | ||||
| go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | ||||
| @@ -546,7 +543,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl | ||||
| golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= | ||||
| golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||||
| golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||||
| golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= | ||||
| golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= | ||||
| golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= | ||||
| golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= | ||||
| @@ -555,7 +551,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB | ||||
| golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||||
| golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
| @@ -724,7 +719,6 @@ golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapK | ||||
| golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= | ||||
| golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||||
| golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||||
| golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= | ||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| @@ -766,8 +760,8 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG | ||||
| google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= | ||||
| google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8 h1:XosVttQUxX8erNhEruTu053/VchgYuksoS9Bj/OITjU= | ||||
| google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= | ||||
| google.golang.org/genproto v0.0.0-20211021150943-2b146023228c h1:FqrtZMB5Wr+/RecOM3uPJNPfWR8Upb5hAPnt7PU6i4k= | ||||
| google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= | ||||
| google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= | ||||
| google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||||
| google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | ||||
| @@ -800,7 +794,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 | ||||
| gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | ||||
| gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= | ||||
| gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | ||||
| gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | ||||
|   | ||||
| @@ -363,6 +363,8 @@ func (g *micro) generateClientMethod(reqServ, servName, serviceDescVar string, m | ||||
|  | ||||
| 	if !method.GetClientStreaming() { | ||||
| 		g.P("if err := stream.Send(in); err != nil { return nil, err }") | ||||
| 		// TODO: currently only grpc support CloseSend | ||||
| 		// g.P("if err := stream.CloseSend(); err != nil { return nil, err }") | ||||
| 	} | ||||
|  | ||||
| 	g.P("return &", streamType, "{stream}, nil") | ||||
| @@ -377,6 +379,7 @@ func (g *micro) generateClientMethod(reqServ, servName, serviceDescVar string, m | ||||
| 	g.P("Context() context.Context") | ||||
| 	g.P("SendMsg(interface{}) error") | ||||
| 	g.P("RecvMsg(interface{}) error") | ||||
| 	g.P("CloseSend() error") | ||||
| 	g.P("Close() error") | ||||
|  | ||||
| 	if genSend { | ||||
| @@ -393,6 +396,11 @@ func (g *micro) generateClientMethod(reqServ, servName, serviceDescVar string, m | ||||
| 	g.P("}") | ||||
| 	g.P() | ||||
|  | ||||
| 	g.P("func (x *", streamType, ") CloseSend() error {") | ||||
| 	g.P("return x.stream.CloseSend()") | ||||
| 	g.P("}") | ||||
| 	g.P() | ||||
|  | ||||
| 	g.P("func (x *", streamType, ") Close() error {") | ||||
| 	g.P("return x.stream.Close()") | ||||
| 	g.P("}") | ||||
|   | ||||
| @@ -4,25 +4,35 @@ go 1.16 | ||||
|  | ||||
| replace ( | ||||
| 	github.com/asim/go-micro/plugins/client/grpc/v4 => ../plugins/client/grpc | ||||
| 	github.com/asim/go-micro/plugins/client/http/v4 => ../plugins/client/http | ||||
| 	github.com/asim/go-micro/plugins/config/encoder/toml/v4 => ../plugins/config/encoder/toml | ||||
| 	github.com/asim/go-micro/plugins/config/encoder/yaml/v4 => ../plugins/config/encoder/yaml | ||||
| 	github.com/asim/go-micro/plugins/config/source/grpc/v4 => ../plugins/config/source/grpc | ||||
| 	github.com/asim/go-micro/plugins/server/grpc/v4 => ../plugins/server/grpc | ||||
| 	github.com/asim/go-micro/plugins/server/http/v4 => ../plugins/server/http | ||||
| 	github.com/asim/go-micro/plugins/transport/grpc/v4 => ../plugins/transport/grpc | ||||
| 	github.com/asim/go-micro/plugins/wrapper/select/roundrobin/v4 => ../plugins/wrapper/select/roundrobin | ||||
| 	github.com/asim/go-micro/plugins/wrapper/select/shard/v4 => ../plugins/wrapper/select/shard | ||||
| 	go-micro.dev/v4 => ../../go-micro | ||||
| ) | ||||
|  | ||||
| require ( | ||||
| 	github.com/asim/go-micro/plugins/client/http/v4 v4.0.0-20211022143028-f96b48dad9f9 | ||||
| 	github.com/asim/go-micro/plugins/config/encoder/toml/v4 v4.0.0-20211022143028-f96b48dad9f9 | ||||
| 	github.com/asim/go-micro/plugins/config/encoder/yaml/v4 v4.0.0-20211022143028-f96b48dad9f9 | ||||
| 	github.com/asim/go-micro/plugins/config/source/grpc/v4 v4.0.0-20211022143028-f96b48dad9f9 | ||||
| 	github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20211022143028-f96b48dad9f9 | ||||
| 	github.com/asim/go-micro/plugins/wrapper/select/roundrobin/v4 v4.0.0-20211022143028-f96b48dad9f9 | ||||
| 	github.com/asim/go-micro/plugins/wrapper/select/shard/v4 v4.0.0-20211022143028-f96b48dad9f9 | ||||
| 	github.com/asim/go-micro/plugins/client/grpc/v4 v4.0.0-20211019191242-9edc569e68bb | ||||
| 	github.com/asim/go-micro/plugins/client/http/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/asim/go-micro/plugins/config/encoder/toml/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/asim/go-micro/plugins/config/encoder/yaml/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/asim/go-micro/plugins/config/source/grpc/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/asim/go-micro/plugins/server/grpc/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/asim/go-micro/plugins/wrapper/select/roundrobin/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/asim/go-micro/plugins/wrapper/select/shard/v4 v4.0.0-00010101000000-000000000000 | ||||
| 	github.com/gin-gonic/gin v1.7.4 | ||||
| 	github.com/golang/glog v1.0.0 | ||||
| 	github.com/golang/protobuf v1.5.2 | ||||
| 	github.com/grpc-ecosystem/grpc-gateway v1.16.0 | ||||
| 	github.com/pborman/uuid v1.2.1 | ||||
| 	github.com/urfave/cli/v2 v2.3.0 | ||||
| 	go-micro.dev/v4 v4.1.0 | ||||
| 	go-micro.dev/v4 v4.2.1 | ||||
| 	golang.org/x/net v0.0.0-20211020060615-d418f374d309 | ||||
| 	google.golang.org/genproto v0.0.0-20211021150943-2b146023228c | ||||
| 	google.golang.org/grpc v1.41.0 | ||||
|   | ||||
| @@ -70,22 +70,6 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV | ||||
| github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= | ||||
| github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= | ||||
| github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= | ||||
| github.com/asim/go-micro/plugins/client/http/v4 v4.0.0-20211022143028-f96b48dad9f9 h1:17x43QitBDfbMjtFcpI2ecAc5PpEDdhNjtiotjqYKq8= | ||||
| github.com/asim/go-micro/plugins/client/http/v4 v4.0.0-20211022143028-f96b48dad9f9/go.mod h1:eCRnBm4m255UbIZw2tabc+wVZQ3ZRP8MWkRbn0MhMbE= | ||||
| github.com/asim/go-micro/plugins/config/encoder/toml/v4 v4.0.0-20211022143028-f96b48dad9f9 h1:OCoe8T41NrRb8gL/2Q3norzCFVubygzzkoeF46YU+XI= | ||||
| github.com/asim/go-micro/plugins/config/encoder/toml/v4 v4.0.0-20211022143028-f96b48dad9f9/go.mod h1:Hi2yzGSStKJbJo+9+EpXMwUi8KPd4hLgX4mOrz8c0oA= | ||||
| github.com/asim/go-micro/plugins/config/encoder/yaml/v4 v4.0.0-20211022143028-f96b48dad9f9 h1:n8EoXmlUJp0IkdUiPUysNM6bJ0QFWdM18oY6EOTy5PY= | ||||
| github.com/asim/go-micro/plugins/config/encoder/yaml/v4 v4.0.0-20211022143028-f96b48dad9f9/go.mod h1:DJsLvPsBo+CNTCPLejskeLjRupUWFF+ypQAEkUhw4iI= | ||||
| github.com/asim/go-micro/plugins/config/source/grpc/v4 v4.0.0-20211022143028-f96b48dad9f9 h1:mIgRuPdmQJbQKY7wkRRPyzKbcSEwkO1x8C9T9EOp1Bo= | ||||
| github.com/asim/go-micro/plugins/config/source/grpc/v4 v4.0.0-20211022143028-f96b48dad9f9/go.mod h1:8WKLbh9L7FP4RViRq3S1CZ7nv0mdapt1Al9w91j0Cjk= | ||||
| github.com/asim/go-micro/plugins/registry/memory/v4 v4.0.0-20211013123123-62801c3d6883 h1:Kt/XROVWpqglcjjiEq26KSwDYhSLsGL6NAEaukteuvc= | ||||
| github.com/asim/go-micro/plugins/registry/memory/v4 v4.0.0-20211013123123-62801c3d6883/go.mod h1:cSvG1suZrBwXQZm1H+v4ZHSrDxmGqJO4RV5O1gpmllM= | ||||
| github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20211022143028-f96b48dad9f9 h1:SW0nzvYDIyBFMp3ssny7+rtBcbNPQfpMYTXegnJ1Wt0= | ||||
| github.com/asim/go-micro/plugins/server/http/v4 v4.0.0-20211022143028-f96b48dad9f9/go.mod h1:IJBO19ayd3T0SO72e7kcW2zN3RxaeI1zYEtWvQfc67M= | ||||
| github.com/asim/go-micro/plugins/wrapper/select/roundrobin/v4 v4.0.0-20211022143028-f96b48dad9f9 h1:RBORITx0x74gDZTk+tohG+nbDFIhgcyPmLUqflWSxGA= | ||||
| github.com/asim/go-micro/plugins/wrapper/select/roundrobin/v4 v4.0.0-20211022143028-f96b48dad9f9/go.mod h1:g3/YAex/PPKlfludcWp/NLqHbTUUQY5HGjCgsKGgOok= | ||||
| github.com/asim/go-micro/plugins/wrapper/select/shard/v4 v4.0.0-20211022143028-f96b48dad9f9 h1:53epXCMQs/5BEHxoV4C0HxQhEcMB+eoiiU5ic0uosHQ= | ||||
| github.com/asim/go-micro/plugins/wrapper/select/shard/v4 v4.0.0-20211022143028-f96b48dad9f9/go.mod h1:V0bMYEIWuaB+TdpgrsYiLUg708JwSeX8whK65tT0J6g= | ||||
| github.com/aws/aws-sdk-go v1.37.27/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= | ||||
| 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= | ||||
| @@ -842,6 +826,8 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfG | ||||
| google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= | ||||
| google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= | ||||
| google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= | ||||
| google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= | ||||
| google.golang.org/genproto v0.0.0-20211021150943-2b146023228c h1:FqrtZMB5Wr+/RecOM3uPJNPfWR8Upb5hAPnt7PU6i4k= | ||||
| google.golang.org/genproto v0.0.0-20211021150943-2b146023228c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= | ||||
| google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= | ||||
| @@ -861,6 +847,8 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ | ||||
| google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= | ||||
| google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= | ||||
| google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= | ||||
| google.golang.org/grpc/examples v0.0.0-20211020220737-f00baa6c3c84 h1:vTEaoYojw/smuQT/Fva/AX+2Bnla97/oRbY75XFhg40= | ||||
| google.golang.org/grpc/examples v0.0.0-20211020220737-f00baa6c3c84/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU= | ||||
| google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | ||||
| google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | ||||
| google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||||
| @@ -869,6 +857,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi | ||||
| google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
| google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= | ||||
| google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= | ||||
| google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | ||||
| google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | ||||
|   | ||||
							
								
								
									
										26
									
								
								examples/stream/grpc/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								examples/stream/grpc/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| # Description | ||||
|  | ||||
| This example is translate [go grpc example](https://grpc.io/docs/languages/go/basics/) into go-micro. | ||||
| You can also find the orignal codes in [github.com/grpc/grpc-go](https://github.com/grpc/grpc-go/tree/master/examples/route_guide). | ||||
|  | ||||
| # Run the sample code | ||||
|  | ||||
| ## Protobuf | ||||
|  | ||||
| ```shell | ||||
| protoc --go_out=proto --micro_out=proto proto/route_guide.proto | ||||
| ``` | ||||
|  | ||||
| ## Server | ||||
|  | ||||
| ```shell | ||||
| cd stream/gprc/server | ||||
| go run . | ||||
| ``` | ||||
|  | ||||
| ## Client | ||||
|  | ||||
| ```shell | ||||
| cd stream/client | ||||
| go run main.go | ||||
| ``` | ||||
							
								
								
									
										161
									
								
								examples/stream/grpc/client/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								examples/stream/grpc/client/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"math/rand" | ||||
| 	"time" | ||||
|  | ||||
| 	pb "github.com/asim/go-micro/examples/v4/stream/grpc/proto" | ||||
| 	"github.com/asim/go-micro/plugins/client/grpc/v4" | ||||
| 	"go-micro.dev/v4" | ||||
| 	"go-micro.dev/v4/logger" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	srv := micro.NewService( | ||||
| 		micro.Client(grpc.NewClient()), | ||||
| 		micro.Name("stream-client"), | ||||
| 	) | ||||
| 	srv.Init() | ||||
| 	client := pb.NewRouteGuideService("stream-server", srv.Client()) | ||||
|  | ||||
| 	for { | ||||
| 		// Looking for a valid feature | ||||
| 		printFeature(client, &pb.Point{Latitude: 409146138, Longitude: -746188906}) | ||||
| 		// Feature missing. | ||||
| 		printFeature(client, &pb.Point{Latitude: 0, Longitude: 0}) | ||||
| 		// Looking for features between 40, -75 and 42, -73. | ||||
| 		printFeatures(client, &pb.Rectangle{ | ||||
| 			Lo: &pb.Point{Latitude: 400000000, Longitude: -750000000}, | ||||
| 			Hi: &pb.Point{Latitude: 420000000, Longitude: -730000000}, | ||||
| 		}) | ||||
|  | ||||
| 		// RecordRoute | ||||
| 		runRecordRoute(client) | ||||
|  | ||||
| 		// RouteChat | ||||
| 		runRouteChat(client) | ||||
|  | ||||
| 		time.Sleep(time.Second) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // printFeature gets the feature for the given point. | ||||
| func printFeature(client pb.RouteGuideService, point *pb.Point) { | ||||
| 	logger.Info("Getting feature for point (%d, %d)", point.Latitude, point.Longitude) | ||||
| 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||||
| 	defer cancel() | ||||
| 	feature, err := client.GetFeature(ctx, point) | ||||
| 	if err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| 	logger.Info(feature) | ||||
| } | ||||
|  | ||||
| // printFeatures lists all the features within the given bounding Rectangle. | ||||
| func printFeatures(client pb.RouteGuideService, rect *pb.Rectangle) { | ||||
| 	logger.Infof("Looking for features within %v", rect) | ||||
| 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||||
| 	defer cancel() | ||||
| 	stream, err := client.ListFeatures(ctx, rect) | ||||
| 	if err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| 	// IMPORTANT: do not forgot to close stream | ||||
| 	defer stream.Close() | ||||
| 	for { | ||||
| 		feature, err := stream.Recv() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			logger.Fatal(err) | ||||
| 		} | ||||
| 		logger.Infof("Feature: name: %q, point:(%v, %v)", feature.GetName(), | ||||
| 			feature.GetLocation().GetLatitude(), feature.GetLocation().GetLongitude()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // runRecordRoute sends a sequence of points to server and expects to get a RouteSummary from server. | ||||
| func runRecordRoute(client pb.RouteGuideService) { | ||||
| 	// Create a random number of random points | ||||
| 	r := rand.New(rand.NewSource(time.Now().UnixNano())) | ||||
| 	pointCount := int(r.Int31n(100)) + 2 // Traverse at least two points | ||||
| 	var points []*pb.Point | ||||
| 	for i := 0; i < pointCount; i++ { | ||||
| 		points = append(points, randomPoint(r)) | ||||
| 	} | ||||
| 	logger.Infof("Traversing %d points.", len(points)) | ||||
| 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||||
| 	defer cancel() | ||||
| 	stream, err := client.RecordRoute(ctx) | ||||
| 	if err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| 	// IMPORTANT: do not forgot to close stream | ||||
| 	defer stream.Close() | ||||
| 	for _, point := range points { | ||||
| 		if err := stream.Send(point); err != nil { | ||||
| 			logger.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
| 	if err := stream.CloseSend(); err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| 	summary := pb.RouteSummary{} | ||||
| 	if err := stream.RecvMsg(&summary); err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| 	logger.Infof("Route summary: %v", &summary) | ||||
| } | ||||
|  | ||||
| // runRouteChat receives a sequence of route notes, while sending notes for various locations. | ||||
| func runRouteChat(client pb.RouteGuideService) { | ||||
| 	notes := []*pb.RouteNote{ | ||||
| 		{Location: &pb.Point{Latitude: 0, Longitude: 1}, Message: "First message"}, | ||||
| 		{Location: &pb.Point{Latitude: 0, Longitude: 2}, Message: "Second message"}, | ||||
| 		{Location: &pb.Point{Latitude: 0, Longitude: 3}, Message: "Third message"}, | ||||
| 		{Location: &pb.Point{Latitude: 0, Longitude: 1}, Message: "Fourth message"}, | ||||
| 		{Location: &pb.Point{Latitude: 0, Longitude: 2}, Message: "Fifth message"}, | ||||
| 		{Location: &pb.Point{Latitude: 0, Longitude: 3}, Message: "Sixth message"}, | ||||
| 	} | ||||
| 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) | ||||
| 	defer cancel() | ||||
| 	stream, err := client.RouteChat(ctx) | ||||
| 	if err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| 	// IMPORTANT: do not forgot to close stream | ||||
| 	defer stream.Close() | ||||
| 	waitc := make(chan struct{}) | ||||
| 	go func() { | ||||
| 		for { | ||||
| 			in, err := stream.Recv() | ||||
| 			if err == io.EOF { | ||||
| 				// read done. | ||||
| 				close(waitc) | ||||
| 				break | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				logger.Fatal(err) | ||||
| 			} | ||||
| 			logger.Infof("Got message %s at point(%d, %d)", in.Message, in.Location.Latitude, in.Location.Longitude) | ||||
| 		} | ||||
| 	}() | ||||
| 	for _, note := range notes { | ||||
| 		if err := stream.Send(note); err != nil { | ||||
| 			logger.Fatal(err) | ||||
| 		} | ||||
| 	} | ||||
| 	if err := stream.CloseSend(); err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| 	<-waitc | ||||
| } | ||||
|  | ||||
| func randomPoint(r *rand.Rand) *pb.Point { | ||||
| 	lat := (r.Int31n(180) - 90) * 1e7 | ||||
| 	long := (r.Int31n(360) - 180) * 1e7 | ||||
| 	return &pb.Point{Latitude: lat, Longitude: long} | ||||
| } | ||||
							
								
								
									
										514
									
								
								examples/stream/grpc/proto/route_guide.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										514
									
								
								examples/stream/grpc/proto/route_guide.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,514 @@ | ||||
| // Code generated by protoc-gen-go. DO NOT EDIT. | ||||
| // versions: | ||||
| // 	protoc-gen-go v1.27.1 | ||||
| // 	protoc        v3.15.6 | ||||
| // source: proto/route_guide.proto | ||||
|  | ||||
| package proto | ||||
|  | ||||
| import ( | ||||
| 	protoreflect "google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	protoimpl "google.golang.org/protobuf/runtime/protoimpl" | ||||
| 	reflect "reflect" | ||||
| 	sync "sync" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// Verify that this generated code is sufficiently up-to-date. | ||||
| 	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) | ||||
| 	// Verify that runtime/protoimpl is sufficiently up-to-date. | ||||
| 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) | ||||
| ) | ||||
|  | ||||
| // Points are represented as latitude-longitude pairs in the E7 representation | ||||
| // (degrees multiplied by 10**7 and rounded to the nearest integer). | ||||
| // Latitudes should be in the range +/- 90 degrees and longitude should be in | ||||
| // the range +/- 180 degrees (inclusive). | ||||
| type Point struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Latitude  int32 `protobuf:"varint,1,opt,name=latitude,proto3" json:"latitude,omitempty"` | ||||
| 	Longitude int32 `protobuf:"varint,2,opt,name=longitude,proto3" json:"longitude,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Point) Reset() { | ||||
| 	*x = Point{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_proto_route_guide_proto_msgTypes[0] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *Point) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*Point) ProtoMessage() {} | ||||
|  | ||||
| func (x *Point) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_proto_route_guide_proto_msgTypes[0] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use Point.ProtoReflect.Descriptor instead. | ||||
| func (*Point) Descriptor() ([]byte, []int) { | ||||
| 	return file_proto_route_guide_proto_rawDescGZIP(), []int{0} | ||||
| } | ||||
|  | ||||
| func (x *Point) GetLatitude() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.Latitude | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *Point) GetLongitude() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.Longitude | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| // A latitude-longitude rectangle, represented as two diagonally opposite | ||||
| // points "lo" and "hi". | ||||
| type Rectangle struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	// One corner of the rectangle. | ||||
| 	Lo *Point `protobuf:"bytes,1,opt,name=lo,proto3" json:"lo,omitempty"` | ||||
| 	// The other corner of the rectangle. | ||||
| 	Hi *Point `protobuf:"bytes,2,opt,name=hi,proto3" json:"hi,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Rectangle) Reset() { | ||||
| 	*x = Rectangle{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_proto_route_guide_proto_msgTypes[1] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *Rectangle) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*Rectangle) ProtoMessage() {} | ||||
|  | ||||
| func (x *Rectangle) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_proto_route_guide_proto_msgTypes[1] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use Rectangle.ProtoReflect.Descriptor instead. | ||||
| func (*Rectangle) Descriptor() ([]byte, []int) { | ||||
| 	return file_proto_route_guide_proto_rawDescGZIP(), []int{1} | ||||
| } | ||||
|  | ||||
| func (x *Rectangle) GetLo() *Point { | ||||
| 	if x != nil { | ||||
| 		return x.Lo | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (x *Rectangle) GetHi() *Point { | ||||
| 	if x != nil { | ||||
| 		return x.Hi | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // A feature names something at a given point. | ||||
| // | ||||
| // If a feature could not be named, the name is empty. | ||||
| type Feature struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	// The name of the feature. | ||||
| 	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` | ||||
| 	// The point where the feature is detected. | ||||
| 	Location *Point `protobuf:"bytes,2,opt,name=location,proto3" json:"location,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Feature) Reset() { | ||||
| 	*x = Feature{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_proto_route_guide_proto_msgTypes[2] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *Feature) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*Feature) ProtoMessage() {} | ||||
|  | ||||
| func (x *Feature) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_proto_route_guide_proto_msgTypes[2] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use Feature.ProtoReflect.Descriptor instead. | ||||
| func (*Feature) Descriptor() ([]byte, []int) { | ||||
| 	return file_proto_route_guide_proto_rawDescGZIP(), []int{2} | ||||
| } | ||||
|  | ||||
| func (x *Feature) GetName() string { | ||||
| 	if x != nil { | ||||
| 		return x.Name | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (x *Feature) GetLocation() *Point { | ||||
| 	if x != nil { | ||||
| 		return x.Location | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // A RouteNote is a message sent while at a given point. | ||||
| type RouteNote struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	// The location from which the message is sent. | ||||
| 	Location *Point `protobuf:"bytes,1,opt,name=location,proto3" json:"location,omitempty"` | ||||
| 	// The message to be sent. | ||||
| 	Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *RouteNote) Reset() { | ||||
| 	*x = RouteNote{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_proto_route_guide_proto_msgTypes[3] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *RouteNote) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*RouteNote) ProtoMessage() {} | ||||
|  | ||||
| func (x *RouteNote) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_proto_route_guide_proto_msgTypes[3] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use RouteNote.ProtoReflect.Descriptor instead. | ||||
| func (*RouteNote) Descriptor() ([]byte, []int) { | ||||
| 	return file_proto_route_guide_proto_rawDescGZIP(), []int{3} | ||||
| } | ||||
|  | ||||
| func (x *RouteNote) GetLocation() *Point { | ||||
| 	if x != nil { | ||||
| 		return x.Location | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (x *RouteNote) GetMessage() string { | ||||
| 	if x != nil { | ||||
| 		return x.Message | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| // A RouteSummary is received in response to a RecordRoute rpc. | ||||
| // | ||||
| // It contains the number of individual points received, the number of | ||||
| // detected features, and the total distance covered as the cumulative sum of | ||||
| // the distance between each point. | ||||
| type RouteSummary struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	// The number of points received. | ||||
| 	PointCount int32 `protobuf:"varint,1,opt,name=point_count,json=pointCount,proto3" json:"point_count,omitempty"` | ||||
| 	// The number of known features passed while traversing the route. | ||||
| 	FeatureCount int32 `protobuf:"varint,2,opt,name=feature_count,json=featureCount,proto3" json:"feature_count,omitempty"` | ||||
| 	// The distance covered in metres. | ||||
| 	Distance int32 `protobuf:"varint,3,opt,name=distance,proto3" json:"distance,omitempty"` | ||||
| 	// The duration of the traversal in seconds. | ||||
| 	ElapsedTime int32 `protobuf:"varint,4,opt,name=elapsed_time,json=elapsedTime,proto3" json:"elapsed_time,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *RouteSummary) Reset() { | ||||
| 	*x = RouteSummary{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_proto_route_guide_proto_msgTypes[4] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *RouteSummary) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*RouteSummary) ProtoMessage() {} | ||||
|  | ||||
| func (x *RouteSummary) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_proto_route_guide_proto_msgTypes[4] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use RouteSummary.ProtoReflect.Descriptor instead. | ||||
| func (*RouteSummary) Descriptor() ([]byte, []int) { | ||||
| 	return file_proto_route_guide_proto_rawDescGZIP(), []int{4} | ||||
| } | ||||
|  | ||||
| func (x *RouteSummary) GetPointCount() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.PointCount | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *RouteSummary) GetFeatureCount() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.FeatureCount | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *RouteSummary) GetDistance() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.Distance | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (x *RouteSummary) GetElapsedTime() int32 { | ||||
| 	if x != nil { | ||||
| 		return x.ElapsedTime | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| var File_proto_route_guide_proto protoreflect.FileDescriptor | ||||
|  | ||||
| var file_proto_route_guide_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x17, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x67, 0x75, | ||||
| 	0x69, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, | ||||
| 	0x22, 0x41, 0x0a, 0x05, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, | ||||
| 	0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6c, 0x61, 0x74, | ||||
| 	0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, | ||||
| 	0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, | ||||
| 	0x75, 0x64, 0x65, 0x22, 0x47, 0x0a, 0x09, 0x52, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x6c, 0x65, | ||||
| 	0x12, 0x1c, 0x0a, 0x02, 0x6c, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, | ||||
| 	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x02, 0x6c, 0x6f, 0x12, 0x1c, | ||||
| 	0x0a, 0x02, 0x68, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, | ||||
| 	0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x02, 0x68, 0x69, 0x22, 0x47, 0x0a, 0x07, | ||||
| 	0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, | ||||
| 	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x6c, | ||||
| 	0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, | ||||
| 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, | ||||
| 	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x4f, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x4e, 0x6f, | ||||
| 	0x74, 0x65, 0x12, 0x28, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, | ||||
| 	0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x69, | ||||
| 	0x6e, 0x74, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, | ||||
| 	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, | ||||
| 	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x0c, 0x52, 0x6f, 0x75, 0x74, 0x65, | ||||
| 	0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6f, 0x69, 0x6e, 0x74, | ||||
| 	0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x6f, | ||||
| 	0x69, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x66, 0x65, 0x61, 0x74, | ||||
| 	0x75, 0x72, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, | ||||
| 	0x0c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, | ||||
| 	0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, | ||||
| 	0x08, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6c, 0x61, | ||||
| 	0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, | ||||
| 	0x0b, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x32, 0xdd, 0x01, 0x0a, | ||||
| 	0x0a, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x47, 0x75, 0x69, 0x64, 0x65, 0x12, 0x2c, 0x0a, 0x0a, 0x47, | ||||
| 	0x65, 0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x0c, 0x2e, 0x70, 0x72, 0x6f, 0x74, | ||||
| 	0x6f, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x1a, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, | ||||
| 	0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x0c, 0x4c, 0x69, 0x73, | ||||
| 	0x74, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, | ||||
| 	0x6f, 0x2e, 0x52, 0x65, 0x63, 0x74, 0x61, 0x6e, 0x67, 0x6c, 0x65, 0x1a, 0x0e, 0x2e, 0x70, 0x72, | ||||
| 	0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, | ||||
| 	0x34, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x0c, | ||||
| 	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x1a, 0x13, 0x2e, 0x70, | ||||
| 	0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, | ||||
| 	0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x35, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x43, 0x68, | ||||
| 	0x61, 0x74, 0x12, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, | ||||
| 	0x4e, 0x6f, 0x74, 0x65, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x6f, 0x75, | ||||
| 	0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x0a, 0x5a, 0x08, | ||||
| 	0x2e, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	file_proto_route_guide_proto_rawDescOnce sync.Once | ||||
| 	file_proto_route_guide_proto_rawDescData = file_proto_route_guide_proto_rawDesc | ||||
| ) | ||||
|  | ||||
| func file_proto_route_guide_proto_rawDescGZIP() []byte { | ||||
| 	file_proto_route_guide_proto_rawDescOnce.Do(func() { | ||||
| 		file_proto_route_guide_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_route_guide_proto_rawDescData) | ||||
| 	}) | ||||
| 	return file_proto_route_guide_proto_rawDescData | ||||
| } | ||||
|  | ||||
| var file_proto_route_guide_proto_msgTypes = make([]protoimpl.MessageInfo, 5) | ||||
| var file_proto_route_guide_proto_goTypes = []interface{}{ | ||||
| 	(*Point)(nil),        // 0: proto.Point | ||||
| 	(*Rectangle)(nil),    // 1: proto.Rectangle | ||||
| 	(*Feature)(nil),      // 2: proto.Feature | ||||
| 	(*RouteNote)(nil),    // 3: proto.RouteNote | ||||
| 	(*RouteSummary)(nil), // 4: proto.RouteSummary | ||||
| } | ||||
| var file_proto_route_guide_proto_depIdxs = []int32{ | ||||
| 	0, // 0: proto.Rectangle.lo:type_name -> proto.Point | ||||
| 	0, // 1: proto.Rectangle.hi:type_name -> proto.Point | ||||
| 	0, // 2: proto.Feature.location:type_name -> proto.Point | ||||
| 	0, // 3: proto.RouteNote.location:type_name -> proto.Point | ||||
| 	0, // 4: proto.RouteGuide.GetFeature:input_type -> proto.Point | ||||
| 	1, // 5: proto.RouteGuide.ListFeatures:input_type -> proto.Rectangle | ||||
| 	0, // 6: proto.RouteGuide.RecordRoute:input_type -> proto.Point | ||||
| 	3, // 7: proto.RouteGuide.RouteChat:input_type -> proto.RouteNote | ||||
| 	2, // 8: proto.RouteGuide.GetFeature:output_type -> proto.Feature | ||||
| 	2, // 9: proto.RouteGuide.ListFeatures:output_type -> proto.Feature | ||||
| 	4, // 10: proto.RouteGuide.RecordRoute:output_type -> proto.RouteSummary | ||||
| 	3, // 11: proto.RouteGuide.RouteChat:output_type -> proto.RouteNote | ||||
| 	8, // [8:12] is the sub-list for method output_type | ||||
| 	4, // [4:8] is the sub-list for method input_type | ||||
| 	4, // [4:4] is the sub-list for extension type_name | ||||
| 	4, // [4:4] is the sub-list for extension extendee | ||||
| 	0, // [0:4] is the sub-list for field type_name | ||||
| } | ||||
|  | ||||
| func init() { file_proto_route_guide_proto_init() } | ||||
| func file_proto_route_guide_proto_init() { | ||||
| 	if File_proto_route_guide_proto != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if !protoimpl.UnsafeEnabled { | ||||
| 		file_proto_route_guide_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*Point); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_proto_route_guide_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*Rectangle); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_proto_route_guide_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*Feature); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_proto_route_guide_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*RouteNote); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_proto_route_guide_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*RouteSummary); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	type x struct{} | ||||
| 	out := protoimpl.TypeBuilder{ | ||||
| 		File: protoimpl.DescBuilder{ | ||||
| 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||||
| 			RawDescriptor: file_proto_route_guide_proto_rawDesc, | ||||
| 			NumEnums:      0, | ||||
| 			NumMessages:   5, | ||||
| 			NumExtensions: 0, | ||||
| 			NumServices:   1, | ||||
| 		}, | ||||
| 		GoTypes:           file_proto_route_guide_proto_goTypes, | ||||
| 		DependencyIndexes: file_proto_route_guide_proto_depIdxs, | ||||
| 		MessageInfos:      file_proto_route_guide_proto_msgTypes, | ||||
| 	}.Build() | ||||
| 	File_proto_route_guide_proto = out.File | ||||
| 	file_proto_route_guide_proto_rawDesc = nil | ||||
| 	file_proto_route_guide_proto_goTypes = nil | ||||
| 	file_proto_route_guide_proto_depIdxs = nil | ||||
| } | ||||
							
								
								
									
										420
									
								
								examples/stream/grpc/proto/route_guide.pb.micro.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								examples/stream/grpc/proto/route_guide.pb.micro.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,420 @@ | ||||
| // Code generated by protoc-gen-micro. DO NOT EDIT. | ||||
| // source: proto/route_guide.proto | ||||
|  | ||||
| package proto | ||||
|  | ||||
| import ( | ||||
| 	fmt "fmt" | ||||
| 	proto "google.golang.org/protobuf/proto" | ||||
| 	math "math" | ||||
| ) | ||||
|  | ||||
| import ( | ||||
| 	context "context" | ||||
| 	api "go-micro.dev/v4/api" | ||||
| 	client "go-micro.dev/v4/client" | ||||
| 	server "go-micro.dev/v4/server" | ||||
| ) | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ api.Endpoint | ||||
| var _ context.Context | ||||
| var _ client.Option | ||||
| var _ server.Option | ||||
|  | ||||
| // Api Endpoints for RouteGuide service | ||||
|  | ||||
| func NewRouteGuideEndpoints() []*api.Endpoint { | ||||
| 	return []*api.Endpoint{} | ||||
| } | ||||
|  | ||||
| // Client API for RouteGuide service | ||||
|  | ||||
| type RouteGuideService interface { | ||||
| 	// A simple RPC. | ||||
| 	// | ||||
| 	// Obtains the feature at a given position. | ||||
| 	// | ||||
| 	// A feature with an empty name is returned if there's no feature at the given | ||||
| 	// position. | ||||
| 	GetFeature(ctx context.Context, in *Point, opts ...client.CallOption) (*Feature, error) | ||||
| 	// A server-to-client streaming RPC. | ||||
| 	// | ||||
| 	// Obtains the Features available within the given Rectangle.  Results are | ||||
| 	// streamed rather than returned at once (e.g. in a response message with a | ||||
| 	// repeated field), as the rectangle may cover a large area and contain a | ||||
| 	// huge number of features. | ||||
| 	ListFeatures(ctx context.Context, in *Rectangle, opts ...client.CallOption) (RouteGuide_ListFeaturesService, error) | ||||
| 	// A client-to-server streaming RPC. | ||||
| 	// | ||||
| 	// Accepts a stream of Points on a route being traversed, returning a | ||||
| 	// RouteSummary when traversal is completed. | ||||
| 	RecordRoute(ctx context.Context, opts ...client.CallOption) (RouteGuide_RecordRouteService, error) | ||||
| 	// A Bidirectional streaming RPC. | ||||
| 	// | ||||
| 	// Accepts a stream of RouteNotes sent while a route is being traversed, | ||||
| 	// while receiving other RouteNotes (e.g. from other users). | ||||
| 	RouteChat(ctx context.Context, opts ...client.CallOption) (RouteGuide_RouteChatService, error) | ||||
| } | ||||
|  | ||||
| type routeGuideService struct { | ||||
| 	c    client.Client | ||||
| 	name string | ||||
| } | ||||
|  | ||||
| func NewRouteGuideService(name string, c client.Client) RouteGuideService { | ||||
| 	return &routeGuideService{ | ||||
| 		c:    c, | ||||
| 		name: name, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (c *routeGuideService) GetFeature(ctx context.Context, in *Point, opts ...client.CallOption) (*Feature, error) { | ||||
| 	req := c.c.NewRequest(c.name, "RouteGuide.GetFeature", in) | ||||
| 	out := new(Feature) | ||||
| 	err := c.c.Call(ctx, req, out, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| func (c *routeGuideService) ListFeatures(ctx context.Context, in *Rectangle, opts ...client.CallOption) (RouteGuide_ListFeaturesService, error) { | ||||
| 	req := c.c.NewRequest(c.name, "RouteGuide.ListFeatures", &Rectangle{}) | ||||
| 	stream, err := c.c.Stream(ctx, req, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := stream.Send(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := stream.CloseSend(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &routeGuideServiceListFeatures{stream}, nil | ||||
| } | ||||
|  | ||||
| type RouteGuide_ListFeaturesService interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	CloseSend() error | ||||
| 	Close() error | ||||
| 	Recv() (*Feature, error) | ||||
| } | ||||
|  | ||||
| type routeGuideServiceListFeatures struct { | ||||
| 	stream client.Stream | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceListFeatures) CloseSend() error { | ||||
| 	return x.stream.CloseSend() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceListFeatures) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceListFeatures) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceListFeatures) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceListFeatures) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceListFeatures) Recv() (*Feature, error) { | ||||
| 	m := new(Feature) | ||||
| 	err := x.stream.Recv(m) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func (c *routeGuideService) RecordRoute(ctx context.Context, opts ...client.CallOption) (RouteGuide_RecordRouteService, error) { | ||||
| 	req := c.c.NewRequest(c.name, "RouteGuide.RecordRoute", &Point{}) | ||||
| 	stream, err := c.c.Stream(ctx, req, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &routeGuideServiceRecordRoute{stream}, nil | ||||
| } | ||||
|  | ||||
| type RouteGuide_RecordRouteService interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	CloseSend() error | ||||
| 	Close() error | ||||
| 	Send(*Point) error | ||||
| } | ||||
|  | ||||
| type routeGuideServiceRecordRoute struct { | ||||
| 	stream client.Stream | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRecordRoute) CloseSend() error { | ||||
| 	return x.stream.CloseSend() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRecordRoute) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRecordRoute) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRecordRoute) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRecordRoute) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRecordRoute) Send(m *Point) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (c *routeGuideService) RouteChat(ctx context.Context, opts ...client.CallOption) (RouteGuide_RouteChatService, error) { | ||||
| 	req := c.c.NewRequest(c.name, "RouteGuide.RouteChat", &RouteNote{}) | ||||
| 	stream, err := c.c.Stream(ctx, req, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &routeGuideServiceRouteChat{stream}, nil | ||||
| } | ||||
|  | ||||
| type RouteGuide_RouteChatService interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	CloseSend() error | ||||
| 	Close() error | ||||
| 	Send(*RouteNote) error | ||||
| 	Recv() (*RouteNote, error) | ||||
| } | ||||
|  | ||||
| type routeGuideServiceRouteChat struct { | ||||
| 	stream client.Stream | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRouteChat) CloseSend() error { | ||||
| 	return x.stream.CloseSend() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRouteChat) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRouteChat) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRouteChat) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRouteChat) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRouteChat) Send(m *RouteNote) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideServiceRouteChat) Recv() (*RouteNote, error) { | ||||
| 	m := new(RouteNote) | ||||
| 	err := x.stream.Recv(m) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| // Server API for RouteGuide service | ||||
|  | ||||
| type RouteGuideHandler interface { | ||||
| 	// A simple RPC. | ||||
| 	// | ||||
| 	// Obtains the feature at a given position. | ||||
| 	// | ||||
| 	// A feature with an empty name is returned if there's no feature at the given | ||||
| 	// position. | ||||
| 	GetFeature(context.Context, *Point, *Feature) error | ||||
| 	// A server-to-client streaming RPC. | ||||
| 	// | ||||
| 	// Obtains the Features available within the given Rectangle.  Results are | ||||
| 	// streamed rather than returned at once (e.g. in a response message with a | ||||
| 	// repeated field), as the rectangle may cover a large area and contain a | ||||
| 	// huge number of features. | ||||
| 	ListFeatures(context.Context, *Rectangle, RouteGuide_ListFeaturesStream) error | ||||
| 	// A client-to-server streaming RPC. | ||||
| 	// | ||||
| 	// Accepts a stream of Points on a route being traversed, returning a | ||||
| 	// RouteSummary when traversal is completed. | ||||
| 	RecordRoute(context.Context, RouteGuide_RecordRouteStream) error | ||||
| 	// A Bidirectional streaming RPC. | ||||
| 	// | ||||
| 	// Accepts a stream of RouteNotes sent while a route is being traversed, | ||||
| 	// while receiving other RouteNotes (e.g. from other users). | ||||
| 	RouteChat(context.Context, RouteGuide_RouteChatStream) error | ||||
| } | ||||
|  | ||||
| func RegisterRouteGuideHandler(s server.Server, hdlr RouteGuideHandler, opts ...server.HandlerOption) error { | ||||
| 	type routeGuide interface { | ||||
| 		GetFeature(ctx context.Context, in *Point, out *Feature) error | ||||
| 		ListFeatures(ctx context.Context, stream server.Stream) error | ||||
| 		RecordRoute(ctx context.Context, stream server.Stream) error | ||||
| 		RouteChat(ctx context.Context, stream server.Stream) error | ||||
| 	} | ||||
| 	type RouteGuide struct { | ||||
| 		routeGuide | ||||
| 	} | ||||
| 	h := &routeGuideHandler{hdlr} | ||||
| 	return s.Handle(s.NewHandler(&RouteGuide{h}, opts...)) | ||||
| } | ||||
|  | ||||
| type routeGuideHandler struct { | ||||
| 	RouteGuideHandler | ||||
| } | ||||
|  | ||||
| func (h *routeGuideHandler) GetFeature(ctx context.Context, in *Point, out *Feature) error { | ||||
| 	return h.RouteGuideHandler.GetFeature(ctx, in, out) | ||||
| } | ||||
|  | ||||
| func (h *routeGuideHandler) ListFeatures(ctx context.Context, stream server.Stream) error { | ||||
| 	m := new(Rectangle) | ||||
| 	if err := stream.Recv(m); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return h.RouteGuideHandler.ListFeatures(ctx, m, &routeGuideListFeaturesStream{stream}) | ||||
| } | ||||
|  | ||||
| type RouteGuide_ListFeaturesStream interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	Close() error | ||||
| 	Send(*Feature) error | ||||
| } | ||||
|  | ||||
| type routeGuideListFeaturesStream struct { | ||||
| 	stream server.Stream | ||||
| } | ||||
|  | ||||
| func (x *routeGuideListFeaturesStream) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideListFeaturesStream) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideListFeaturesStream) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideListFeaturesStream) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideListFeaturesStream) Send(m *Feature) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (h *routeGuideHandler) RecordRoute(ctx context.Context, stream server.Stream) error { | ||||
| 	return h.RouteGuideHandler.RecordRoute(ctx, &routeGuideRecordRouteStream{stream}) | ||||
| } | ||||
|  | ||||
| type RouteGuide_RecordRouteStream interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	Close() error | ||||
| 	Recv() (*Point, error) | ||||
| } | ||||
|  | ||||
| type routeGuideRecordRouteStream struct { | ||||
| 	stream server.Stream | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRecordRouteStream) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRecordRouteStream) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRecordRouteStream) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRecordRouteStream) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRecordRouteStream) Recv() (*Point, error) { | ||||
| 	m := new(Point) | ||||
| 	if err := x.stream.Recv(m); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func (h *routeGuideHandler) RouteChat(ctx context.Context, stream server.Stream) error { | ||||
| 	return h.RouteGuideHandler.RouteChat(ctx, &routeGuideRouteChatStream{stream}) | ||||
| } | ||||
|  | ||||
| type RouteGuide_RouteChatStream interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	Close() error | ||||
| 	Send(*RouteNote) error | ||||
| 	Recv() (*RouteNote, error) | ||||
| } | ||||
|  | ||||
| type routeGuideRouteChatStream struct { | ||||
| 	stream server.Stream | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRouteChatStream) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRouteChatStream) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRouteChatStream) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRouteChatStream) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRouteChatStream) Send(m *RouteNote) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
|  | ||||
| func (x *routeGuideRouteChatStream) Recv() (*RouteNote, error) { | ||||
| 	m := new(RouteNote) | ||||
| 	if err := x.stream.Recv(m); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
							
								
								
									
										94
									
								
								examples/stream/grpc/proto/route_guide.proto
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								examples/stream/grpc/proto/route_guide.proto
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| syntax = "proto3"; | ||||
|  | ||||
| option go_package = "../proto"; | ||||
|  | ||||
| package proto; | ||||
|  | ||||
| // Interface exported by the server. | ||||
| service RouteGuide { | ||||
|   // A simple RPC. | ||||
|   // | ||||
|   // Obtains the feature at a given position. | ||||
|   // | ||||
|   // A feature with an empty name is returned if there's no feature at the given | ||||
|   // position. | ||||
|   rpc GetFeature(Point) returns (Feature) {} | ||||
|  | ||||
|   // A server-to-client streaming RPC. | ||||
|   // | ||||
|   // Obtains the Features available within the given Rectangle.  Results are | ||||
|   // streamed rather than returned at once (e.g. in a response message with a | ||||
|   // repeated field), as the rectangle may cover a large area and contain a | ||||
|   // huge number of features. | ||||
|   rpc ListFeatures(Rectangle) returns (stream Feature) {} | ||||
|  | ||||
|   // A client-to-server streaming RPC. | ||||
|   // | ||||
|   // Accepts a stream of Points on a route being traversed, returning a | ||||
|   // RouteSummary when traversal is completed. | ||||
|   rpc RecordRoute(stream Point) returns (RouteSummary) {} | ||||
|  | ||||
|   // A Bidirectional streaming RPC. | ||||
|   // | ||||
|   // Accepts a stream of RouteNotes sent while a route is being traversed, | ||||
|   // while receiving other RouteNotes (e.g. from other users). | ||||
|   rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} | ||||
| } | ||||
|  | ||||
| // Points are represented as latitude-longitude pairs in the E7 representation | ||||
| // (degrees multiplied by 10**7 and rounded to the nearest integer). | ||||
| // Latitudes should be in the range +/- 90 degrees and longitude should be in | ||||
| // the range +/- 180 degrees (inclusive). | ||||
| message Point { | ||||
|   int32 latitude = 1; | ||||
|   int32 longitude = 2; | ||||
| } | ||||
|  | ||||
| // A latitude-longitude rectangle, represented as two diagonally opposite | ||||
| // points "lo" and "hi". | ||||
| message Rectangle { | ||||
|   // One corner of the rectangle. | ||||
|   Point lo = 1; | ||||
|  | ||||
|   // The other corner of the rectangle. | ||||
|   Point hi = 2; | ||||
| } | ||||
|  | ||||
| // A feature names something at a given point. | ||||
| // | ||||
| // If a feature could not be named, the name is empty. | ||||
| message Feature { | ||||
|   // The name of the feature. | ||||
|   string name = 1; | ||||
|  | ||||
|   // The point where the feature is detected. | ||||
|   Point location = 2; | ||||
| } | ||||
|  | ||||
| // A RouteNote is a message sent while at a given point. | ||||
| message RouteNote { | ||||
|   // The location from which the message is sent. | ||||
|   Point location = 1; | ||||
|  | ||||
|   // The message to be sent. | ||||
|   string message = 2; | ||||
| } | ||||
|  | ||||
| // A RouteSummary is received in response to a RecordRoute rpc. | ||||
| // | ||||
| // It contains the number of individual points received, the number of | ||||
| // detected features, and the total distance covered as the cumulative sum of | ||||
| // the distance between each point. | ||||
| message RouteSummary { | ||||
|   // The number of points received. | ||||
|   int32 point_count = 1; | ||||
|  | ||||
|   // The number of known features passed while traversing the route. | ||||
|   int32 feature_count = 2; | ||||
|  | ||||
|   // The distance covered in metres. | ||||
|   int32 distance = 3; | ||||
|  | ||||
|   // The duration of the traversal in seconds. | ||||
|   int32 elapsed_time = 4; | ||||
| } | ||||
							
								
								
									
										661
									
								
								examples/stream/grpc/server/data.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										661
									
								
								examples/stream/grpc/server/data.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,661 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"math" | ||||
|  | ||||
| 	pb "github.com/asim/go-micro/examples/v4/stream/grpc/proto" | ||||
| ) | ||||
|  | ||||
| var features []*pb.Feature | ||||
|  | ||||
| func init() { | ||||
| 	if err := json.Unmarshal(testingData, &features); err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func inRange(point *pb.Point, rect *pb.Rectangle) bool { | ||||
| 	left := math.Min(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) | ||||
| 	right := math.Max(float64(rect.Lo.Longitude), float64(rect.Hi.Longitude)) | ||||
| 	top := math.Max(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude)) | ||||
| 	bottom := math.Min(float64(rect.Lo.Latitude), float64(rect.Hi.Latitude)) | ||||
|  | ||||
| 	if float64(point.Longitude) >= left && | ||||
| 		float64(point.Longitude) <= right && | ||||
| 		float64(point.Latitude) >= bottom && | ||||
| 		float64(point.Latitude) <= top { | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| func calcDistance(p1 *pb.Point, p2 *pb.Point) int32 { | ||||
| 	const CordFactor float64 = 1e7 | ||||
| 	const R = float64(6371000) // earth radius in metres | ||||
| 	lat1 := toRadians(float64(p1.Latitude) / CordFactor) | ||||
| 	lat2 := toRadians(float64(p2.Latitude) / CordFactor) | ||||
| 	lng1 := toRadians(float64(p1.Longitude) / CordFactor) | ||||
| 	lng2 := toRadians(float64(p2.Longitude) / CordFactor) | ||||
| 	dlat := lat2 - lat1 | ||||
| 	dlng := lng2 - lng1 | ||||
|  | ||||
| 	a := math.Sin(dlat/2)*math.Sin(dlat/2) + | ||||
| 		math.Cos(lat1)*math.Cos(lat2)* | ||||
| 			math.Sin(dlng/2)*math.Sin(dlng/2) | ||||
| 	c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a)) | ||||
|  | ||||
| 	distance := R * c | ||||
| 	return int32(distance) | ||||
| } | ||||
|  | ||||
| func toRadians(num float64) float64 { | ||||
| 	return num * math.Pi / float64(180) | ||||
| } | ||||
|  | ||||
| func serialize(point *pb.Point) string { | ||||
| 	return fmt.Sprintf("%d %d", point.Latitude, point.Longitude) | ||||
| } | ||||
|  | ||||
| var testingData = []byte(`[{ | ||||
|     "location": { | ||||
|         "latitude": 407838351, | ||||
|         "longitude": -746143763 | ||||
|     }, | ||||
|     "name": "Patriots Path, Mendham, NJ 07945, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 408122808, | ||||
|         "longitude": -743999179 | ||||
|     }, | ||||
|     "name": "101 New Jersey 10, Whippany, NJ 07981, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 413628156, | ||||
|         "longitude": -749015468 | ||||
|     }, | ||||
|     "name": "U.S. 6, Shohola, PA 18458, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 419999544, | ||||
|         "longitude": -740371136 | ||||
|     }, | ||||
|     "name": "5 Conners Road, Kingston, NY 12401, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 414008389, | ||||
|         "longitude": -743951297 | ||||
|     }, | ||||
|     "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 419611318, | ||||
|         "longitude": -746524769 | ||||
|     }, | ||||
|     "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406109563, | ||||
|         "longitude": -742186778 | ||||
|     }, | ||||
|     "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 416802456, | ||||
|         "longitude": -742370183 | ||||
|     }, | ||||
|     "name": "352 South Mountain Road, Wallkill, NY 12589, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412950425, | ||||
|         "longitude": -741077389 | ||||
|     }, | ||||
|     "name": "Bailey Turn Road, Harriman, NY 10926, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412144655, | ||||
|         "longitude": -743949739 | ||||
|     }, | ||||
|     "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 415736605, | ||||
|         "longitude": -742847522 | ||||
|     }, | ||||
|     "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 413843930, | ||||
|         "longitude": -740501726 | ||||
|     }, | ||||
|     "name": "162 Merrill Road, Highland Mills, NY 10930, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 410873075, | ||||
|         "longitude": -744459023 | ||||
|     }, | ||||
|     "name": "Clinton Road, West Milford, NJ 07480, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412346009, | ||||
|         "longitude": -744026814 | ||||
|     }, | ||||
|     "name": "16 Old Brook Lane, Warwick, NY 10990, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 402948455, | ||||
|         "longitude": -747903913 | ||||
|     }, | ||||
|     "name": "3 Drake Lane, Pennington, NJ 08534, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406337092, | ||||
|         "longitude": -740122226 | ||||
|     }, | ||||
|     "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406421967, | ||||
|         "longitude": -747727624 | ||||
|     }, | ||||
|     "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 416318082, | ||||
|         "longitude": -749677716 | ||||
|     }, | ||||
|     "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 415301720, | ||||
|         "longitude": -748416257 | ||||
|     }, | ||||
|     "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 402647019, | ||||
|         "longitude": -747071791 | ||||
|     }, | ||||
|     "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412567807, | ||||
|         "longitude": -741058078 | ||||
|     }, | ||||
|     "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 416855156, | ||||
|         "longitude": -744420597 | ||||
|     }, | ||||
|     "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404663628, | ||||
|         "longitude": -744820157 | ||||
|     }, | ||||
|     "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 407113723, | ||||
|         "longitude": -749746483 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 402133926, | ||||
|         "longitude": -743613249 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 400273442, | ||||
|         "longitude": -741220915 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 411236786, | ||||
|         "longitude": -744070769 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 411633782, | ||||
|         "longitude": -746784970 | ||||
|     }, | ||||
|     "name": "211-225 Plains Road, Augusta, NJ 07822, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 415830701, | ||||
|         "longitude": -742952812 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 413447164, | ||||
|         "longitude": -748712898 | ||||
|     }, | ||||
|     "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 405047245, | ||||
|         "longitude": -749800722 | ||||
|     }, | ||||
|     "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 418858923, | ||||
|         "longitude": -746156790 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 417951888, | ||||
|         "longitude": -748484944 | ||||
|     }, | ||||
|     "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 407033786, | ||||
|         "longitude": -743977337 | ||||
|     }, | ||||
|     "name": "26 East 3rd Street, New Providence, NJ 07974, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 417548014, | ||||
|         "longitude": -740075041 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 410395868, | ||||
|         "longitude": -744972325 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404615353, | ||||
|         "longitude": -745129803 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406589790, | ||||
|         "longitude": -743560121 | ||||
|     }, | ||||
|     "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 414653148, | ||||
|         "longitude": -740477477 | ||||
|     }, | ||||
|     "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 405957808, | ||||
|         "longitude": -743255336 | ||||
|     }, | ||||
|     "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 411733589, | ||||
|         "longitude": -741648093 | ||||
|     }, | ||||
|     "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412676291, | ||||
|         "longitude": -742606606 | ||||
|     }, | ||||
|     "name": "1270 Lakes Road, Monroe, NY 10950, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 409224445, | ||||
|         "longitude": -748286738 | ||||
|     }, | ||||
|     "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406523420, | ||||
|         "longitude": -742135517 | ||||
|     }, | ||||
|     "name": "652 Garden Street, Elizabeth, NJ 07202, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 401827388, | ||||
|         "longitude": -740294537 | ||||
|     }, | ||||
|     "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 410564152, | ||||
|         "longitude": -743685054 | ||||
|     }, | ||||
|     "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 408472324, | ||||
|         "longitude": -740726046 | ||||
|     }, | ||||
|     "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412452168, | ||||
|         "longitude": -740214052 | ||||
|     }, | ||||
|     "name": "5 White Oak Lane, Stony Point, NY 10980, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 409146138, | ||||
|         "longitude": -746188906 | ||||
|     }, | ||||
|     "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404701380, | ||||
|         "longitude": -744781745 | ||||
|     }, | ||||
|     "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 409642566, | ||||
|         "longitude": -746017679 | ||||
|     }, | ||||
|     "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 408031728, | ||||
|         "longitude": -748645385 | ||||
|     }, | ||||
|     "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 413700272, | ||||
|         "longitude": -742135189 | ||||
|     }, | ||||
|     "name": "367 Prospect Road, Chester, NY 10918, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404310607, | ||||
|         "longitude": -740282632 | ||||
|     }, | ||||
|     "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 409319800, | ||||
|         "longitude": -746201391 | ||||
|     }, | ||||
|     "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406685311, | ||||
|         "longitude": -742108603 | ||||
|     }, | ||||
|     "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 419018117, | ||||
|         "longitude": -749142781 | ||||
|     }, | ||||
|     "name": "43 Dreher Road, Roscoe, NY 12776, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412856162, | ||||
|         "longitude": -745148837 | ||||
|     }, | ||||
|     "name": "Swan Street, Pine Island, NY 10969, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 416560744, | ||||
|         "longitude": -746721964 | ||||
|     }, | ||||
|     "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 405314270, | ||||
|         "longitude": -749836354 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 414219548, | ||||
|         "longitude": -743327440 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 415534177, | ||||
|         "longitude": -742900616 | ||||
|     }, | ||||
|     "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406898530, | ||||
|         "longitude": -749127080 | ||||
|     }, | ||||
|     "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 407586880, | ||||
|         "longitude": -741670168 | ||||
|     }, | ||||
|     "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 400106455, | ||||
|         "longitude": -742870190 | ||||
|     }, | ||||
|     "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 400066188, | ||||
|         "longitude": -746793294 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 418803880, | ||||
|         "longitude": -744102673 | ||||
|     }, | ||||
|     "name": "40 Mountain Road, Napanoch, NY 12458, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 414204288, | ||||
|         "longitude": -747895140 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 414777405, | ||||
|         "longitude": -740615601 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 415464475, | ||||
|         "longitude": -747175374 | ||||
|     }, | ||||
|     "name": "48 North Road, Forestburgh, NY 12777, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404062378, | ||||
|         "longitude": -746376177 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 405688272, | ||||
|         "longitude": -749285130 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 400342070, | ||||
|         "longitude": -748788996 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 401809022, | ||||
|         "longitude": -744157964 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404226644, | ||||
|         "longitude": -740517141 | ||||
|     }, | ||||
|     "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 410322033, | ||||
|         "longitude": -747871659 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 407100674, | ||||
|         "longitude": -747742727 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 418811433, | ||||
|         "longitude": -741718005 | ||||
|     }, | ||||
|     "name": "213 Bush Road, Stone Ridge, NY 12484, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 415034302, | ||||
|         "longitude": -743850945 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 411349992, | ||||
|         "longitude": -743694161 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404839914, | ||||
|         "longitude": -744759616 | ||||
|     }, | ||||
|     "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 414638017, | ||||
|         "longitude": -745957854 | ||||
|     }, | ||||
|     "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412127800, | ||||
|         "longitude": -740173578 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 401263460, | ||||
|         "longitude": -747964303 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 412843391, | ||||
|         "longitude": -749086026 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 418512773, | ||||
|         "longitude": -743067823 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404318328, | ||||
|         "longitude": -740835638 | ||||
|     }, | ||||
|     "name": "42-102 Main Street, Belford, NJ 07718, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 419020746, | ||||
|         "longitude": -741172328 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404080723, | ||||
|         "longitude": -746119569 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 401012643, | ||||
|         "longitude": -744035134 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 404306372, | ||||
|         "longitude": -741079661 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 403966326, | ||||
|         "longitude": -748519297 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 405002031, | ||||
|         "longitude": -748407866 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 409532885, | ||||
|         "longitude": -742200683 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 416851321, | ||||
|         "longitude": -742674555 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 406411633, | ||||
|         "longitude": -741722051 | ||||
|     }, | ||||
|     "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 413069058, | ||||
|         "longitude": -744597778 | ||||
|     }, | ||||
|     "name": "261 Van Sickle Road, Goshen, NY 10924, USA" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 418465462, | ||||
|         "longitude": -746859398 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 411733222, | ||||
|         "longitude": -744228360 | ||||
|     }, | ||||
|     "name": "" | ||||
| }, { | ||||
|     "location": { | ||||
|         "latitude": 410248224, | ||||
|         "longitude": -747127767 | ||||
|     }, | ||||
|     "name": "3 Hasta Way, Newton, NJ 07860, USA" | ||||
| }]`) | ||||
							
								
								
									
										114
									
								
								examples/stream/grpc/server/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								examples/stream/grpc/server/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| 	pb "github.com/asim/go-micro/examples/v4/stream/grpc/proto" | ||||
| 	"github.com/asim/go-micro/plugins/server/grpc/v4" | ||||
| 	"go-micro.dev/v4" | ||||
| 	"go-micro.dev/v4/logger" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| ) | ||||
|  | ||||
| type server struct { | ||||
| 	mu         sync.Mutex | ||||
| 	routeNotes map[string][]*pb.RouteNote | ||||
| } | ||||
|  | ||||
| func main() { | ||||
| 	srv := micro.NewService( | ||||
| 		micro.Server(grpc.NewServer()), | ||||
| 		micro.Name("stream-server"), | ||||
| 	) | ||||
| 	srv.Init() | ||||
| 	pb.RegisterRouteGuideHandler(srv.Server(), &server{routeNotes: make(map[string][]*pb.RouteNote)}) | ||||
| 	if err := srv.Run(); err != nil { | ||||
| 		logger.Fatal(err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *server) GetFeature(ctx context.Context, in *pb.Point, out *pb.Feature) error { | ||||
| 	for _, f := range features { | ||||
| 		if proto.Equal(f.Location, in) { | ||||
| 			out.Location = f.Location | ||||
| 			out.Name = f.Name | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	out.Location = in | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (s *server) ListFeatures(ctx context.Context, in *pb.Rectangle, stream pb.RouteGuide_ListFeaturesStream) error { | ||||
| 	for _, feature := range features { | ||||
| 		if inRange(feature.Location, in) { | ||||
| 			if err := stream.Send(feature); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (s *server) RecordRoute(ctx context.Context, stream pb.RouteGuide_RecordRouteStream) error { | ||||
| 	var pointCount, featureCount, distance int32 | ||||
| 	var lastPoint *pb.Point | ||||
| 	startTime := time.Now() | ||||
| 	for { | ||||
| 		point, err := stream.Recv() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		pointCount++ | ||||
| 		for _, feature := range features { | ||||
| 			if proto.Equal(feature.Location, point) { | ||||
| 				featureCount++ | ||||
| 			} | ||||
| 		} | ||||
| 		if lastPoint != nil { | ||||
| 			distance += calcDistance(lastPoint, point) | ||||
| 		} | ||||
| 		lastPoint = point | ||||
| 	} | ||||
| 	return stream.SendMsg(&pb.RouteSummary{ | ||||
| 		PointCount:   pointCount, | ||||
| 		FeatureCount: featureCount, | ||||
| 		Distance:     distance, | ||||
| 		ElapsedTime:  int32(time.Since(startTime).Seconds()), | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func (s *server) RouteChat(ctx context.Context, stream pb.RouteGuide_RouteChatStream) error { | ||||
| 	for { | ||||
| 		in, err := stream.Recv() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		key := serialize(in.Location) | ||||
|  | ||||
| 		s.mu.Lock() | ||||
| 		s.routeNotes[key] = append(s.routeNotes[key], in) | ||||
| 		// Note: this copy prevents blocking other clients while serving this one. | ||||
| 		// We don't need to do a deep copy, because elements in the slice are | ||||
| 		// insert-only and never modified. | ||||
| 		rn := make([]*pb.RouteNote, len(s.routeNotes[key])) | ||||
| 		copy(rn, s.routeNotes[key]) | ||||
| 		s.mu.Unlock() | ||||
|  | ||||
| 		for _, note := range rn { | ||||
| 			if err := stream.Send(note); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -2,10 +2,12 @@ package main | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"context" | ||||
| 	proto "github.com/asim/go-micro/examples/v4/stream/server/proto" | ||||
| 
 | ||||
| 	proto "github.com/asim/go-micro/examples/v4/stream/rpc/server/proto" | ||||
| 	"go-micro.dev/v4" | ||||
| ) | ||||
| 
 | ||||
| @@ -25,6 +27,9 @@ func bidirectional(cl proto.StreamerService) { | ||||
| 			return | ||||
| 		} | ||||
| 		rsp, err := stream.Recv() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			fmt.Println("recv err", err) | ||||
| 			break | ||||
| @@ -52,6 +57,9 @@ func serverStream(cl proto.StreamerService) { | ||||
| 	// receive messages for a 10 count | ||||
| 	for { | ||||
| 		rsp, err := stream.Recv() | ||||
| 		if err == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			fmt.Println("recv err", err) | ||||
| 			break | ||||
| @@ -6,7 +6,7 @@ import ( | ||||
| 	"io" | ||||
| 	"log" | ||||
| 
 | ||||
| 	proto "github.com/asim/go-micro/examples/v4/stream/server/proto" | ||||
| 	proto "github.com/asim/go-micro/examples/v4/stream/rpc/server/proto" | ||||
| 	"go-micro.dev/v4" | ||||
| ) | ||||
| 
 | ||||
							
								
								
									
										213
									
								
								examples/stream/rpc/server/proto/stream.pb.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								examples/stream/rpc/server/proto/stream.pb.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,213 @@ | ||||
| // Code generated by protoc-gen-go. DO NOT EDIT. | ||||
| // versions: | ||||
| // 	protoc-gen-go v1.27.1 | ||||
| // 	protoc        v3.15.6 | ||||
| // source: proto/stream.proto | ||||
|  | ||||
| package stream | ||||
|  | ||||
| import ( | ||||
| 	protoreflect "google.golang.org/protobuf/reflect/protoreflect" | ||||
| 	protoimpl "google.golang.org/protobuf/runtime/protoimpl" | ||||
| 	reflect "reflect" | ||||
| 	sync "sync" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	// Verify that this generated code is sufficiently up-to-date. | ||||
| 	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) | ||||
| 	// Verify that runtime/protoimpl is sufficiently up-to-date. | ||||
| 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) | ||||
| ) | ||||
|  | ||||
| type Request struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Request) Reset() { | ||||
| 	*x = Request{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_proto_stream_proto_msgTypes[0] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *Request) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*Request) ProtoMessage() {} | ||||
|  | ||||
| func (x *Request) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_proto_stream_proto_msgTypes[0] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use Request.ProtoReflect.Descriptor instead. | ||||
| func (*Request) Descriptor() ([]byte, []int) { | ||||
| 	return file_proto_stream_proto_rawDescGZIP(), []int{0} | ||||
| } | ||||
|  | ||||
| func (x *Request) GetCount() int64 { | ||||
| 	if x != nil { | ||||
| 		return x.Count | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| type Response struct { | ||||
| 	state         protoimpl.MessageState | ||||
| 	sizeCache     protoimpl.SizeCache | ||||
| 	unknownFields protoimpl.UnknownFields | ||||
|  | ||||
| 	Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"` | ||||
| } | ||||
|  | ||||
| func (x *Response) Reset() { | ||||
| 	*x = Response{} | ||||
| 	if protoimpl.UnsafeEnabled { | ||||
| 		mi := &file_proto_stream_proto_msgTypes[1] | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		ms.StoreMessageInfo(mi) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (x *Response) String() string { | ||||
| 	return protoimpl.X.MessageStringOf(x) | ||||
| } | ||||
|  | ||||
| func (*Response) ProtoMessage() {} | ||||
|  | ||||
| func (x *Response) ProtoReflect() protoreflect.Message { | ||||
| 	mi := &file_proto_stream_proto_msgTypes[1] | ||||
| 	if protoimpl.UnsafeEnabled && x != nil { | ||||
| 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||||
| 		if ms.LoadMessageInfo() == nil { | ||||
| 			ms.StoreMessageInfo(mi) | ||||
| 		} | ||||
| 		return ms | ||||
| 	} | ||||
| 	return mi.MessageOf(x) | ||||
| } | ||||
|  | ||||
| // Deprecated: Use Response.ProtoReflect.Descriptor instead. | ||||
| func (*Response) Descriptor() ([]byte, []int) { | ||||
| 	return file_proto_stream_proto_rawDescGZIP(), []int{1} | ||||
| } | ||||
|  | ||||
| func (x *Response) GetCount() int64 { | ||||
| 	if x != nil { | ||||
| 		return x.Count | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| var File_proto_stream_proto protoreflect.FileDescriptor | ||||
|  | ||||
| var file_proto_stream_proto_rawDesc = []byte{ | ||||
| 	0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x70, | ||||
| 	0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1f, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, | ||||
| 	0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, | ||||
| 	0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x20, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, | ||||
| 	0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, | ||||
| 	0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0x58, 0x0a, 0x08, 0x53, 0x74, 0x72, 0x65, 0x61, | ||||
| 	0x6d, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x06, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x08, 0x2e, | ||||
| 	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x09, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, | ||||
| 	0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x27, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, | ||||
| 	0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x08, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, | ||||
| 	0x73, 0x74, 0x1a, 0x09, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, | ||||
| 	0x01, 0x42, 0x10, 0x5a, 0x0e, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x73, 0x74, 0x72, | ||||
| 	0x65, 0x61, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||
| } | ||||
|  | ||||
| var ( | ||||
| 	file_proto_stream_proto_rawDescOnce sync.Once | ||||
| 	file_proto_stream_proto_rawDescData = file_proto_stream_proto_rawDesc | ||||
| ) | ||||
|  | ||||
| func file_proto_stream_proto_rawDescGZIP() []byte { | ||||
| 	file_proto_stream_proto_rawDescOnce.Do(func() { | ||||
| 		file_proto_stream_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_stream_proto_rawDescData) | ||||
| 	}) | ||||
| 	return file_proto_stream_proto_rawDescData | ||||
| } | ||||
|  | ||||
| var file_proto_stream_proto_msgTypes = make([]protoimpl.MessageInfo, 2) | ||||
| var file_proto_stream_proto_goTypes = []interface{}{ | ||||
| 	(*Request)(nil),  // 0: Request | ||||
| 	(*Response)(nil), // 1: Response | ||||
| } | ||||
| var file_proto_stream_proto_depIdxs = []int32{ | ||||
| 	0, // 0: Streamer.Stream:input_type -> Request | ||||
| 	0, // 1: Streamer.ServerStream:input_type -> Request | ||||
| 	1, // 2: Streamer.Stream:output_type -> Response | ||||
| 	1, // 3: Streamer.ServerStream:output_type -> Response | ||||
| 	2, // [2:4] is the sub-list for method output_type | ||||
| 	0, // [0:2] is the sub-list for method input_type | ||||
| 	0, // [0:0] is the sub-list for extension type_name | ||||
| 	0, // [0:0] is the sub-list for extension extendee | ||||
| 	0, // [0:0] is the sub-list for field type_name | ||||
| } | ||||
|  | ||||
| func init() { file_proto_stream_proto_init() } | ||||
| func file_proto_stream_proto_init() { | ||||
| 	if File_proto_stream_proto != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if !protoimpl.UnsafeEnabled { | ||||
| 		file_proto_stream_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*Request); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 		file_proto_stream_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { | ||||
| 			switch v := v.(*Response); i { | ||||
| 			case 0: | ||||
| 				return &v.state | ||||
| 			case 1: | ||||
| 				return &v.sizeCache | ||||
| 			case 2: | ||||
| 				return &v.unknownFields | ||||
| 			default: | ||||
| 				return nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	type x struct{} | ||||
| 	out := protoimpl.TypeBuilder{ | ||||
| 		File: protoimpl.DescBuilder{ | ||||
| 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||||
| 			RawDescriptor: file_proto_stream_proto_rawDesc, | ||||
| 			NumEnums:      0, | ||||
| 			NumMessages:   2, | ||||
| 			NumExtensions: 0, | ||||
| 			NumServices:   1, | ||||
| 		}, | ||||
| 		GoTypes:           file_proto_stream_proto_goTypes, | ||||
| 		DependencyIndexes: file_proto_stream_proto_depIdxs, | ||||
| 		MessageInfos:      file_proto_stream_proto_msgTypes, | ||||
| 	}.Build() | ||||
| 	File_proto_stream_proto = out.File | ||||
| 	file_proto_stream_proto_rawDesc = nil | ||||
| 	file_proto_stream_proto_goTypes = nil | ||||
| 	file_proto_stream_proto_depIdxs = nil | ||||
| } | ||||
| @@ -1,24 +1,17 @@ | ||||
| // Code generated by protoc-gen-micro. DO NOT EDIT. | ||||
| // source: github.com/asim/go-micro/examples/v4/stream/server/proto/stream.proto | ||||
| // source: proto/stream.proto | ||||
| 
 | ||||
| /* | ||||
| Package stream is a generated protocol buffer package. | ||||
| 
 | ||||
| It is generated from these files: | ||||
| 	github.com/asim/go-micro/examples/v4/stream/server/proto/stream.proto | ||||
| 
 | ||||
| It has these top-level messages: | ||||
| 	Request | ||||
| 	Response | ||||
| */ | ||||
| package stream | ||||
| 
 | ||||
| import proto "github.com/golang/protobuf/proto" | ||||
| import fmt "fmt" | ||||
| import math "math" | ||||
| import ( | ||||
| 	fmt "fmt" | ||||
| 	proto "google.golang.org/protobuf/proto" | ||||
| 	math "math" | ||||
| ) | ||||
| 
 | ||||
| import ( | ||||
| 	context "context" | ||||
| 	api "go-micro.dev/v4/api" | ||||
| 	client "go-micro.dev/v4/client" | ||||
| 	server "go-micro.dev/v4/server" | ||||
| ) | ||||
| @@ -28,17 +21,18 @@ var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
| 
 | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| // A compilation error at this line likely means your copy of the | ||||
| // proto package needs to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package | ||||
| 
 | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ api.Endpoint | ||||
| var _ context.Context | ||||
| var _ client.Option | ||||
| var _ server.Option | ||||
| 
 | ||||
| // Api Endpoints for Streamer service | ||||
| 
 | ||||
| func NewStreamerEndpoints() []*api.Endpoint { | ||||
| 	return []*api.Endpoint{} | ||||
| } | ||||
| 
 | ||||
| // Client API for Streamer service | ||||
| 
 | ||||
| type StreamerService interface { | ||||
| @@ -47,61 +41,65 @@ type StreamerService interface { | ||||
| } | ||||
| 
 | ||||
| type streamerService struct { | ||||
| 	c           client.Client | ||||
| 	serviceName string | ||||
| 	c    client.Client | ||||
| 	name string | ||||
| } | ||||
| 
 | ||||
| func NewStreamerService(serviceName string, c client.Client) StreamerService { | ||||
| 	if c == nil { | ||||
| 		c = client.NewClient() | ||||
| 	} | ||||
| 	if len(serviceName) == 0 { | ||||
| 		serviceName = "streamer" | ||||
| 	} | ||||
| func NewStreamerService(name string, c client.Client) StreamerService { | ||||
| 	return &streamerService{ | ||||
| 		c:           c, | ||||
| 		serviceName: serviceName, | ||||
| 		c:    c, | ||||
| 		name: name, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (c *streamerService) Stream(ctx context.Context, opts ...client.CallOption) (Streamer_StreamService, error) { | ||||
| 	req := c.c.NewRequest(c.serviceName, "Streamer.Stream", &Request{}) | ||||
| 	req := c.c.NewRequest(c.name, "Streamer.Stream", &Request{}) | ||||
| 	stream, err := c.c.Stream(ctx, req, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &streamerStreamService{stream}, nil | ||||
| 	return &streamerServiceStream{stream}, nil | ||||
| } | ||||
| 
 | ||||
| type Streamer_StreamService interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	CloseSend() error | ||||
| 	Close() error | ||||
| 	Send(*Request) error | ||||
| 	Recv() (*Response, error) | ||||
| } | ||||
| 
 | ||||
| type streamerStreamService struct { | ||||
| type streamerServiceStream struct { | ||||
| 	stream client.Stream | ||||
| } | ||||
| 
 | ||||
| func (x *streamerStreamService) Close() error { | ||||
| func (x *streamerServiceStream) CloseSend() error { | ||||
| 	return x.stream.CloseSend() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServiceStream) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerStreamService) SendMsg(m interface{}) error { | ||||
| func (x *streamerServiceStream) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServiceStream) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
| 
 | ||||
| func (x *streamerStreamService) RecvMsg(m interface{}) error { | ||||
| func (x *streamerServiceStream) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
| 
 | ||||
| func (x *streamerStreamService) Send(m *Request) error { | ||||
| func (x *streamerServiceStream) Send(m *Request) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
| 
 | ||||
| func (x *streamerStreamService) Recv() (*Response, error) { | ||||
| func (x *streamerServiceStream) Recv() (*Response, error) { | ||||
| 	m := new(Response) | ||||
| 	err := x.stream.Recv(m) | ||||
| 	if err != nil { | ||||
| @@ -111,7 +109,7 @@ func (x *streamerStreamService) Recv() (*Response, error) { | ||||
| } | ||||
| 
 | ||||
| func (c *streamerService) ServerStream(ctx context.Context, in *Request, opts ...client.CallOption) (Streamer_ServerStreamService, error) { | ||||
| 	req := c.c.NewRequest(c.serviceName, "Streamer.ServerStream", &Request{}) | ||||
| 	req := c.c.NewRequest(c.name, "Streamer.ServerStream", &Request{}) | ||||
| 	stream, err := c.c.Stream(ctx, req, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| @@ -119,33 +117,43 @@ func (c *streamerService) ServerStream(ctx context.Context, in *Request, opts .. | ||||
| 	if err := stream.Send(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &streamerServerStreamService{stream}, nil | ||||
| 	return &streamerServiceServerStream{stream}, nil | ||||
| } | ||||
| 
 | ||||
| type Streamer_ServerStreamService interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	CloseSend() error | ||||
| 	Close() error | ||||
| 	Recv() (*Response, error) | ||||
| } | ||||
| 
 | ||||
| type streamerServerStreamService struct { | ||||
| type streamerServiceServerStream struct { | ||||
| 	stream client.Stream | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServerStreamService) Close() error { | ||||
| func (x *streamerServiceServerStream) CloseSend() error { | ||||
| 	return x.stream.CloseSend() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServiceServerStream) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServerStreamService) SendMsg(m interface{}) error { | ||||
| func (x *streamerServiceServerStream) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServiceServerStream) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServerStreamService) RecvMsg(m interface{}) error { | ||||
| func (x *streamerServiceServerStream) RecvMsg(m interface{}) error { | ||||
| 	return x.stream.Recv(m) | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServerStreamService) Recv() (*Response, error) { | ||||
| func (x *streamerServiceServerStream) Recv() (*Response, error) { | ||||
| 	m := new(Response) | ||||
| 	err := x.stream.Recv(m) | ||||
| 	if err != nil { | ||||
| @@ -161,7 +169,7 @@ type StreamerHandler interface { | ||||
| 	ServerStream(context.Context, *Request, Streamer_ServerStreamStream) error | ||||
| } | ||||
| 
 | ||||
| func RegisterStreamerHandler(s server.Server, hdlr StreamerHandler, opts ...server.HandlerOption) { | ||||
| func RegisterStreamerHandler(s server.Server, hdlr StreamerHandler, opts ...server.HandlerOption) error { | ||||
| 	type streamer interface { | ||||
| 		Stream(ctx context.Context, stream server.Stream) error | ||||
| 		ServerStream(ctx context.Context, stream server.Stream) error | ||||
| @@ -170,7 +178,7 @@ func RegisterStreamerHandler(s server.Server, hdlr StreamerHandler, opts ...serv | ||||
| 		streamer | ||||
| 	} | ||||
| 	h := &streamerHandler{hdlr} | ||||
| 	s.Handle(s.NewHandler(&Streamer{h}, opts...)) | ||||
| 	return s.Handle(s.NewHandler(&Streamer{h}, opts...)) | ||||
| } | ||||
| 
 | ||||
| type streamerHandler struct { | ||||
| @@ -182,6 +190,7 @@ func (h *streamerHandler) Stream(ctx context.Context, stream server.Stream) erro | ||||
| } | ||||
| 
 | ||||
| type Streamer_StreamStream interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	Close() error | ||||
| @@ -197,6 +206,10 @@ func (x *streamerStreamStream) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerStreamStream) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerStreamStream) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
| @@ -226,6 +239,7 @@ func (h *streamerHandler) ServerStream(ctx context.Context, stream server.Stream | ||||
| } | ||||
| 
 | ||||
| type Streamer_ServerStreamStream interface { | ||||
| 	Context() context.Context | ||||
| 	SendMsg(interface{}) error | ||||
| 	RecvMsg(interface{}) error | ||||
| 	Close() error | ||||
| @@ -240,6 +254,10 @@ func (x *streamerServerStreamStream) Close() error { | ||||
| 	return x.stream.Close() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServerStreamStream) Context() context.Context { | ||||
| 	return x.stream.Context() | ||||
| } | ||||
| 
 | ||||
| func (x *streamerServerStreamStream) SendMsg(m interface{}) error { | ||||
| 	return x.stream.Send(m) | ||||
| } | ||||
| @@ -1,5 +1,7 @@ | ||||
| syntax = "proto3"; | ||||
| 
 | ||||
| option go_package = "./proto;stream"; | ||||
| 
 | ||||
| service Streamer { | ||||
| 	rpc Stream(stream Request) returns (stream Response) {} | ||||
| 	rpc ServerStream(Request) returns (stream Response) {} | ||||
| @@ -1,254 +0,0 @@ | ||||
| // Code generated by protoc-gen-go. DO NOT EDIT. | ||||
| // source: github.com/asim/go-micro/examples/v4/stream/server/proto/stream.proto | ||||
|  | ||||
| /* | ||||
| Package stream is a generated protocol buffer package. | ||||
|  | ||||
| It is generated from these files: | ||||
| 	github.com/asim/go-micro/examples/v4/stream/server/proto/stream.proto | ||||
|  | ||||
| It has these top-level messages: | ||||
| 	Request | ||||
| 	Response | ||||
| */ | ||||
| package stream | ||||
|  | ||||
| import proto "github.com/golang/protobuf/proto" | ||||
| import fmt "fmt" | ||||
| import math "math" | ||||
|  | ||||
| import ( | ||||
| 	context "golang.org/x/net/context" | ||||
| 	grpc "google.golang.org/grpc" | ||||
| ) | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ = proto.Marshal | ||||
| var _ = fmt.Errorf | ||||
| var _ = math.Inf | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the proto package it is being compiled against. | ||||
| // A compilation error at this line likely means your copy of the | ||||
| // proto package needs to be updated. | ||||
| const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package | ||||
|  | ||||
| type Request struct { | ||||
| 	Count int64 `protobuf:"varint,1,opt,name=count" json:"count,omitempty"` | ||||
| } | ||||
|  | ||||
| func (m *Request) Reset()                    { *m = Request{} } | ||||
| func (m *Request) String() string            { return proto.CompactTextString(m) } | ||||
| func (*Request) ProtoMessage()               {} | ||||
| func (*Request) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } | ||||
|  | ||||
| func (m *Request) GetCount() int64 { | ||||
| 	if m != nil { | ||||
| 		return m.Count | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| type Response struct { | ||||
| 	Count int64 `protobuf:"varint,1,opt,name=count" json:"count,omitempty"` | ||||
| } | ||||
|  | ||||
| func (m *Response) Reset()                    { *m = Response{} } | ||||
| func (m *Response) String() string            { return proto.CompactTextString(m) } | ||||
| func (*Response) ProtoMessage()               {} | ||||
| func (*Response) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } | ||||
|  | ||||
| func (m *Response) GetCount() int64 { | ||||
| 	if m != nil { | ||||
| 		return m.Count | ||||
| 	} | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterType((*Request)(nil), "Request") | ||||
| 	proto.RegisterType((*Response)(nil), "Response") | ||||
| } | ||||
|  | ||||
| // Reference imports to suppress errors if they are not otherwise used. | ||||
| var _ context.Context | ||||
| var _ grpc.ClientConn | ||||
|  | ||||
| // This is a compile-time assertion to ensure that this generated file | ||||
| // is compatible with the grpc package it is being compiled against. | ||||
| const _ = grpc.SupportPackageIsVersion4 | ||||
|  | ||||
| // Client API for Streamer service | ||||
|  | ||||
| type StreamerClient interface { | ||||
| 	Stream(ctx context.Context, opts ...grpc.CallOption) (Streamer_StreamClient, error) | ||||
| 	ServerStream(ctx context.Context, in *Request, opts ...grpc.CallOption) (Streamer_ServerStreamClient, error) | ||||
| } | ||||
|  | ||||
| type streamerClient struct { | ||||
| 	cc *grpc.ClientConn | ||||
| } | ||||
|  | ||||
| func NewStreamerClient(cc *grpc.ClientConn) StreamerClient { | ||||
| 	return &streamerClient{cc} | ||||
| } | ||||
|  | ||||
| func (c *streamerClient) Stream(ctx context.Context, opts ...grpc.CallOption) (Streamer_StreamClient, error) { | ||||
| 	stream, err := grpc.NewClientStream(ctx, &_Streamer_serviceDesc.Streams[0], c.cc, "/Streamer/Stream", opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	x := &streamerStreamClient{stream} | ||||
| 	return x, nil | ||||
| } | ||||
|  | ||||
| type Streamer_StreamClient interface { | ||||
| 	Send(*Request) error | ||||
| 	Recv() (*Response, error) | ||||
| 	grpc.ClientStream | ||||
| } | ||||
|  | ||||
| type streamerStreamClient struct { | ||||
| 	grpc.ClientStream | ||||
| } | ||||
|  | ||||
| func (x *streamerStreamClient) Send(m *Request) error { | ||||
| 	return x.ClientStream.SendMsg(m) | ||||
| } | ||||
|  | ||||
| func (x *streamerStreamClient) Recv() (*Response, error) { | ||||
| 	m := new(Response) | ||||
| 	if err := x.ClientStream.RecvMsg(m); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func (c *streamerClient) ServerStream(ctx context.Context, in *Request, opts ...grpc.CallOption) (Streamer_ServerStreamClient, error) { | ||||
| 	stream, err := grpc.NewClientStream(ctx, &_Streamer_serviceDesc.Streams[1], c.cc, "/Streamer/ServerStream", opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	x := &streamerServerStreamClient{stream} | ||||
| 	if err := x.ClientStream.SendMsg(in); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if err := x.ClientStream.CloseSend(); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return x, nil | ||||
| } | ||||
|  | ||||
| type Streamer_ServerStreamClient interface { | ||||
| 	Recv() (*Response, error) | ||||
| 	grpc.ClientStream | ||||
| } | ||||
|  | ||||
| type streamerServerStreamClient struct { | ||||
| 	grpc.ClientStream | ||||
| } | ||||
|  | ||||
| func (x *streamerServerStreamClient) Recv() (*Response, error) { | ||||
| 	m := new(Response) | ||||
| 	if err := x.ClientStream.RecvMsg(m); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| // Server API for Streamer service | ||||
|  | ||||
| type StreamerServer interface { | ||||
| 	Stream(Streamer_StreamServer) error | ||||
| 	ServerStream(*Request, Streamer_ServerStreamServer) error | ||||
| } | ||||
|  | ||||
| func RegisterStreamerServer(s *grpc.Server, srv StreamerServer) { | ||||
| 	s.RegisterService(&_Streamer_serviceDesc, srv) | ||||
| } | ||||
|  | ||||
| func _Streamer_Stream_Handler(srv interface{}, stream grpc.ServerStream) error { | ||||
| 	return srv.(StreamerServer).Stream(&streamerStreamServer{stream}) | ||||
| } | ||||
|  | ||||
| type Streamer_StreamServer interface { | ||||
| 	Send(*Response) error | ||||
| 	Recv() (*Request, error) | ||||
| 	grpc.ServerStream | ||||
| } | ||||
|  | ||||
| type streamerStreamServer struct { | ||||
| 	grpc.ServerStream | ||||
| } | ||||
|  | ||||
| func (x *streamerStreamServer) Send(m *Response) error { | ||||
| 	return x.ServerStream.SendMsg(m) | ||||
| } | ||||
|  | ||||
| func (x *streamerStreamServer) Recv() (*Request, error) { | ||||
| 	m := new(Request) | ||||
| 	if err := x.ServerStream.RecvMsg(m); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return m, nil | ||||
| } | ||||
|  | ||||
| func _Streamer_ServerStream_Handler(srv interface{}, stream grpc.ServerStream) error { | ||||
| 	m := new(Request) | ||||
| 	if err := stream.RecvMsg(m); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return srv.(StreamerServer).ServerStream(m, &streamerServerStreamServer{stream}) | ||||
| } | ||||
|  | ||||
| type Streamer_ServerStreamServer interface { | ||||
| 	Send(*Response) error | ||||
| 	grpc.ServerStream | ||||
| } | ||||
|  | ||||
| type streamerServerStreamServer struct { | ||||
| 	grpc.ServerStream | ||||
| } | ||||
|  | ||||
| func (x *streamerServerStreamServer) Send(m *Response) error { | ||||
| 	return x.ServerStream.SendMsg(m) | ||||
| } | ||||
|  | ||||
| var _Streamer_serviceDesc = grpc.ServiceDesc{ | ||||
| 	ServiceName: "Streamer", | ||||
| 	HandlerType: (*StreamerServer)(nil), | ||||
| 	Methods:     []grpc.MethodDesc{}, | ||||
| 	Streams: []grpc.StreamDesc{ | ||||
| 		{ | ||||
| 			StreamName:    "Stream", | ||||
| 			Handler:       _Streamer_Stream_Handler, | ||||
| 			ServerStreams: true, | ||||
| 			ClientStreams: true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			StreamName:    "ServerStream", | ||||
| 			Handler:       _Streamer_ServerStream_Handler, | ||||
| 			ServerStreams: true, | ||||
| 		}, | ||||
| 	}, | ||||
| 	Metadata: "github.com/asim/go-micro/examples/v4/stream/server/proto/stream.proto", | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	proto.RegisterFile("github.com/asim/go-micro/examples/v4/stream/server/proto/stream.proto", fileDescriptor0) | ||||
| } | ||||
|  | ||||
| var fileDescriptor0 = []byte{ | ||||
| 	// 167 bytes of a gzipped FileDescriptorProto | ||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4a, 0xcf, 0x2c, 0xc9, | ||||
| 	0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0xcf, 0xcd, 0x4c, 0x2e, 0xca, 0xd7, 0x4f, 0xad, 0x48, | ||||
| 	0xcc, 0x2d, 0xc8, 0x49, 0x2d, 0xd6, 0x2f, 0x2e, 0x29, 0x4a, 0x4d, 0xcc, 0xd5, 0x2f, 0x4e, 0x2d, | ||||
| 	0x2a, 0x4b, 0x2d, 0xd2, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x87, 0x8a, 0xe9, 0x81, 0x39, 0x4a, 0xf2, | ||||
| 	0x5c, 0xec, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x22, 0x5c, 0xac, 0xc9, 0xf9, 0xa5, | ||||
| 	0x79, 0x25, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x10, 0x8e, 0x92, 0x02, 0x17, 0x47, 0x50, | ||||
| 	0x6a, 0x71, 0x41, 0x7e, 0x5e, 0x71, 0x2a, 0x76, 0x15, 0x46, 0x11, 0x5c, 0x1c, 0xc1, 0x60, 0x23, | ||||
| 	0x53, 0x8b, 0x84, 0x94, 0xb9, 0xd8, 0x20, 0x6c, 0x21, 0x0e, 0x3d, 0xa8, 0xb9, 0x52, 0x9c, 0x7a, | ||||
| 	0x30, 0x03, 0x94, 0x18, 0x34, 0x18, 0x0d, 0x18, 0x85, 0xd4, 0xb9, 0x78, 0x82, 0xc1, 0x0e, 0xc2, | ||||
| 	0xab, 0xd4, 0x80, 0x31, 0x89, 0x0d, 0xec, 0x46, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x16, | ||||
| 	0x4a, 0x84, 0x3f, 0xe1, 0x00, 0x00, 0x00, | ||||
| } | ||||
| @@ -1,19 +1,17 @@ | ||||
| package grpc | ||||
|  | ||||
| import ( | ||||
| 	b "bytes" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
|  | ||||
| 	b "bytes" | ||||
|  | ||||
| 	"github.com/golang/protobuf/jsonpb" | ||||
| 	"github.com/golang/protobuf/proto" | ||||
| 	"go-micro.dev/v4/codec" | ||||
| 	"go-micro.dev/v4/codec/bytes" | ||||
| 	"github.com/oxtoacart/bpool" | ||||
| 	"google.golang.org/grpc" | ||||
| 	"google.golang.org/grpc/encoding" | ||||
| 	"google.golang.org/protobuf/encoding/protojson" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| ) | ||||
|  | ||||
| type jsonCodec struct{} | ||||
| @@ -21,12 +19,8 @@ type protoCodec struct{} | ||||
| type bytesCodec struct{} | ||||
| type wrapCodec struct{ encoding.Codec } | ||||
|  | ||||
| var jsonpbMarshaler = &jsonpb.Marshaler{} | ||||
| var useNumber bool | ||||
|  | ||||
| // create buffer pool with 16 instances each preallocated with 256 bytes | ||||
| var bufferPool = bpool.NewSizedBufferPool(16, 256) | ||||
|  | ||||
| var ( | ||||
| 	defaultGRPCCodecs = map[string]encoding.Codec{ | ||||
| 		"application/json":         jsonCodec{}, | ||||
| @@ -115,12 +109,11 @@ func (jsonCodec) Marshal(v interface{}) ([]byte, error) { | ||||
| 	} | ||||
|  | ||||
| 	if pb, ok := v.(proto.Message); ok { | ||||
| 		buf := bufferPool.Get() | ||||
| 		defer bufferPool.Put(buf) | ||||
| 		if err := jsonpbMarshaler.Marshal(buf, pb); err != nil { | ||||
| 		bytes, err := protojson.Marshal(pb) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		return buf.Bytes(), nil | ||||
| 		return bytes, nil | ||||
| 	} | ||||
|  | ||||
| 	return json.Marshal(v) | ||||
| @@ -135,7 +128,7 @@ func (jsonCodec) Unmarshal(data []byte, v interface{}) error { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if pb, ok := v.(proto.Message); ok { | ||||
| 		return jsonpb.Unmarshal(b.NewReader(data), pb) | ||||
| 		return protojson.Unmarshal(data, pb) | ||||
| 	} | ||||
|  | ||||
| 	dec := json.NewDecoder(b.NewReader(data)) | ||||
|   | ||||
| @@ -3,11 +3,10 @@ module github.com/asim/go-micro/plugins/client/grpc/v4 | ||||
| go 1.16 | ||||
|  | ||||
| require ( | ||||
| 	github.com/golang/protobuf v1.5.2 | ||||
| 	github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c | ||||
| 	go-micro.dev/v4 v4.2.1 | ||||
| 	google.golang.org/grpc v1.41.0 | ||||
| 	google.golang.org/grpc/examples v0.0.0-20211020220737-f00baa6c3c84 | ||||
| 	google.golang.org/protobuf v1.26.0 | ||||
| ) | ||||
|  | ||||
| replace go-micro.dev/v4 => ../../../../go-micro | ||||
|   | ||||
| @@ -12,15 +12,14 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"go-micro.dev/v4/broker" | ||||
| 	"go-micro.dev/v4/cmd" | ||||
| 	"go-micro.dev/v4/client" | ||||
| 	"go-micro.dev/v4/cmd" | ||||
| 	raw "go-micro.dev/v4/codec/bytes" | ||||
| 	"go-micro.dev/v4/errors" | ||||
| 	"go-micro.dev/v4/metadata" | ||||
| 	"go-micro.dev/v4/registry" | ||||
| 	"go-micro.dev/v4/selector" | ||||
| 	pnet "go-micro.dev/v4/util/net" | ||||
|  | ||||
| 	"google.golang.org/grpc" | ||||
| 	"google.golang.org/grpc/credentials" | ||||
| 	"google.golang.org/grpc/encoding" | ||||
| @@ -104,7 +103,6 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R | ||||
|  | ||||
| 	address := node.Address | ||||
|  | ||||
| 	header = make(map[string]string) | ||||
| 	if md, ok := metadata.FromContext(ctx); ok { | ||||
| 		header = make(map[string]string, len(md)) | ||||
| 		for k, v := range md { | ||||
| @@ -132,8 +130,16 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R | ||||
|  | ||||
| 	var grr error | ||||
|  | ||||
| 	var dialCtx context.Context | ||||
| 	var cancel context.CancelFunc | ||||
| 	if opts.DialTimeout > 0 { | ||||
| 		dialCtx, cancel = context.WithTimeout(ctx, opts.DialTimeout) | ||||
| 	} else { | ||||
| 		dialCtx, cancel = context.WithCancel(ctx) | ||||
| 	} | ||||
| 	defer cancel() | ||||
|  | ||||
| 	grpcDialOptions := []grpc.DialOption{ | ||||
| 		grpc.WithTimeout(opts.DialTimeout), | ||||
| 		g.secure(address), | ||||
| 		grpc.WithDefaultCallOptions( | ||||
| 			grpc.MaxCallRecvMsgSize(maxRecvMsgSize), | ||||
| @@ -145,7 +151,7 @@ func (g *grpcClient) call(ctx context.Context, node *registry.Node, req client.R | ||||
| 		grpcDialOptions = append(grpcDialOptions, opts...) | ||||
| 	} | ||||
|  | ||||
| 	cc, err := g.pool.getConn(address, grpcDialOptions...) | ||||
| 	cc, err := g.pool.getConn(dialCtx, address, grpcDialOptions...) | ||||
| 	if err != nil { | ||||
| 		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err)) | ||||
| 	} | ||||
| @@ -208,7 +214,7 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client | ||||
|  | ||||
| 	var dialCtx context.Context | ||||
| 	var cancel context.CancelFunc | ||||
| 	if opts.DialTimeout >= 0 { | ||||
| 	if opts.DialTimeout > 0 { | ||||
| 		dialCtx, cancel = context.WithTimeout(ctx, opts.DialTimeout) | ||||
| 	} else { | ||||
| 		dialCtx, cancel = context.WithCancel(ctx) | ||||
| @@ -218,7 +224,6 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client | ||||
| 	wc := wrapCodec{cf} | ||||
|  | ||||
| 	grpcDialOptions := []grpc.DialOption{ | ||||
| 		grpc.WithTimeout(opts.DialTimeout), | ||||
| 		g.secure(address), | ||||
| 	} | ||||
|  | ||||
| @@ -226,7 +231,7 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client | ||||
| 		grpcDialOptions = append(grpcDialOptions, opts...) | ||||
| 	} | ||||
|  | ||||
| 	cc, err := grpc.DialContext(dialCtx, address, grpcDialOptions...) | ||||
| 	cc, err := g.pool.getConn(dialCtx, address, grpcDialOptions...) | ||||
| 	if err != nil { | ||||
| 		return errors.InternalServerError("go.micro.client", fmt.Sprintf("Error sending request: %v", err)) | ||||
| 	} | ||||
| @@ -274,14 +279,16 @@ func (g *grpcClient) stream(ctx context.Context, node *registry.Node, req client | ||||
| 		context: ctx, | ||||
| 		request: req, | ||||
| 		response: &response{ | ||||
| 			conn:   cc, | ||||
| 			conn:   cc.ClientConn, | ||||
| 			stream: st, | ||||
| 			codec:  cf, | ||||
| 			gcodec: codec, | ||||
| 		}, | ||||
| 		stream: st, | ||||
| 		conn:   cc, | ||||
| 		cancel: cancel, | ||||
| 		release: func(err error) { | ||||
| 			g.pool.release(address, cc, err) | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	// set the stream as the response | ||||
| @@ -347,7 +354,7 @@ func (g *grpcClient) newGRPCCodec(contentType string) (encoding.Codec, error) { | ||||
| 	if c, ok := defaultGRPCCodecs[contentType]; ok { | ||||
| 		return wrapCodec{c}, nil | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("Unsupported Content-Type: %s", contentType) | ||||
| 	return nil, fmt.Errorf("unsupported Content-Type: %s", contentType) | ||||
| } | ||||
|  | ||||
| func (g *grpcClient) Init(opts ...client.Option) error { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package grpc | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"sync" | ||||
| 	"time" | ||||
|  | ||||
| @@ -66,7 +67,7 @@ func newPool(size int, ttl time.Duration, idle int, ms int) *pool { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (p *pool) getConn(addr string, opts ...grpc.DialOption) (*poolConn, error) { | ||||
| func (p *pool) getConn(dialCtx context.Context, addr string, opts ...grpc.DialOption) (*poolConn, error) { | ||||
| 	now := time.Now().Unix() | ||||
| 	p.Lock() | ||||
| 	sp, ok := p.conns[addr] | ||||
| @@ -135,7 +136,7 @@ func (p *pool) getConn(addr string, opts ...grpc.DialOption) (*poolConn, error) | ||||
| 	p.Unlock() | ||||
|  | ||||
| 	//  create new conn | ||||
| 	cc, err := grpc.Dial(addr, opts...) | ||||
| 	cc, err := grpc.DialContext(dialCtx, addr, opts...) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -184,7 +185,6 @@ func (p *pool) release(addr string, conn *poolConn, err error) { | ||||
| 		sp.idle++ | ||||
| 	} | ||||
| 	p.Unlock() | ||||
| 	return | ||||
| } | ||||
|  | ||||
| func (conn *poolConn) Close() { | ||||
|   | ||||
| @@ -7,7 +7,6 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"google.golang.org/grpc" | ||||
| 	pgrpc "google.golang.org/grpc" | ||||
| 	pb "google.golang.org/grpc/examples/helloworld/helloworld" | ||||
| ) | ||||
|  | ||||
| @@ -19,7 +18,7 @@ func testPool(t *testing.T, size int, ttl time.Duration, idle int, ms int) { | ||||
| 	} | ||||
| 	defer l.Close() | ||||
|  | ||||
| 	s := pgrpc.NewServer() | ||||
| 	s := grpc.NewServer() | ||||
| 	pb.RegisterGreeterServer(s, &greeterServer{}) | ||||
|  | ||||
| 	go s.Serve(l) | ||||
| @@ -30,7 +29,7 @@ func testPool(t *testing.T, size int, ttl time.Duration, idle int, ms int) { | ||||
|  | ||||
| 	for i := 0; i < 10; i++ { | ||||
| 		// get a conn | ||||
| 		cc, err := p.getConn(l.Addr().String(), grpc.WithInsecure()) | ||||
| 		cc, err := p.getConn(context.TODO(), l.Addr().String(), grpc.WithInsecure()) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
|   | ||||
| @@ -14,12 +14,12 @@ type grpcStream struct { | ||||
| 	sync.RWMutex | ||||
| 	closed   bool | ||||
| 	err      error | ||||
| 	conn     *grpc.ClientConn | ||||
| 	stream   grpc.ClientStream | ||||
| 	request  client.Request | ||||
| 	response client.Response | ||||
| 	context  context.Context | ||||
| 	cancel   func() | ||||
| 	release  func(error) | ||||
| } | ||||
|  | ||||
| func (g *grpcStream) Context() context.Context { | ||||
| @@ -43,15 +43,11 @@ func (g *grpcStream) Send(msg interface{}) error { | ||||
| } | ||||
|  | ||||
| func (g *grpcStream) Recv(msg interface{}) (err error) { | ||||
| 	defer g.setError(err) | ||||
| 	if err = g.stream.RecvMsg(msg); err != nil { | ||||
| 		// #202 - inconsistent gRPC stream behavior | ||||
| 		// the only way to tell if the stream is done is when we get a EOF on the Recv | ||||
| 		// here we should close the underlying gRPC ClientConn | ||||
| 		closeErr := g.Close() | ||||
| 		if err == io.EOF && closeErr != nil { | ||||
| 			err = closeErr | ||||
| 		if err != io.EOF { | ||||
| 			g.setError(err) | ||||
| 		} | ||||
| 		return err | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @@ -68,11 +64,10 @@ func (g *grpcStream) setError(e error) { | ||||
| 	g.Unlock() | ||||
| } | ||||
|  | ||||
| // Close the gRPC send stream | ||||
| // #202 - inconsistent gRPC stream behavior | ||||
| // The underlying gRPC stream should not be closed here since the | ||||
| // stream should still be able to receive after this function call | ||||
| // TODO: should the conn be closed in another way? | ||||
| func (g *grpcStream) CloseSend() error { | ||||
| 	return g.stream.CloseSend() | ||||
| } | ||||
|  | ||||
| func (g *grpcStream) Close() error { | ||||
| 	g.Lock() | ||||
| 	defer g.Unlock() | ||||
| @@ -83,6 +78,7 @@ func (g *grpcStream) Close() error { | ||||
| 	// cancel the context | ||||
| 	g.cancel() | ||||
| 	g.closed = true | ||||
| 	g.stream.CloseSend() | ||||
| 	return g.conn.Close() | ||||
| 	// release back to pool | ||||
| 	g.release(g.err) | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -120,6 +120,10 @@ func (h *httpStream) Error() error { | ||||
| 	return h.err | ||||
| } | ||||
|  | ||||
| func (h *httpStream) CloseSend() error { | ||||
| 	return errors.New("streamer not implemented") | ||||
| } | ||||
|  | ||||
| func (h *httpStream) Close() error { | ||||
| 	select { | ||||
| 	case <-h.closed: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user