From dfc882661633530e33ab5cd0ac160b7081323079 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Thu, 30 Mar 2017 17:07:23 -0700 Subject: [PATCH 01/15] Add default timeout for tcahnnel client request --- examples/example-gateway/clients/baz/baz.go | 38 ++++++++++++++++--- .../example-gateway/config/production.json | 1 + 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/examples/example-gateway/clients/baz/baz.go b/examples/example-gateway/clients/baz/baz.go index 22f9d3c8f..ddeb85d99 100644 --- a/examples/example-gateway/clients/baz/baz.go +++ b/examples/example-gateway/clients/baz/baz.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "strconv" + "time" "github.com/uber-go/zap" "github.com/uber/tchannel-go" @@ -34,9 +35,9 @@ type BazClient struct { // NewClient returns a new http client for service Bar. func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazClient { - // TODO: (lu) get clientName from config - // clientName := config.MustGetString("clients.baz.clientName") + // TODO: (lu) get clientName and serviceName from client config clientName := "BazClient" + serviceName := "SimpleService" // TODO: (lu) client channel opts ch, err := tchannel.NewChannel(clientName, nil) @@ -45,19 +46,20 @@ func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazCli zap.String("error", err.Error())) } + // TODO: (lu) client connection type ip := config.MustGetString("clients.SimpleService.ip") port := config.MustGetInt("clients.SimpleService.port") ch.Peers().Add(ip + ":" + strconv.Itoa(int(port))) - // TODO: (lu) get serviceName from config - // serviceName := config.MustGetString("clients.baz.serviceName") - serviceName := "SimpleService" client := zt.NewClient(ch, serviceName) + timeout := time.Duration(config.MustGetInt("clients.SimpleService.timeout")) * time.Millisecond + return &BazClient{ SimpleServiceClient{ thriftService: serviceName, client: client, + timeout: timeout, }, } } @@ -66,11 +68,21 @@ func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazCli type SimpleServiceClient struct { thriftService string client zt.TChanClient + // timeout is the default timeout if upstream does not have one + timeout time.Duration } // Call ... func (c *SimpleServiceClient) Call(ctx context.Context, reqHeaders map[string]string, args *baz.SimpleService_Call_Args) (map[string]string, *baz.BazResponse, error) { var result baz.SimpleService_Call_Result + + _, ok := ctx.Deadline() + if !ok { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.timeout) + defer cancel() + } + respHeaders, success, err := c.client.Call(ctx, c.thriftService, "Call", reqHeaders, args, &result) if err == nil && !success { err = errors.New("received no result or unknown exception for Call") @@ -87,6 +99,14 @@ func (c *SimpleServiceClient) Call(ctx context.Context, reqHeaders map[string]st // Simple ... func (c *SimpleServiceClient) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { var result baz.SimpleService_Simple_Result + + _, ok := ctx.Deadline() + if !ok { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.timeout) + defer cancel() + } + args := baz.SimpleService_Simple_Args{} respHeaders, success, err := c.client.Call(ctx, c.thriftService, "Simple", reqHeaders, &args, &result) if err == nil && !success { @@ -104,6 +124,14 @@ func (c *SimpleServiceClient) Simple(ctx context.Context, reqHeaders map[string] // SimpleFuture ... func (c *SimpleServiceClient) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { var result baz.SimpleService_SimpleFuture_Result + + _, ok := ctx.Deadline() + if !ok { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, c.timeout) + defer cancel() + } + args := baz.SimpleService_SimpleFuture_Args{} respHeaders, success, err := c.client.Call(ctx, c.thriftService, "SimpleFuture", reqHeaders, &args, &result) if err == nil && !success { diff --git a/examples/example-gateway/config/production.json b/examples/example-gateway/config/production.json index 8991ce038..612c77f59 100644 --- a/examples/example-gateway/config/production.json +++ b/examples/example-gateway/config/production.json @@ -22,6 +22,7 @@ "clients.SimpleService.port": 4002, "clients.SimpleService.ip": "127.0.0.1", + "clients.SimpleService.timeout": 1000, "clients.googleNowTChannel.connectionType": "p2p", "clients.googleNowTChannel.hostList": [ From 3451b2881bae37f75ca0b137eb7fe55729fe6f48 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Thu, 30 Mar 2017 17:08:47 -0700 Subject: [PATCH 02/15] Add baz endpoints --- .../baz/baz_simpleservice_method_call.go | 66 +++++++++++++ .../baz/baz_simpleservice_method_simple.go | 48 +++++++++ .../baz_simpleservice_method_simplefuture.go | 49 +++++++++ .../endpoints/baz/baz_structs.go | 22 +++++ .../endpoints/baz/baz_structs_easyjson.go | 99 +++++++++++++++++++ 5 files changed, 284 insertions(+) create mode 100644 examples/example-gateway/endpoints/baz/baz_simpleservice_method_call.go create mode 100644 examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go create mode 100644 examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go create mode 100644 examples/example-gateway/endpoints/baz/baz_structs.go create mode 100644 examples/example-gateway/endpoints/baz/baz_structs_easyjson.go diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call.go new file mode 100644 index 000000000..e8e7982bc --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call.go @@ -0,0 +1,66 @@ +// Code generated by zanzibar +// @generated +// TODO: (lu) to be generated + +package baz + +import ( + "context" + + "github.com/pkg/errors" + "github.com/uber-go/zap" + "github.com/uber/zanzibar/examples/example-gateway/build/clients" + zanzibar "github.com/uber/zanzibar/runtime" + + clientTypeBaz "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" + "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/endpoints/baz/baz" +) + +// HandleCallRequest handles "/baz/call-path". +func HandleCallRequest( + ctx context.Context, + req *zanzibar.ServerHTTPRequest, + res *zanzibar.ServerHTTPResponse, + clients *clients.Clients, +) { + // Handle request headers. + //h := http.Header{} + var clientReqHeaders map[string]string + + // Handle request body. + var body CallHTTPRequest + if ok := req.ReadAndUnmarshalBody(&body); !ok { + return + } + clientRequest := convertToCallClientRequest(&body) + + // TODO: (lu) deal response headers + _, clientResp, err := clients.Baz.Call(ctx, clientReqHeaders, clientRequest) + if err != nil { + switch err.(type) { + default: + req.Logger.Error("Client request returned unexpected error", + zap.String("error", err.Error()), + ) + res.SendError(500, errors.Wrap(err, "could not make client request:")) + return + } + } + + response := convertCallClientResponse(clientResp) + + // TODO: (lu) decide response status code + statusCode := 200 + res.WriteJSON(statusCode, response) +} + +func convertToCallClientRequest(body *CallHTTPRequest) *clientTypeBaz.SimpleService_Call_Args { + clientRequest := &clientTypeBaz.SimpleService_Call_Args{} + clientRequest.Arg = (*clientTypeBaz.BazRequest)(body.Arg) + + return clientRequest +} +func convertCallClientResponse(body *clientTypeBaz.BazResponse) *baz.BazResponse { + response := (*baz.BazResponse)(body) + return response +} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go new file mode 100644 index 000000000..302cd0ebe --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go @@ -0,0 +1,48 @@ +// Code generated by zanzibar +// @generated +// TODO: (lu) to be generated + +package baz + +import ( + "context" + + "github.com/pkg/errors" + "github.com/uber-go/zap" + "github.com/uber/zanzibar/examples/example-gateway/build/clients" + zanzibar "github.com/uber/zanzibar/runtime" + + "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" +) + +// HandleSimpleRequest handles "/baz/simple-path". +func HandleSimpleRequest( + ctx context.Context, + req *zanzibar.ServerHTTPRequest, + res *zanzibar.ServerHTTPResponse, + clients *clients.Clients, +) { + // Handle request headers. + //h := http.Header{} + var clientReqHeaders map[string]string + + // TODO: (lu) deal response headers + _, err := clients.Baz.Simple(ctx, clientReqHeaders) + if err != nil { + switch err.(type) { + case *baz.SimpleErr: + res.SendError(400, errors.Wrap(err, "simple error")) + default: + req.Logger.Error("Client request returned error", + zap.String("error", err.Error()), + ) + res.SendError(500, errors.Wrap(err, "could not make client request:")) + } + return + } + + // TODO: (lu) convert rpc response to http response status code + statusCode := 200 + // TODO: (lu) empty response? + res.WriteJSON(statusCode, nil) +} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go new file mode 100644 index 000000000..6aec43b83 --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go @@ -0,0 +1,49 @@ +// Code generated by zanzibar +// @generated +// TODO: (lu) to be generated + +package baz + +import ( + "context" + + "github.com/pkg/errors" + "github.com/uber-go/zap" + "github.com/uber/zanzibar/examples/example-gateway/build/clients" + zanzibar "github.com/uber/zanzibar/runtime" + + "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" +) + +// HandleSimpleFutureRequest handles "/baz/simple-future-path". +func HandleSimpleFutureRequest( + ctx context.Context, + req *zanzibar.ServerHTTPRequest, + res *zanzibar.ServerHTTPResponse, + clients *clients.Clients, +) { + // Handle request headers. + //h := http.Header{} + var clientReqHeaders map[string]string + + _, err := clients.Baz.SimpleFuture(ctx, clientReqHeaders) + + if err != nil { + switch err.(type) { + case *baz.SimpleErr: + res.SendError(400, errors.Wrap(err, "simple error")) + case *baz.NewErr: + res.SendError(400, errors.Wrap(err, "new error")) + default: + req.Logger.Error("Client request returned error", + zap.String("error", err.Error()), + ) + res.SendError(500, errors.Wrap(err, "could not make client request:")) + } + return + } + + // TODO: (lu) convert rpc response to http response status code + statusCode := 200 + res.WriteJSON(statusCode, nil) +} diff --git a/examples/example-gateway/endpoints/baz/baz_structs.go b/examples/example-gateway/endpoints/baz/baz_structs.go new file mode 100644 index 000000000..ab997b3ef --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_structs.go @@ -0,0 +1,22 @@ +// Code generated by zanzibar +// @generated +// TODO: (lu) generate + +package baz + +import ( + "runtime" + + "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/endpoints/baz/baz" + "github.com/uber/zanzibar/runtime" +) + +func getDirName() string { + _, file, _, _ := runtime.Caller(0) + return zanzibar.GetDirnameFromRuntimeCaller(file) +} + +// CallHTTPRequest is the http body type for endpoint call. +type CallHTTPRequest struct { + Arg *baz.BazRequest +} diff --git a/examples/example-gateway/endpoints/baz/baz_structs_easyjson.go b/examples/example-gateway/endpoints/baz/baz_structs_easyjson.go new file mode 100644 index 000000000..603582424 --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_structs_easyjson.go @@ -0,0 +1,99 @@ +// AUTOGENERATED FILE: easyjson marshaller/unmarshallers. + +package baz + +import ( + json "encoding/json" + easyjson "github.com/mailru/easyjson" + jlexer "github.com/mailru/easyjson/jlexer" + jwriter "github.com/mailru/easyjson/jwriter" + baz "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/endpoints/baz/baz" +) + +// suppress unused package warning +var ( + _ *json.RawMessage + _ *jlexer.Lexer + _ *jwriter.Writer + _ easyjson.Marshaler +) + +func easyjson62ef335aDecodeGithubComUberZanzibarExamplesExampleGatewayBuildEndpointsBaz(in *jlexer.Lexer, out *CallHTTPRequest) { + isTopLevel := in.IsStart() + if in.IsNull() { + if isTopLevel { + in.Consumed() + } + in.Skip() + return + } + in.Delim('{') + for !in.IsDelim('}') { + key := in.UnsafeString() + in.WantColon() + if in.IsNull() { + in.Skip() + in.WantComma() + continue + } + switch key { + case "Arg": + if in.IsNull() { + in.Skip() + out.Arg = nil + } else { + if out.Arg == nil { + out.Arg = new(baz.BazRequest) + } + (*out.Arg).UnmarshalEasyJSON(in) + } + default: + in.SkipRecursive() + } + in.WantComma() + } + in.Delim('}') + if isTopLevel { + in.Consumed() + } +} +func easyjson62ef335aEncodeGithubComUberZanzibarExamplesExampleGatewayBuildEndpointsBaz(out *jwriter.Writer, in CallHTTPRequest) { + out.RawByte('{') + first := true + _ = first + if !first { + out.RawByte(',') + } + first = false + out.RawString("\"Arg\":") + if in.Arg == nil { + out.RawString("null") + } else { + (*in.Arg).MarshalEasyJSON(out) + } + out.RawByte('}') +} + +// MarshalJSON supports json.Marshaler interface +func (v CallHTTPRequest) MarshalJSON() ([]byte, error) { + w := jwriter.Writer{} + easyjson62ef335aEncodeGithubComUberZanzibarExamplesExampleGatewayBuildEndpointsBaz(&w, v) + return w.Buffer.BuildBytes(), w.Error +} + +// MarshalEasyJSON supports easyjson.Marshaler interface +func (v CallHTTPRequest) MarshalEasyJSON(w *jwriter.Writer) { + easyjson62ef335aEncodeGithubComUberZanzibarExamplesExampleGatewayBuildEndpointsBaz(w, v) +} + +// UnmarshalJSON supports json.Unmarshaler interface +func (v *CallHTTPRequest) UnmarshalJSON(data []byte) error { + r := jlexer.Lexer{Data: data} + easyjson62ef335aDecodeGithubComUberZanzibarExamplesExampleGatewayBuildEndpointsBaz(&r, v) + return r.Error() +} + +// UnmarshalEasyJSON supports easyjson.Unmarshaler interface +func (v *CallHTTPRequest) UnmarshalEasyJSON(l *jlexer.Lexer) { + easyjson62ef335aDecodeGithubComUberZanzibarExamplesExampleGatewayBuildEndpointsBaz(l, v) +} From 74d5eb3ea0711da9dfa96269e241545fff34d82f Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Thu, 30 Mar 2017 22:33:26 -0700 Subject: [PATCH 03/15] Temporarily register baz endpoints manually --- codegen/templates/endpoint_register.tmpl | 35 +++++++++++++++++++ .../build/endpoints/register.go | 34 ++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/codegen/templates/endpoint_register.tmpl b/codegen/templates/endpoint_register.tmpl index 9b7cc3514..165a2782a 100644 --- a/codegen/templates/endpoint_register.tmpl +++ b/codegen/templates/endpoint_register.tmpl @@ -12,6 +12,9 @@ import ( {{end}} "github.com/uber/zanzibar/runtime" + + // TODO: (lu) remove this, to be generated + "github.com/uber/zanzibar/examples/example-gateway/endpoints/baz" ) type handlerFn func( @@ -88,4 +91,36 @@ func Register(g *zanzibar.Gateway, router *zanzibar.Router) { ), ) {{end}} + + // TODO: (lu) remove below, to be generated + router.Register( + "POST", "/baz/call-path", + makeEndpoint( + g, + "baz", + "call", + nil, + baz.HandleCallRequest, + ), + ) + router.Register( + "GET", "/baz/simple-path", + makeEndpoint( + g, + "baz", + "simple", + nil, + baz.HandleSimpleRequest, + ), + ) + router.Register( + "GET", "/baz/simple-future-path", + makeEndpoint( + g, + "baz", + "simpleFuture", + nil, + baz.HandleSimpleFutureRequest, + ), + ) } diff --git a/examples/example-gateway/build/endpoints/register.go b/examples/example-gateway/build/endpoints/register.go index b0a9f09af..4c6b96812 100644 --- a/examples/example-gateway/build/endpoints/register.go +++ b/examples/example-gateway/build/endpoints/register.go @@ -14,6 +14,9 @@ import ( "github.com/uber/zanzibar/runtime/middlewares/logger" "github.com/uber/zanzibar/runtime" + + // TODO: (lu) remove this, to be generated + "github.com/uber/zanzibar/examples/example-gateway/endpoints/baz" ) type handlerFn func( @@ -154,4 +157,35 @@ func Register(g *zanzibar.Gateway, router *zanzibar.Router) { ), ) + // TODO: (lu) remove below, to be generated + router.Register( + "POST", "/baz/call-path", + makeEndpoint( + g, + "baz", + "call", + nil, + baz.HandleCallRequest, + ), + ) + router.Register( + "GET", "/baz/simple-path", + makeEndpoint( + g, + "baz", + "simple", + nil, + baz.HandleSimpleRequest, + ), + ) + router.Register( + "GET", "/baz/simple-future-path", + makeEndpoint( + g, + "baz", + "simpleFuture", + nil, + baz.HandleSimpleFutureRequest, + ), + ) } From 713a2f547675c82647a74ecd883254925af42617 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Thu, 30 Mar 2017 22:34:45 -0700 Subject: [PATCH 04/15] Add baz server handler struct --- examples/example-gateway/clients/baz/baz.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/example-gateway/clients/baz/baz.go b/examples/example-gateway/clients/baz/baz.go index ddeb85d99..4cb229fe9 100644 --- a/examples/example-gateway/clients/baz/baz.go +++ b/examples/example-gateway/clients/baz/baz.go @@ -263,3 +263,16 @@ func (s *SimpleServiceServer) handleSimpleFuture(ctx context.Context, reqHeaders return err == nil, respHeaders, &res, nil } + +type Handler struct{} + +func (h *Handler) Call(ctx context.Context, reqHeaders map[string]string, r *baz.SimpleService_Call_Args) (map[string]string, *baz.BazResponse, error) { + return nil, nil, errors.New("not implemented") +} + +func (h *Handler) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { + return nil, errors.New("not implemented") +} +func (h *Handler) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { + return nil, errors.New("not implemented") +} From 5890963398345ce367c8be262a3f28c1b7612e9e Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Thu, 30 Mar 2017 22:35:34 -0700 Subject: [PATCH 05/15] Fix baz endpoints for empty response body case --- .../endpoints/baz/baz_simpleservice_method_simple.go | 3 +-- .../endpoints/baz/baz_simpleservice_method_simplefuture.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go index 302cd0ebe..3a2d66caf 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple.go @@ -43,6 +43,5 @@ func HandleSimpleRequest( // TODO: (lu) convert rpc response to http response status code statusCode := 200 - // TODO: (lu) empty response? - res.WriteJSON(statusCode, nil) + res.WriteJSONBytes(statusCode, nil) } diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go index 6aec43b83..d0927ece6 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simplefuture.go @@ -45,5 +45,5 @@ func HandleSimpleFutureRequest( // TODO: (lu) convert rpc response to http response status code statusCode := 200 - res.WriteJSON(statusCode, nil) + res.WriteJSONBytes(statusCode, nil) } From d6f16b840dc0cdd25b5dbd31b268aac8d79d8a18 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Thu, 30 Mar 2017 23:51:54 -0700 Subject: [PATCH 06/15] Add baz endpoint tests --- examples/example-gateway/clients/baz/baz.go | 5 + .../baz/baz_simpleservice_method_call_test.go | 96 +++++++++++++++++++ ...simpleservice_method_simple_future_test.go | 85 ++++++++++++++++ .../baz_simpleservice_method_simple_test.go | 83 ++++++++++++++++ 4 files changed, 269 insertions(+) create mode 100644 examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go create mode 100644 examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go create mode 100644 examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go diff --git a/examples/example-gateway/clients/baz/baz.go b/examples/example-gateway/clients/baz/baz.go index 4cb229fe9..f9a87b183 100644 --- a/examples/example-gateway/clients/baz/baz.go +++ b/examples/example-gateway/clients/baz/baz.go @@ -264,15 +264,20 @@ func (s *SimpleServiceServer) handleSimpleFuture(ctx context.Context, reqHeaders return err == nil, respHeaders, &res, nil } +// Handler is intended as the base struct for testing type Handler struct{} +// Call is to be implemented by a struct that embeds Handler func (h *Handler) Call(ctx context.Context, reqHeaders map[string]string, r *baz.SimpleService_Call_Args) (map[string]string, *baz.BazResponse, error) { return nil, nil, errors.New("not implemented") } +// Simple is to be implemented by a struct that embeds Handler func (h *Handler) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { return nil, errors.New("not implemented") } + +// SimpleFuture is to be implemented by a struct that embeds Handler func (h *Handler) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { return nil, errors.New("not implemented") } diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go new file mode 100644 index 000000000..7af132474 --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go @@ -0,0 +1,96 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// TODO: (lu) to be generated + +package baz + +import ( + "bytes" + "context" + "io/ioutil" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/uber/zanzibar/test/lib/test_gateway" + + "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" + bazServer "github.com/uber/zanzibar/examples/example-gateway/clients/baz" +) + +var testCallCounter int + +type testCallHandler struct { + *bazServer.Handler +} + +func (h *testCallHandler) Call( + ctx context.Context, reqHeaders map[string]string, r *baz.SimpleService_Call_Args, +) (map[string]string, *baz.BazResponse, error) { + testCallCounter++ + var resp *baz.BazResponse + if r.Arg.B1 && r.Arg.S2 == "hello" && r.Arg.I3 == 42 { + resp = &baz.BazResponse{ + Message: "yo", + } + } + return nil, resp, nil + +} + +func TestCallSuccessfulRequestOKResponse(t *testing.T) { + gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{ + KnownTChannelBackends: []string{"SimpleService"}, + TestBinary: filepath.Join( + getDirName(), "..", "..", "build", "main.go", + ), + }) + if !assert.NoError(t, err, "got bootstrap err") { + return + } + defer gateway.Close() + + server := bazServer.NewSimpleServiceServer(&testCallHandler{}) + gateway.TChannelBackends()["SimpleService"].Register(server) + + headers := map[string]string{} + + res, err := gateway.MakeRequest( + "POST", + "/baz/call-path", + headers, + bytes.NewReader([]byte(`{"Arg":{"b1":true,"s2":"hello","i3":42}}`)), + ) + + if !assert.NoError(t, err, "got http error") { + return + } + + defer func() { _ = res.Body.Close() }() + data, err := ioutil.ReadAll(res.Body) + if !assert.NoError(t, err, "failed to read response body") { + return + } + + assert.Equal(t, 1, testCallCounter) + assert.Equal(t, "200 OK", res.Status) + assert.Equal(t, `{"message":"yo"}`, string(data)) +} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go new file mode 100644 index 000000000..1f51a65d2 --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go @@ -0,0 +1,85 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// TODO: (lu) to be generated + +package baz + +import ( + "bytes" + "context" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/uber/zanzibar/test/lib/test_gateway" + + bazServer "github.com/uber/zanzibar/examples/example-gateway/clients/baz" +) + +var testSimpleFutureCounter int + +type testSimpleFutureHandler struct { + *bazServer.Handler +} + +func (h *testSimpleFutureHandler) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { + testSimpleFutureCounter++ + return nil, nil + +} + +func TestSimpleFutureSuccessfulRequestOKResponse(t *testing.T) { + gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{ + KnownTChannelBackends: []string{"SimpleService"}, + TestBinary: filepath.Join( + getDirName(), "..", "..", "build", "main.go", + ), + }) + if !assert.NoError(t, err, "got bootstrap err") { + return + } + defer gateway.Close() + + testSimpleFutureCounter = 0 + + server := bazServer.NewSimpleServiceServer(&testSimpleFutureHandler{}) + gateway.TChannelBackends()["SimpleService"].Register(server) + + headers := map[string]string{} + + res, err := gateway.MakeRequest( + "GET", + "/baz/simple-future-path", + headers, + bytes.NewReader([]byte(`{}`)), + ) + + if !assert.NoError(t, err, "got http error") { + return + } + + if !assert.NoError(t, err, "failed to read response body") { + return + } + + assert.Equal(t, 1, testSimpleFutureCounter) + assert.Equal(t, "200 OK", res.Status) +} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go new file mode 100644 index 000000000..c86710bfa --- /dev/null +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go @@ -0,0 +1,83 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// TODO: (lu) to be generated + +package baz + +import ( + "bytes" + "context" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/uber/zanzibar/test/lib/test_gateway" + + bazServer "github.com/uber/zanzibar/examples/example-gateway/clients/baz" +) + +var testSimpleCounter int + +type testSimpleHandler struct { + *bazServer.Handler +} + +func (h *testSimpleHandler) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { + testSimpleCounter++ + return nil, nil + +} + +func TestSimpleSuccessfulRequestOKResponse(t *testing.T) { + gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{ + KnownTChannelBackends: []string{"SimpleService"}, + TestBinary: filepath.Join( + getDirName(), "..", "..", "build", "main.go", + ), + }) + if !assert.NoError(t, err, "got bootstrap err") { + return + } + defer gateway.Close() + + server := bazServer.NewSimpleServiceServer(&testSimpleHandler{}) + gateway.TChannelBackends()["SimpleService"].Register(server) + + headers := map[string]string{} + + res, err := gateway.MakeRequest( + "GET", + "/baz/simple-path", + headers, + bytes.NewReader([]byte(`{}`)), + ) + + if !assert.NoError(t, err, "got http error") { + return + } + + if !assert.NoError(t, err, "failed to read response body") { + return + } + + assert.Equal(t, 1, testSimpleCounter) + assert.Equal(t, "200 OK", res.Status) +} From 1b1ee49ac338bdcf41ba1270df353a7c13b49552 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 14:27:55 -0700 Subject: [PATCH 07/15] Fix merge conflict leftover --- examples/example-gateway/clients/baz/baz.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example-gateway/clients/baz/baz.go b/examples/example-gateway/clients/baz/baz.go index e2f91078d..d3b06d4da 100644 --- a/examples/example-gateway/clients/baz/baz.go +++ b/examples/example-gateway/clients/baz/baz.go @@ -36,7 +36,7 @@ func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazCli client := zt.NewClient(gateway.Channel, serviceName) - timeout := time.Duration(config.MustGetInt("clients.SimpleService.timeout")) * time.Millisecond + timeout := time.Duration(config.MustGetInt("clients.baz.timeout")) * time.Millisecond return &BazClient{ thriftService: serviceName, From 294251271d9977f709eb59ba1db37185d1442ef3 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 16:45:14 -0700 Subject: [PATCH 08/15] Make config in production.json consistent --- .../baz/baz_simpleservice_method_call_test.go | 4 ++-- .../baz_simpleservice_method_simple_future_test.go | 4 ++-- .../baz/baz_simpleservice_method_simple_test.go | 4 ++-- test/lib/test_backend/test_tchannel_backend.go | 14 ++++++++++---- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go index 7af132474..c04c9d5e9 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go @@ -58,7 +58,7 @@ func (h *testCallHandler) Call( func TestCallSuccessfulRequestOKResponse(t *testing.T) { gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{ - KnownTChannelBackends: []string{"SimpleService"}, + KnownTChannelBackends: []string{"baz"}, TestBinary: filepath.Join( getDirName(), "..", "..", "build", "main.go", ), @@ -69,7 +69,7 @@ func TestCallSuccessfulRequestOKResponse(t *testing.T) { defer gateway.Close() server := bazServer.NewSimpleServiceServer(&testCallHandler{}) - gateway.TChannelBackends()["SimpleService"].Register(server) + gateway.TChannelBackends()["baz"].Register(server) headers := map[string]string{} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go index 1f51a65d2..8fe7b3f7e 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go @@ -48,7 +48,7 @@ func (h *testSimpleFutureHandler) SimpleFuture(ctx context.Context, reqHeaders m func TestSimpleFutureSuccessfulRequestOKResponse(t *testing.T) { gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{ - KnownTChannelBackends: []string{"SimpleService"}, + KnownTChannelBackends: []string{"baz"}, TestBinary: filepath.Join( getDirName(), "..", "..", "build", "main.go", ), @@ -61,7 +61,7 @@ func TestSimpleFutureSuccessfulRequestOKResponse(t *testing.T) { testSimpleFutureCounter = 0 server := bazServer.NewSimpleServiceServer(&testSimpleFutureHandler{}) - gateway.TChannelBackends()["SimpleService"].Register(server) + gateway.TChannelBackends()["baz"].Register(server) headers := map[string]string{} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go index c86710bfa..e31bc14ba 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go @@ -48,7 +48,7 @@ func (h *testSimpleHandler) Simple(ctx context.Context, reqHeaders map[string]st func TestSimpleSuccessfulRequestOKResponse(t *testing.T) { gateway, err := testGateway.CreateGateway(t, nil, &testGateway.Options{ - KnownTChannelBackends: []string{"SimpleService"}, + KnownTChannelBackends: []string{"baz"}, TestBinary: filepath.Join( getDirName(), "..", "..", "build", "main.go", ), @@ -59,7 +59,7 @@ func TestSimpleSuccessfulRequestOKResponse(t *testing.T) { defer gateway.Close() server := bazServer.NewSimpleServiceServer(&testSimpleHandler{}) - gateway.TChannelBackends()["SimpleService"].Register(server) + gateway.TChannelBackends()["baz"].Register(server) headers := map[string]string{} diff --git a/test/lib/test_backend/test_tchannel_backend.go b/test/lib/test_backend/test_tchannel_backend.go index 33d1feb0e..f7ea7c21e 100644 --- a/test/lib/test_backend/test_tchannel_backend.go +++ b/test/lib/test_backend/test_tchannel_backend.go @@ -47,8 +47,14 @@ func BuildTChannelBackends( n := len(knownTChannelBackends) result := make(map[string]*TestTChannelBackend, n) + var clientName, serviceName string for i := 0; i < n; i++ { - serviceName := knownTChannelBackends[i] + clientName = knownTChannelBackends[i] + + // TODO: (lu) tmp, get backend thrift service name from config + if clientName == "baz" { + serviceName = "SimpleService" + } backend, err := CreateTChannelBackend(0, serviceName) if err != nil { return nil, err @@ -59,9 +65,9 @@ func BuildTChannelBackends( return nil, err } - result[serviceName] = backend - cfg["clients."+serviceName+".ip"] = "127.0.0.1" - cfg["clients."+serviceName+".port"] = int64(backend.RealPort) + result[clientName] = backend + cfg["clients."+clientName+".ip"] = "127.0.0.1" + cfg["clients."+clientName+".port"] = int64(backend.RealPort) } return result, nil From 946ef781657a317c4b8ac93c60ec478454375382 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 16:46:16 -0700 Subject: [PATCH 09/15] Merge runtime/tchannel_server.go into runtime/tchannel/server.go --- runtime/gateway.go | 32 +++++++++++++---- runtime/tchannel_server.go | 74 -------------------------------------- 2 files changed, 25 insertions(+), 81 deletions(-) delete mode 100644 runtime/tchannel_server.go diff --git a/runtime/gateway.go b/runtime/gateway.go index 320892079..873a2a581 100644 --- a/runtime/gateway.go +++ b/runtime/gateway.go @@ -356,17 +356,35 @@ func (gateway *Gateway) setupHTTPServer() error { } func (gateway *Gateway) setupTChannel(config *StaticConfig) error { - tchannelServer, err := NewTChannelServer( - &TChannelServerOptions{ - ServiceName: config.MustGetString("tchannel.serviceName"), - ProcessName: config.MustGetString("tchannel.processName"), - }, gateway) + serviceName := config.MustGetString("tchannel.serviceName") + processName := config.MustGetString("tchannel.processName") + + channel, err := tchannel.NewChannel( + serviceName, + &tchannel.ChannelOptions{ + ProcessName: processName, + + //DefaultConnectionOptions: opts.DefaultConnectionOptions, + //OnPeerStatusChanged: opts.OnPeerStatusChanged, + //RelayHost: opts.RelayHost, + //RelayLocalHandlers: opts.RelayLocalHandlers, + //RelayMaxTimeout: opts.RelayMaxTimeout, + //StatsReporter: opts.StatsReporter, + //Tracer: + + // TODO: (lu) wrap zap logger with tchannel logger interface + Logger: tchannel.NullLogger, + }) if err != nil { - return err + return errors.Errorf( + "Error creating top channel:\n %s", + err) } - gateway.tchannelServer = tchannelServer + gateway.Channel = channel + gateway.tchannelServer = zt.NewServer(channel, gateway.Logger) + return nil } diff --git a/runtime/tchannel_server.go b/runtime/tchannel_server.go deleted file mode 100644 index 6f26e1b52..000000000 --- a/runtime/tchannel_server.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2017 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -package zanzibar - -import ( - "time" - - "github.com/opentracing/opentracing-go" - "github.com/pkg/errors" - "github.com/uber-go/zap" - "github.com/uber/tchannel-go" - - zt "github.com/uber/zanzibar/runtime/tchannel" -) - -// TChannelServerOptions are used to initialize the TChannel wrapper struct -type TChannelServerOptions struct { - DefaultConnectionOptions tchannel.ConnectionOptions - Logger zap.Logger - OnPeerStatusChanged func(*tchannel.Peer) - ProcessName string - RelayHost tchannel.RelayHost - RelayLocalHandlers []string - RelayMaxTimeout time.Duration - ServiceName string - StatsReporter tchannel.StatsReporter - Tracer opentracing.Tracer -} - -// NewTChannelServer allocates a new TChannel wrapper struct -func NewTChannelServer(opts *TChannelServerOptions, gateway *Gateway) (*zt.Server, error) { - channel, err := tchannel.NewChannel( - opts.ServiceName, - &tchannel.ChannelOptions{ - DefaultConnectionOptions: opts.DefaultConnectionOptions, - OnPeerStatusChanged: opts.OnPeerStatusChanged, - ProcessName: opts.ProcessName, - RelayHost: opts.RelayHost, - RelayLocalHandlers: opts.RelayLocalHandlers, - RelayMaxTimeout: opts.RelayMaxTimeout, - StatsReporter: opts.StatsReporter, - - // TODO: (lu) wrap zap logger with tchannel logger interface - Logger: tchannel.NullLogger, - }) - - if err != nil { - return nil, errors.Errorf( - "Error creating TChannel Server:\n %s", - err) - } - - gateway.Channel = channel - - return zt.NewServer(channel, gateway.Logger), nil -} From b87504b48f2b8d8b75f27827df89ab9021d9786e Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 17:36:30 -0700 Subject: [PATCH 10/15] Set initial timeout for incoming request --- runtime/router.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/runtime/router.go b/runtime/router.go index beec233c1..b5a808bed 100644 --- a/runtime/router.go +++ b/runtime/router.go @@ -24,6 +24,7 @@ import ( "context" "net/http" "strconv" + "time" "github.com/julienschmidt/httprouter" "github.com/uber-go/tally" @@ -163,7 +164,17 @@ func (endpoint *Endpoint) HandleRequest( req := NewServerHTTPRequest(w, r, params, endpoint) fn := endpoint.HandlerFn - fn(r.Context(), req, req.res) + + ctx := r.Context() + _, ok := ctx.Deadline() + if !ok { + var cancel context.CancelFunc + // TODO: (lu) get timeout from endpoint config + ctx, cancel = context.WithTimeout(ctx, time.Duration(100)*time.Millisecond) + defer cancel() + } + + fn(ctx, req, req.res) req.res.flush() } From 4925dce6401547ecbf88478e7638e5225ee708ac Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 17:36:50 -0700 Subject: [PATCH 11/15] Use tchannel contextBuilder to set client timeout options --- examples/example-gateway/clients/baz/baz.go | 51 +++++++++++-------- .../example-gateway/config/production.json | 1 + 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/examples/example-gateway/clients/baz/baz.go b/examples/example-gateway/clients/baz/baz.go index d3b06d4da..180a73549 100644 --- a/examples/example-gateway/clients/baz/baz.go +++ b/examples/example-gateway/clients/baz/baz.go @@ -9,6 +9,7 @@ import ( "strconv" "time" + "github.com/uber/tchannel-go" "github.com/uber/zanzibar/runtime" zt "github.com/uber/zanzibar/runtime/tchannel" @@ -36,12 +37,15 @@ func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazCli client := zt.NewClient(gateway.Channel, serviceName) + // TODO: (lu) maybe set these at per method level timeout := time.Duration(config.MustGetInt("clients.baz.timeout")) * time.Millisecond + timeoutPerAttempt := time.Duration(config.MustGetInt("clients.baz.timeoutPerAttempt")) * time.Millisecond return &BazClient{ - thriftService: serviceName, - client: client, - timeout: timeout, + thriftService: serviceName, + client: client, + timeout: timeout, + timeoutPerAttempt: timeoutPerAttempt, } } @@ -49,20 +53,23 @@ func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazCli type BazClient struct { thriftService string client zt.TChanClient - // timeout is the default timeout if upstream does not have one - timeout time.Duration + + timeout time.Duration + timeoutPerAttempt time.Duration } // Call ... func (c *BazClient) Call(ctx context.Context, reqHeaders map[string]string, args *baz.SimpleService_Call_Args) (map[string]string, *baz.BazResponse, error) { var result baz.SimpleService_Call_Result - _, ok := ctx.Deadline() - if !ok { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, c.timeout) - defer cancel() + retryOpts := &tchannel.RetryOptions{ + TimeoutPerAttempt: c.timeoutPerAttempt, } + ctx, cancel := tchannel.NewContextBuilder(c.timeout). + SetParentContext(ctx). + SetRetryOptions(retryOpts). + Build() + defer cancel() respHeaders, success, err := c.client.Call(ctx, c.thriftService, "Call", reqHeaders, args, &result) if err == nil && !success { @@ -81,12 +88,14 @@ func (c *BazClient) Call(ctx context.Context, reqHeaders map[string]string, args func (c *BazClient) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { var result baz.SimpleService_Simple_Result - _, ok := ctx.Deadline() - if !ok { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, c.timeout) - defer cancel() + retryOpts := &tchannel.RetryOptions{ + TimeoutPerAttempt: c.timeoutPerAttempt, } + ctx, cancel := tchannel.NewContextBuilder(c.timeout). + SetParentContext(ctx). + SetRetryOptions(retryOpts). + Build() + defer cancel() args := baz.SimpleService_Simple_Args{} respHeaders, success, err := c.client.Call(ctx, c.thriftService, "Simple", reqHeaders, &args, &result) @@ -106,12 +115,14 @@ func (c *BazClient) Simple(ctx context.Context, reqHeaders map[string]string) (m func (c *BazClient) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { var result baz.SimpleService_SimpleFuture_Result - _, ok := ctx.Deadline() - if !ok { - var cancel context.CancelFunc - ctx, cancel = context.WithTimeout(ctx, c.timeout) - defer cancel() + retryOpts := &tchannel.RetryOptions{ + TimeoutPerAttempt: c.timeoutPerAttempt, } + ctx, cancel := tchannel.NewContextBuilder(c.timeout). + SetParentContext(ctx). + SetRetryOptions(retryOpts). + Build() + defer cancel() args := baz.SimpleService_SimpleFuture_Args{} respHeaders, success, err := c.client.Call(ctx, c.thriftService, "SimpleFuture", reqHeaders, &args, &result) diff --git a/examples/example-gateway/config/production.json b/examples/example-gateway/config/production.json index 72cf53c08..e44c4e481 100644 --- a/examples/example-gateway/config/production.json +++ b/examples/example-gateway/config/production.json @@ -22,6 +22,7 @@ "clients.baz.port": 4002, "clients.baz.ip": "127.0.0.1", "clients.baz.timeout": 1000, + "clients.baz.timeoutPerAttempt": 1000, "clients.googleNowTChannel.connectionType": "p2p", "clients.googleNowTChannel.hostList": [ From 426a58964d5a7860d402232d68fc092949db2432 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 19:32:18 -0700 Subject: [PATCH 12/15] Register single method during endpoint test --- examples/example-gateway/clients/baz/baz.go | 134 ------------ .../example-gateway/clients/baz/baz_server.go | 191 ++++++++++++++++++ .../baz/baz_simpleservice_method_call_test.go | 9 +- ...simpleservice_method_simple_future_test.go | 9 +- .../baz_simpleservice_method_simple_test.go | 9 +- 5 files changed, 197 insertions(+), 155 deletions(-) create mode 100644 examples/example-gateway/clients/baz/baz_server.go diff --git a/examples/example-gateway/clients/baz/baz.go b/examples/example-gateway/clients/baz/baz.go index 180a73549..479130d02 100644 --- a/examples/example-gateway/clients/baz/baz.go +++ b/examples/example-gateway/clients/baz/baz.go @@ -5,7 +5,6 @@ package bazClient import ( "context" "errors" - "fmt" "strconv" "time" @@ -13,7 +12,6 @@ import ( "github.com/uber/zanzibar/runtime" zt "github.com/uber/zanzibar/runtime/tchannel" - "go.uber.org/thriftrw/wire" "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" ) @@ -139,135 +137,3 @@ func (c *BazClient) SimpleFuture(ctx context.Context, reqHeaders map[string]stri return respHeaders, err } - -// SimpleServiceServer is the Baz backend service -type SimpleServiceServer struct { - handler TChanBaz -} - -// NewSimpleServiceServer wraps a handler for Baz so it can be registered with a thrift server. -func NewSimpleServiceServer(handler TChanBaz) zt.TChanServer { - return &SimpleServiceServer{ - handler, - } -} - -// Service returns the service name. -func (s *SimpleServiceServer) Service() string { - return "SimpleService" -} - -// Methods returns the method names handled by this server. -func (s *SimpleServiceServer) Methods() []string { - return []string{ - "Call", - "Simple", - "SimpleFuture", - } -} - -// Handle dispatches a method call to corresponding handler. -func (s *SimpleServiceServer) Handle(ctx context.Context, methodName string, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { - switch methodName { - case "Call": - return s.handleCall(ctx, reqHeaders, wireValue) - case "Simple": - return s.handleSimple(ctx, reqHeaders, wireValue) - case "SimpleFuture": - return s.handleSimpleFuture(ctx, reqHeaders, wireValue) - - default: - return false, nil, nil, fmt.Errorf("method %v not found in service %v", methodName, s.Service()) - } -} - -func (s *SimpleServiceServer) handleCall(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { - var req baz.SimpleService_Call_Args - var res baz.SimpleService_Call_Result - - if err := req.FromWire(*wireValue); err != nil { - return false, nil, nil, err - } - - respHeaders, r, err := s.handler.Call(ctx, reqHeaders, &req) - - if err != nil { - return false, nil, nil, err - } - - res.Success = r - return true, respHeaders, &res, nil -} - -func (s *SimpleServiceServer) handleSimple(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { - var req baz.SimpleService_Simple_Args - var res baz.SimpleService_Simple_Result - - if err := req.FromWire(*wireValue); err != nil { - return false, nil, nil, err - } - - respHeaders, err := s.handler.Simple(ctx, reqHeaders) - - if err != nil { - switch v := err.(type) { - case *baz.SimpleErr: - if v == nil { - return false, nil, nil, errors.New("Handler for simpleErr returned non-nil error type *SimpleErr but nil value") - } - res.SimpleErr = v - default: - return false, nil, nil, err - } - } - - return err == nil, respHeaders, &res, nil -} - -func (s *SimpleServiceServer) handleSimpleFuture(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { - var req baz.SimpleService_SimpleFuture_Args - var res baz.SimpleService_SimpleFuture_Result - - if err := req.FromWire(*wireValue); err != nil { - return false, nil, nil, err - } - - respHeaders, err := s.handler.SimpleFuture(ctx, reqHeaders) - - if err != nil { - switch v := err.(type) { - case *baz.SimpleErr: - if v == nil { - return false, nil, nil, errors.New("Handler for simpleErr returned non-nil error type *SimpleErr but nil value") - } - res.SimpleErr = v - case *baz.NewErr: - if v == nil { - return false, nil, nil, errors.New("Handler for newErr returned non-nil error type *NewErr_ but nil value") - } - res.NewErr = v - default: - return false, nil, nil, err - } - } - - return err == nil, respHeaders, &res, nil -} - -// Handler is intended as the base struct for testing -type Handler struct{} - -// Call is to be implemented by a struct that embeds Handler -func (h *Handler) Call(ctx context.Context, reqHeaders map[string]string, r *baz.SimpleService_Call_Args) (map[string]string, *baz.BazResponse, error) { - return nil, nil, errors.New("not implemented") -} - -// Simple is to be implemented by a struct that embeds Handler -func (h *Handler) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { - return nil, errors.New("not implemented") -} - -// SimpleFuture is to be implemented by a struct that embeds Handler -func (h *Handler) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { - return nil, errors.New("not implemented") -} diff --git a/examples/example-gateway/clients/baz/baz_server.go b/examples/example-gateway/clients/baz/baz_server.go new file mode 100644 index 000000000..95916e0f9 --- /dev/null +++ b/examples/example-gateway/clients/baz/baz_server.go @@ -0,0 +1,191 @@ +// TODO: (lu) generate + +// TODO: (lu) find a better place for this file + +package bazClient + +import ( + "context" + "errors" + "fmt" + + zt "github.com/uber/zanzibar/runtime/tchannel" + "go.uber.org/thriftrw/wire" + + "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" +) + +// SimpleServiceServer is the Baz backend service +type SimpleServiceServer struct { + handler TChanBaz +} + +// NewSimpleServiceServer wraps a handler for Baz so it can be registered with a thrift server. +func NewSimpleServiceServer(handler TChanBaz) zt.TChanServer { + return &SimpleServiceServer{ + handler, + } +} + +// Service returns the service name. +func (s *SimpleServiceServer) Service() string { + return "SimpleService" +} + +// Methods returns the method names handled by this server. +func (s *SimpleServiceServer) Methods() []string { + return []string{ + "Call", + "Simple", + "SimpleFuture", + } +} + +// Handle dispatches a method call to corresponding handler. +func (s *SimpleServiceServer) Handle(ctx context.Context, methodName string, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { + switch methodName { + case "Call": + return s.handleCall(ctx, reqHeaders, wireValue) + case "Simple": + return s.handleSimple(ctx, reqHeaders, wireValue) + case "SimpleFuture": + return s.handleSimpleFuture(ctx, reqHeaders, wireValue) + + default: + return false, nil, nil, fmt.Errorf("method %v not found in service %v", methodName, s.Service()) + } +} + +func (s *SimpleServiceServer) handleCall(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { + var req baz.SimpleService_Call_Args + var res baz.SimpleService_Call_Result + + if err := req.FromWire(*wireValue); err != nil { + return false, nil, nil, err + } + + respHeaders, r, err := s.handler.Call(ctx, reqHeaders, &req) + + if err != nil { + return false, nil, nil, err + } + + res.Success = r + return true, respHeaders, &res, nil +} + +func (s *SimpleServiceServer) handleSimple(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { + var req baz.SimpleService_Simple_Args + var res baz.SimpleService_Simple_Result + + if err := req.FromWire(*wireValue); err != nil { + return false, nil, nil, err + } + + respHeaders, err := s.handler.Simple(ctx, reqHeaders) + + if err != nil { + switch v := err.(type) { + case *baz.SimpleErr: + if v == nil { + return false, nil, nil, errors.New("Handler for simpleErr returned non-nil error type *SimpleErr but nil value") + } + res.SimpleErr = v + default: + return false, nil, nil, err + } + } + + return err == nil, respHeaders, &res, nil +} + +func (s *SimpleServiceServer) handleSimpleFuture(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { + var req baz.SimpleService_SimpleFuture_Args + var res baz.SimpleService_SimpleFuture_Result + + if err := req.FromWire(*wireValue); err != nil { + return false, nil, nil, err + } + + respHeaders, err := s.handler.SimpleFuture(ctx, reqHeaders) + + if err != nil { + switch v := err.(type) { + case *baz.SimpleErr: + if v == nil { + return false, nil, nil, errors.New("Handler for simpleErr returned non-nil error type *SimpleErr but nil value") + } + res.SimpleErr = v + case *baz.NewErr: + if v == nil { + return false, nil, nil, errors.New("Handler for newErr returned non-nil error type *NewErr_ but nil value") + } + res.NewErr = v + default: + return false, nil, nil, err + } + } + + return err == nil, respHeaders, &res, nil +} + +// CallFunc ... +type CallFunc func(context.Context, map[string]string, *baz.SimpleService_Call_Args) (map[string]string, *baz.BazResponse, error) + +// SimpleFunc ... +type SimpleFunc func(context.Context, map[string]string) (map[string]string, error) + +// SimpleFutureFunc ... +type SimpleFutureFunc func(context.Context, map[string]string) (map[string]string, error) + +// WithCall creates a TChanServer with Call handler function registered +func WithCall(call CallFunc) zt.TChanServer { + return NewSimpleServiceServer(&Handler{ + CallFunc: call, + }) +} + +// WithSimple creates a TChanServer with Simple handler function registered +func WithSimple(simple SimpleFunc) zt.TChanServer { + return NewSimpleServiceServer(&Handler{ + SimpleFunc: simple, + }) +} + +// WithSimpleFuture creates a TChanServer with SimpleFuture handler function registered +func WithSimpleFuture(simpleFuture SimpleFutureFunc) zt.TChanServer { + return NewSimpleServiceServer(&Handler{ + SimpleFutureFunc: simpleFuture, + }) +} + +// Handler is intended as the base struct for testing +type Handler struct { + CallFunc CallFunc + SimpleFunc SimpleFunc + SimpleFutureFunc SimpleFutureFunc +} + +// Call ... +func (h *Handler) Call(ctx context.Context, reqHeaders map[string]string, r *baz.SimpleService_Call_Args) (map[string]string, *baz.BazResponse, error) { + if h.CallFunc == nil { + return nil, nil, errors.New("not implemented") + } + return h.CallFunc(ctx, reqHeaders, r) +} + +// Simple ... +func (h *Handler) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { + if h.SimpleFunc == nil { + return nil, errors.New("not implemented") + } + return h.SimpleFunc(ctx, reqHeaders) +} + +// SimpleFuture ... +func (h *Handler) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { + if h.SimpleFutureFunc == nil { + return nil, errors.New("not implemented") + } + return h.SimpleFutureFunc(ctx, reqHeaders) +} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go index c04c9d5e9..9adde8322 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_call_test.go @@ -38,11 +38,7 @@ import ( var testCallCounter int -type testCallHandler struct { - *bazServer.Handler -} - -func (h *testCallHandler) Call( +func call( ctx context.Context, reqHeaders map[string]string, r *baz.SimpleService_Call_Args, ) (map[string]string, *baz.BazResponse, error) { testCallCounter++ @@ -68,8 +64,7 @@ func TestCallSuccessfulRequestOKResponse(t *testing.T) { } defer gateway.Close() - server := bazServer.NewSimpleServiceServer(&testCallHandler{}) - gateway.TChannelBackends()["baz"].Register(server) + gateway.TChannelBackends()["baz"].Register(bazServer.WithCall(call)) headers := map[string]string{} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go index 8fe7b3f7e..551167268 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go @@ -36,11 +36,7 @@ import ( var testSimpleFutureCounter int -type testSimpleFutureHandler struct { - *bazServer.Handler -} - -func (h *testSimpleFutureHandler) SimpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { +func simpleFuture(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { testSimpleFutureCounter++ return nil, nil @@ -60,8 +56,7 @@ func TestSimpleFutureSuccessfulRequestOKResponse(t *testing.T) { testSimpleFutureCounter = 0 - server := bazServer.NewSimpleServiceServer(&testSimpleFutureHandler{}) - gateway.TChannelBackends()["baz"].Register(server) + gateway.TChannelBackends()["baz"].Register(bazServer.WithSimpleFuture(simpleFuture)) headers := map[string]string{} diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go index e31bc14ba..c3e8d21bc 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go @@ -36,11 +36,7 @@ import ( var testSimpleCounter int -type testSimpleHandler struct { - *bazServer.Handler -} - -func (h *testSimpleHandler) Simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { +func simple(ctx context.Context, reqHeaders map[string]string) (map[string]string, error) { testSimpleCounter++ return nil, nil @@ -58,8 +54,7 @@ func TestSimpleSuccessfulRequestOKResponse(t *testing.T) { } defer gateway.Close() - server := bazServer.NewSimpleServiceServer(&testSimpleHandler{}) - gateway.TChannelBackends()["baz"].Register(server) + gateway.TChannelBackends()["baz"].Register(bazServer.WithSimple(simple)) headers := map[string]string{} From cf7ec90a990ae03cbc548988939e148eabeb527b Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 19:47:55 -0700 Subject: [PATCH 13/15] Move tchannel stuff out into zanzibar runtime --- examples/example-gateway/clients/baz/baz.go | 6 ++--- .../example-gateway/clients/baz/baz_server.go | 18 ++++++------- runtime/gateway.go | 6 ++--- runtime/tchannel/doc.go | 23 ---------------- .../client.go => tchannel_client.go} | 2 +- .../headers.go => tchannel_headers.go} | 2 +- ...aders_test.go => tchannel_headers_test.go} | 2 +- .../helpers.go => tchannel_helpers.go} | 2 +- ...lpers_test.go => tchannel_helpers_test.go} | 2 +- .../interfaces.go => tchannel_interfaces.go} | 2 +- .../server.go => tchannel_server.go} | 26 +++++++++---------- .../lib/test_backend/test_tchannel_backend.go | 8 +++--- 12 files changed, 36 insertions(+), 63 deletions(-) delete mode 100644 runtime/tchannel/doc.go rename runtime/{tchannel/client.go => tchannel_client.go} (99%) rename runtime/{tchannel/headers.go => tchannel_headers.go} (99%) rename runtime/{tchannel/headers_test.go => tchannel_headers_test.go} (99%) rename runtime/{tchannel/helpers.go => tchannel_helpers.go} (99%) rename runtime/{tchannel/helpers_test.go => tchannel_helpers_test.go} (99%) rename runtime/{tchannel/interfaces.go => tchannel_interfaces.go} (99%) rename runtime/{tchannel/server.go => tchannel_server.go} (89%) diff --git a/examples/example-gateway/clients/baz/baz.go b/examples/example-gateway/clients/baz/baz.go index 479130d02..b7dc0d225 100644 --- a/examples/example-gateway/clients/baz/baz.go +++ b/examples/example-gateway/clients/baz/baz.go @@ -11,8 +11,6 @@ import ( "github.com/uber/tchannel-go" "github.com/uber/zanzibar/runtime" - zt "github.com/uber/zanzibar/runtime/tchannel" - "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" ) @@ -33,7 +31,7 @@ func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazCli port := config.MustGetInt("clients.baz.port") sc.Peers().Add(ip + ":" + strconv.Itoa(int(port))) - client := zt.NewClient(gateway.Channel, serviceName) + client := zanzibar.NewClient(gateway.Channel, serviceName) // TODO: (lu) maybe set these at per method level timeout := time.Duration(config.MustGetInt("clients.baz.timeout")) * time.Millisecond @@ -50,7 +48,7 @@ func NewClient(config *zanzibar.StaticConfig, gateway *zanzibar.Gateway) *BazCli // BazClient is the client to talk to SimpleService backend. type BazClient struct { thriftService string - client zt.TChanClient + client zanzibar.TChanClient timeout time.Duration timeoutPerAttempt time.Duration diff --git a/examples/example-gateway/clients/baz/baz_server.go b/examples/example-gateway/clients/baz/baz_server.go index 95916e0f9..bce4cc02f 100644 --- a/examples/example-gateway/clients/baz/baz_server.go +++ b/examples/example-gateway/clients/baz/baz_server.go @@ -9,7 +9,7 @@ import ( "errors" "fmt" - zt "github.com/uber/zanzibar/runtime/tchannel" + "github.com/uber/zanzibar/runtime" "go.uber.org/thriftrw/wire" "github.com/uber/zanzibar/examples/example-gateway/build/gen-code/github.com/uber/zanzibar/clients/baz/baz" @@ -21,7 +21,7 @@ type SimpleServiceServer struct { } // NewSimpleServiceServer wraps a handler for Baz so it can be registered with a thrift server. -func NewSimpleServiceServer(handler TChanBaz) zt.TChanServer { +func NewSimpleServiceServer(handler TChanBaz) zanzibar.TChanServer { return &SimpleServiceServer{ handler, } @@ -42,7 +42,7 @@ func (s *SimpleServiceServer) Methods() []string { } // Handle dispatches a method call to corresponding handler. -func (s *SimpleServiceServer) Handle(ctx context.Context, methodName string, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { +func (s *SimpleServiceServer) Handle(ctx context.Context, methodName string, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zanzibar.RWTStruct, error) { switch methodName { case "Call": return s.handleCall(ctx, reqHeaders, wireValue) @@ -56,7 +56,7 @@ func (s *SimpleServiceServer) Handle(ctx context.Context, methodName string, req } } -func (s *SimpleServiceServer) handleCall(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { +func (s *SimpleServiceServer) handleCall(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zanzibar.RWTStruct, error) { var req baz.SimpleService_Call_Args var res baz.SimpleService_Call_Result @@ -74,7 +74,7 @@ func (s *SimpleServiceServer) handleCall(ctx context.Context, reqHeaders map[str return true, respHeaders, &res, nil } -func (s *SimpleServiceServer) handleSimple(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { +func (s *SimpleServiceServer) handleSimple(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zanzibar.RWTStruct, error) { var req baz.SimpleService_Simple_Args var res baz.SimpleService_Simple_Result @@ -99,7 +99,7 @@ func (s *SimpleServiceServer) handleSimple(ctx context.Context, reqHeaders map[s return err == nil, respHeaders, &res, nil } -func (s *SimpleServiceServer) handleSimpleFuture(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zt.RWTStruct, error) { +func (s *SimpleServiceServer) handleSimpleFuture(ctx context.Context, reqHeaders map[string]string, wireValue *wire.Value) (bool, map[string]string, zanzibar.RWTStruct, error) { var req baz.SimpleService_SimpleFuture_Args var res baz.SimpleService_SimpleFuture_Result @@ -139,21 +139,21 @@ type SimpleFunc func(context.Context, map[string]string) (map[string]string, err type SimpleFutureFunc func(context.Context, map[string]string) (map[string]string, error) // WithCall creates a TChanServer with Call handler function registered -func WithCall(call CallFunc) zt.TChanServer { +func WithCall(call CallFunc) zanzibar.TChanServer { return NewSimpleServiceServer(&Handler{ CallFunc: call, }) } // WithSimple creates a TChanServer with Simple handler function registered -func WithSimple(simple SimpleFunc) zt.TChanServer { +func WithSimple(simple SimpleFunc) zanzibar.TChanServer { return NewSimpleServiceServer(&Handler{ SimpleFunc: simple, }) } // WithSimpleFuture creates a TChanServer with SimpleFuture handler function registered -func WithSimpleFuture(simpleFuture SimpleFutureFunc) zt.TChanServer { +func WithSimpleFuture(simpleFuture SimpleFutureFunc) zanzibar.TChanServer { return NewSimpleServiceServer(&Handler{ SimpleFutureFunc: simpleFuture, }) diff --git a/runtime/gateway.go b/runtime/gateway.go index 873a2a581..04d2deee7 100644 --- a/runtime/gateway.go +++ b/runtime/gateway.go @@ -36,8 +36,6 @@ import ( "github.com/uber-go/tally/m3" "github.com/uber-go/zap" "github.com/uber/tchannel-go" - - zt "github.com/uber/zanzibar/runtime/tchannel" ) const defaultM3MaxQueueSize = 10000 @@ -75,7 +73,7 @@ type Gateway struct { logWriter zap.WriteSyncer server *HTTPServer localServer *HTTPServer - tchannelServer *zt.Server + tchannelServer *TChannelServer // clients? // - panic ??? // - process reporter ? @@ -383,7 +381,7 @@ func (gateway *Gateway) setupTChannel(config *StaticConfig) error { } gateway.Channel = channel - gateway.tchannelServer = zt.NewServer(channel, gateway.Logger) + gateway.tchannelServer = NewTChannelServer(channel, gateway.Logger) return nil } diff --git a/runtime/tchannel/doc.go b/runtime/tchannel/doc.go deleted file mode 100644 index 59e92c3b2..000000000 --- a/runtime/tchannel/doc.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) 2017 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -// Package tchannel integrates the thriftrw Thrift encoding/coding library with -// tchannel to provide an alternative thrift-over-tchannel solution. -package tchannel diff --git a/runtime/tchannel/client.go b/runtime/tchannel_client.go similarity index 99% rename from runtime/tchannel/client.go rename to runtime/tchannel_client.go index 8ec5ed4e4..2c8ae9fd9 100644 --- a/runtime/tchannel/client.go +++ b/runtime/tchannel_client.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package tchannel +package zanzibar import ( "context" diff --git a/runtime/tchannel/headers.go b/runtime/tchannel_headers.go similarity index 99% rename from runtime/tchannel/headers.go rename to runtime/tchannel_headers.go index 935e67021..8733fe601 100644 --- a/runtime/tchannel/headers.go +++ b/runtime/tchannel_headers.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package tchannel +package zanzibar import ( "fmt" diff --git a/runtime/tchannel/headers_test.go b/runtime/tchannel_headers_test.go similarity index 99% rename from runtime/tchannel/headers_test.go rename to runtime/tchannel_headers_test.go index 6c29dab22..99983c411 100644 --- a/runtime/tchannel/headers_test.go +++ b/runtime/tchannel_headers_test.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package tchannel +package zanzibar import ( "bytes" diff --git a/runtime/tchannel/helpers.go b/runtime/tchannel_helpers.go similarity index 99% rename from runtime/tchannel/helpers.go rename to runtime/tchannel_helpers.go index 2a981c754..0a28a785e 100644 --- a/runtime/tchannel/helpers.go +++ b/runtime/tchannel_helpers.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package tchannel +package zanzibar import ( "bytes" diff --git a/runtime/tchannel/helpers_test.go b/runtime/tchannel_helpers_test.go similarity index 99% rename from runtime/tchannel/helpers_test.go rename to runtime/tchannel_helpers_test.go index 2dd6faf09..37b4320a4 100644 --- a/runtime/tchannel/helpers_test.go +++ b/runtime/tchannel_helpers_test.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package tchannel +package zanzibar import ( "bytes" diff --git a/runtime/tchannel/interfaces.go b/runtime/tchannel_interfaces.go similarity index 99% rename from runtime/tchannel/interfaces.go rename to runtime/tchannel_interfaces.go index 77b90b4ce..141531ca8 100644 --- a/runtime/tchannel/interfaces.go +++ b/runtime/tchannel_interfaces.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package tchannel +package zanzibar import ( "context" diff --git a/runtime/tchannel/server.go b/runtime/tchannel_server.go similarity index 89% rename from runtime/tchannel/server.go rename to runtime/tchannel_server.go index 7354447a7..45c89e131 100644 --- a/runtime/tchannel/server.go +++ b/runtime/tchannel_server.go @@ -18,7 +18,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -package tchannel +package zanzibar import ( "bytes" @@ -46,8 +46,8 @@ type handler struct { postResponseCB PostResponseCB } -// Server handles incoming TChannel calls and forwards them to the matching TChanServer. -type Server struct { +// TChannelServer handles incoming TChannel calls and forwards them to the matching TChanServer. +type TChannelServer struct { sync.RWMutex registrar tchan.Registrar logger zap.Logger @@ -56,16 +56,16 @@ type Server struct { // netContextServer implements the Handler interface that consumes netContext instead of stdlib context type netContextServer struct { - server *Server + server *TChannelServer } func (ncs netContextServer) Handle(ctx netContext.Context, call *tchan.InboundCall) { ncs.server.Handle(ctx, call) } -// NewServer returns a server that can serve thrift services over TChannel. -func NewServer(registrar tchan.Registrar, logger zap.Logger) *Server { - server := &Server{ +// NewTChannelServer returns a server that can serve thrift services over TChannel. +func NewTChannelServer(registrar tchan.Registrar, logger zap.Logger) *TChannelServer { + server := &TChannelServer{ registrar: registrar, logger: logger, handlers: map[string]handler{}, @@ -73,7 +73,7 @@ func NewServer(registrar tchan.Registrar, logger zap.Logger) *Server { return server } -func (s *Server) register(svr TChanServer, h *handler) { +func (s *TChannelServer) register(svr TChanServer, h *handler) { service := svr.Service() s.Lock() s.handlers[service] = *h @@ -86,13 +86,13 @@ func (s *Server) register(svr TChanServer, h *handler) { } // Register registers the given TChanServer to the be called on any incoming call for its services. -func (s *Server) Register(svr TChanServer) { +func (s *TChannelServer) Register(svr TChanServer) { handler := &handler{server: svr} s.register(svr, handler) } // RegisterWithPostResponseCB registers the given TChanServer with a PostResponseCB function -func (s *Server) RegisterWithPostResponseCB(svr TChanServer, cb PostResponseCB) { +func (s *TChannelServer) RegisterWithPostResponseCB(svr TChanServer, cb PostResponseCB) { handler := &handler{ server: svr, postResponseCB: cb, @@ -100,7 +100,7 @@ func (s *Server) RegisterWithPostResponseCB(svr TChanServer, cb PostResponseCB) s.register(svr, handler) } -func (s *Server) onError(err error) { +func (s *TChannelServer) onError(err error) { if tchan.GetSystemErrorCode(err) == tchan.ErrCodeTimeout { s.logger.Warn("Thrift server timeout", zap.String("error", err.Error()), @@ -112,7 +112,7 @@ func (s *Server) onError(err error) { } } -func (s *Server) handle(ctx context.Context, handler handler, method string, call *tchan.InboundCall) error { +func (s *TChannelServer) handle(ctx context.Context, handler handler, method string, call *tchan.InboundCall) error { serviceName := handler.server.Service() reader, err := call.Arg2Reader() @@ -215,7 +215,7 @@ func getServiceMethod(method string) (string, string, bool) { } // Handle handles an incoming TChannel call and forwards it to the correct handler. -func (s *Server) Handle(ctx context.Context, call *tchan.InboundCall) { +func (s *TChannelServer) Handle(ctx context.Context, call *tchan.InboundCall) { op := call.MethodString() service, method, ok := getServiceMethod(op) if !ok { diff --git a/test/lib/test_backend/test_tchannel_backend.go b/test/lib/test_backend/test_tchannel_backend.go index f7ea7c21e..f962ec48d 100644 --- a/test/lib/test_backend/test_tchannel_backend.go +++ b/test/lib/test_backend/test_tchannel_backend.go @@ -27,13 +27,13 @@ import ( "github.com/uber-go/zap" "github.com/uber/tchannel-go" - zt "github.com/uber/zanzibar/runtime/tchannel" + "github.com/uber/zanzibar/runtime" ) // TestTChannelBackend will pretend to be a http backend type TestTChannelBackend struct { Channel *tchannel.Channel - Server *zt.Server + Server *zanzibar.TChannelServer IP string Port int32 RealPort int32 @@ -91,7 +91,7 @@ func (backend *TestTChannelBackend) Bootstrap() error { } // Register registers tchannel server handler -func (backend *TestTChannelBackend) Register(server zt.TChanServer) { +func (backend *TestTChannelBackend) Register(server zanzibar.TChanServer) { backend.Server.Register(server) } @@ -119,7 +119,7 @@ func CreateTChannelBackend(port int32, serviceName string) (*TestTChannelBackend } backend.Channel = channel - backend.Server = zt.NewServer(channel, testLogger) + backend.Server = zanzibar.NewTChannelServer(channel, testLogger) return backend, nil } From ec6c21c9966b5e8be1a514f6acd70630de85c61d Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 19:50:24 -0700 Subject: [PATCH 14/15] Remove redundant error assertion --- .../baz/baz_simpleservice_method_simple_future_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go index 551167268..9dd076807 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_future_test.go @@ -71,10 +71,6 @@ func TestSimpleFutureSuccessfulRequestOKResponse(t *testing.T) { return } - if !assert.NoError(t, err, "failed to read response body") { - return - } - assert.Equal(t, 1, testSimpleFutureCounter) assert.Equal(t, "200 OK", res.Status) } From cbd9dfb4890bcd8a0c1b91d66963e32f80005f39 Mon Sep 17 00:00:00 2001 From: Chuntao Lu Date: Mon, 3 Apr 2017 19:51:59 -0700 Subject: [PATCH 15/15] Remove redundant error assertion, one more --- .../endpoints/baz/baz_simpleservice_method_simple_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go index c3e8d21bc..8391bfbf6 100644 --- a/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go +++ b/examples/example-gateway/endpoints/baz/baz_simpleservice_method_simple_test.go @@ -69,10 +69,6 @@ func TestSimpleSuccessfulRequestOKResponse(t *testing.T) { return } - if !assert.NoError(t, err, "failed to read response body") { - return - } - assert.Equal(t, 1, testSimpleCounter) assert.Equal(t, "200 OK", res.Status) }