diff --git a/examples/README.md b/examples/README.md index 2891d7886..1148c185b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,5 +1,3 @@ # Examples -For more information about these examples, - including a walkthrough of the stringsvc example, - see [gokit.io/examples](https://gokit.io/examples). +Examples have been relocated to a separate repository: https://github.com/go-kit/examples diff --git a/examples/addsvc/README.md b/examples/addsvc/README.md deleted file mode 100644 index 080800609..000000000 --- a/examples/addsvc/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# addsvc - -addsvc is an example microservice which takes full advantage of most of Go -kit's features, including both service- and transport-level middlewares, -speaking multiple transports simultaneously, distributed tracing, and rich -error definitions. The server binary is available in cmd/addsvc. The client -binary is available in cmd/addcli. - -Finally, the addtransport package provides both server and clients for each -supported transport. The client structs bake-in certain middlewares, in order to -demonstrate the _client library pattern_. But beware: client libraries are -generally a bad idea, because they easily lead to the - [distributed monolith antipattern](https://www.microservices.com/talks/dont-build-a-distributed-monolith/). -If you don't _know_ you need to use one in your organization, it's probably best -avoided: prefer moving that logic to consumers, and relying on - [contract testing](https://docs.pact.io/best_practices/contract_tests_not_functional_tests.html) -to detect incompatibilities. diff --git a/examples/addsvc/cmd/addcli/addcli.go b/examples/addsvc/cmd/addcli/addcli.go deleted file mode 100644 index 9afe0ae31..000000000 --- a/examples/addsvc/cmd/addcli/addcli.go +++ /dev/null @@ -1,210 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "os" - "strconv" - "text/tabwriter" - "time" - - "google.golang.org/grpc" - - "github.com/apache/thrift/lib/go/thrift" - lightstep "github.com/lightstep/lightstep-tracer-go" - stdopentracing "github.com/opentracing/opentracing-go" - zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing" - zipkin "github.com/openzipkin/zipkin-go" - zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http" - "sourcegraph.com/sourcegraph/appdash" - appdashot "sourcegraph.com/sourcegraph/appdash/opentracing" - - "github.com/go-kit/kit/log" - - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" - "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" - addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" -) - -func main() { - // The addcli presumes no service discovery system, and expects users to - // provide the direct address of an addsvc. This presumption is reflected in - // the addcli binary and the client packages: the -transport.addr flags - // and various client constructors both expect host:port strings. For an - // example service with a client built on top of a service discovery system, - // see profilesvc. - fs := flag.NewFlagSet("addcli", flag.ExitOnError) - var ( - httpAddr = fs.String("http-addr", "", "HTTP address of addsvc") - grpcAddr = fs.String("grpc-addr", "", "gRPC address of addsvc") - thriftAddr = fs.String("thrift-addr", "", "Thrift address of addsvc") - jsonRPCAddr = fs.String("jsonrpc-addr", "", "JSON RPC address of addsvc") - thriftProtocol = fs.String("thrift-protocol", "binary", "binary, compact, json, simplejson") - thriftBuffer = fs.Int("thrift-buffer", 0, "0 for unbuffered") - thriftFramed = fs.Bool("thrift-framed", false, "true to enable framing") - zipkinURL = fs.String("zipkin-url", "", "Enable Zipkin tracing via HTTP reporter URL e.g. http://localhost:9411/api/v2/spans") - zipkinBridge = fs.Bool("zipkin-ot-bridge", false, "Use Zipkin OpenTracing bridge instead of native implementation") - lightstepToken = fs.String("lightstep-token", "", "Enable LightStep tracing via a LightStep access token") - appdashAddr = fs.String("appdash-addr", "", "Enable Appdash tracing via an Appdash server host:port") - method = fs.String("method", "sum", "sum, concat") - ) - fs.Usage = usageFor(fs, os.Args[0]+" [flags] ") - fs.Parse(os.Args[1:]) - if len(fs.Args()) != 2 { - fs.Usage() - os.Exit(1) - } - - // This is a demonstration of the native Zipkin tracing client. If using - // Zipkin this is the more idiomatic client over OpenTracing. - var zipkinTracer *zipkin.Tracer - { - if *zipkinURL != "" { - var ( - err error - hostPort = "" // if host:port is unknown we can keep this empty - serviceName = "addsvc-cli" - reporter = zipkinhttp.NewReporter(*zipkinURL) - ) - defer reporter.Close() - zEP, _ := zipkin.NewEndpoint(serviceName, hostPort) - zipkinTracer, err = zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(zEP)) - if err != nil { - fmt.Fprintf(os.Stderr, "unable to create zipkin tracer: %s\n", err.Error()) - os.Exit(1) - } - } - } - - // This is a demonstration client, which supports multiple tracers. - // Your clients will probably just use one tracer. - var otTracer stdopentracing.Tracer - { - if *zipkinBridge && zipkinTracer != nil { - otTracer = zipkinot.Wrap(zipkinTracer) - zipkinTracer = nil // do not instrument with both native and ot bridge - } else if *lightstepToken != "" { - otTracer = lightstep.NewTracer(lightstep.Options{ - AccessToken: *lightstepToken, - }) - defer lightstep.FlushLightStepTracer(otTracer) - } else if *appdashAddr != "" { - otTracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) - } else { - otTracer = stdopentracing.GlobalTracer() // no-op - } - } - - // This is a demonstration client, which supports multiple transports. - // Your clients will probably just define and stick with 1 transport. - var ( - svc addservice.Service - err error - ) - if *httpAddr != "" { - svc, err = addtransport.NewHTTPClient(*httpAddr, otTracer, zipkinTracer, log.NewNopLogger()) - } else if *grpcAddr != "" { - conn, err := grpc.Dial(*grpcAddr, grpc.WithInsecure(), grpc.WithTimeout(time.Second)) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v", err) - os.Exit(1) - } - defer conn.Close() - svc = addtransport.NewGRPCClient(conn, otTracer, zipkinTracer, log.NewNopLogger()) - } else if *jsonRPCAddr != "" { - svc, err = addtransport.NewJSONRPCClient(*jsonRPCAddr, otTracer, log.NewNopLogger()) - } else if *thriftAddr != "" { - // It's necessary to do all of this construction in the func main, - // because (among other reasons) we need to control the lifecycle of the - // Thrift transport, i.e. close it eventually. - var protocolFactory thrift.TProtocolFactory - switch *thriftProtocol { - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - case "binary", "": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - default: - fmt.Fprintf(os.Stderr, "error: invalid protocol %q\n", *thriftProtocol) - os.Exit(1) - } - var transportFactory thrift.TTransportFactory - if *thriftBuffer > 0 { - transportFactory = thrift.NewTBufferedTransportFactory(*thriftBuffer) - } else { - transportFactory = thrift.NewTTransportFactory() - } - if *thriftFramed { - transportFactory = thrift.NewTFramedTransportFactory(transportFactory) - } - transportSocket, err := thrift.NewTSocket(*thriftAddr) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - transport, err := transportFactory.GetTransport(transportSocket) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - if err := transport.Open(); err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - defer transport.Close() - client := addthrift.NewAddServiceClientFactory(transport, protocolFactory) - svc = addtransport.NewThriftClient(client) - } else { - fmt.Fprintf(os.Stderr, "error: no remote address specified\n") - os.Exit(1) - } - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - - switch *method { - case "sum": - a, _ := strconv.ParseInt(fs.Args()[0], 10, 64) - b, _ := strconv.ParseInt(fs.Args()[1], 10, 64) - v, err := svc.Sum(context.Background(), int(a), int(b)) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - fmt.Fprintf(os.Stdout, "%d + %d = %d\n", a, b, v) - - case "concat": - a := fs.Args()[0] - b := fs.Args()[1] - v, err := svc.Concat(context.Background(), a, b) - if err != nil { - fmt.Fprintf(os.Stderr, "error: %v\n", err) - os.Exit(1) - } - fmt.Fprintf(os.Stdout, "%q + %q = %q\n", a, b, v) - - default: - fmt.Fprintf(os.Stderr, "error: invalid method %q\n", *method) - os.Exit(1) - } -} - -func usageFor(fs *flag.FlagSet, short string) func() { - return func() { - fmt.Fprintf(os.Stderr, "USAGE\n") - fmt.Fprintf(os.Stderr, " %s\n", short) - fmt.Fprintf(os.Stderr, "\n") - fmt.Fprintf(os.Stderr, "FLAGS\n") - w := tabwriter.NewWriter(os.Stderr, 0, 2, 2, ' ', 0) - fs.VisitAll(func(f *flag.Flag) { - fmt.Fprintf(w, "\t-%s %s\t%s\n", f.Name, f.DefValue, f.Usage) - }) - w.Flush() - fmt.Fprintf(os.Stderr, "\n") - } -} diff --git a/examples/addsvc/cmd/addsvc/addsvc.go b/examples/addsvc/cmd/addsvc/addsvc.go deleted file mode 100644 index 0fc2454c9..000000000 --- a/examples/addsvc/cmd/addsvc/addsvc.go +++ /dev/null @@ -1,306 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "net" - "net/http" - "os" - "os/signal" - "syscall" - "text/tabwriter" - - "github.com/apache/thrift/lib/go/thrift" - lightstep "github.com/lightstep/lightstep-tracer-go" - "github.com/oklog/oklog/pkg/group" - stdopentracing "github.com/opentracing/opentracing-go" - zipkinot "github.com/openzipkin-contrib/zipkin-go-opentracing" - zipkin "github.com/openzipkin/zipkin-go" - zipkinhttp "github.com/openzipkin/zipkin-go/reporter/http" - stdprometheus "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - "google.golang.org/grpc" - "sourcegraph.com/sourcegraph/appdash" - appdashot "sourcegraph.com/sourcegraph/appdash/opentracing" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/metrics/prometheus" - kitgrpc "github.com/go-kit/kit/transport/grpc" - - addpb "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" - "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" - addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" -) - -func main() { - // Define our flags. Your service probably won't need to bind listeners for - // *all* supported transports, or support both Zipkin and LightStep, and so - // on, but we do it here for demonstration purposes. - fs := flag.NewFlagSet("addsvc", flag.ExitOnError) - var ( - debugAddr = fs.String("debug.addr", ":8080", "Debug and metrics listen address") - httpAddr = fs.String("http-addr", ":8081", "HTTP listen address") - grpcAddr = fs.String("grpc-addr", ":8082", "gRPC listen address") - thriftAddr = fs.String("thrift-addr", ":8083", "Thrift listen address") - jsonRPCAddr = fs.String("jsonrpc-addr", ":8084", "JSON RPC listen address") - thriftProtocol = fs.String("thrift-protocol", "binary", "binary, compact, json, simplejson") - thriftBuffer = fs.Int("thrift-buffer", 0, "0 for unbuffered") - thriftFramed = fs.Bool("thrift-framed", false, "true to enable framing") - zipkinURL = fs.String("zipkin-url", "", "Enable Zipkin tracing via HTTP reporter URL e.g. http://localhost:9411/api/v2/spans") - zipkinBridge = fs.Bool("zipkin-ot-bridge", false, "Use Zipkin OpenTracing bridge instead of native implementation") - lightstepToken = fs.String("lightstep-token", "", "Enable LightStep tracing via a LightStep access token") - appdashAddr = fs.String("appdash-addr", "", "Enable Appdash tracing via an Appdash server host:port") - ) - fs.Usage = usageFor(fs, os.Args[0]+" [flags]") - fs.Parse(os.Args[1:]) - - // Create a single logger, which we'll use and give to other components. - var logger log.Logger - { - logger = log.NewLogfmtLogger(os.Stderr) - logger = log.With(logger, "ts", log.DefaultTimestampUTC) - logger = log.With(logger, "caller", log.DefaultCaller) - } - - var zipkinTracer *zipkin.Tracer - { - if *zipkinURL != "" { - var ( - err error - hostPort = "localhost:80" - serviceName = "addsvc" - reporter = zipkinhttp.NewReporter(*zipkinURL) - ) - defer reporter.Close() - zEP, _ := zipkin.NewEndpoint(serviceName, hostPort) - zipkinTracer, err = zipkin.NewTracer(reporter, zipkin.WithLocalEndpoint(zEP)) - if err != nil { - logger.Log("err", err) - os.Exit(1) - } - if !(*zipkinBridge) { - logger.Log("tracer", "Zipkin", "type", "Native", "URL", *zipkinURL) - } - } - } - - // Determine which OpenTracing tracer to use. We'll pass the tracer to all the - // components that use it, as a dependency. - var tracer stdopentracing.Tracer - { - if *zipkinBridge && zipkinTracer != nil { - logger.Log("tracer", "Zipkin", "type", "OpenTracing", "URL", *zipkinURL) - tracer = zipkinot.Wrap(zipkinTracer) - zipkinTracer = nil // do not instrument with both native tracer and opentracing bridge - } else if *lightstepToken != "" { - logger.Log("tracer", "LightStep") // probably don't want to print out the token :) - tracer = lightstep.NewTracer(lightstep.Options{ - AccessToken: *lightstepToken, - }) - defer lightstep.FlushLightStepTracer(tracer) - } else if *appdashAddr != "" { - logger.Log("tracer", "Appdash", "addr", *appdashAddr) - tracer = appdashot.NewTracer(appdash.NewRemoteCollector(*appdashAddr)) - } else { - tracer = stdopentracing.GlobalTracer() // no-op - } - } - - // Create the (sparse) metrics we'll use in the service. They, too, are - // dependencies that we pass to components that use them. - var ints, chars metrics.Counter - { - // Business-level metrics. - ints = prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "example", - Subsystem: "addsvc", - Name: "integers_summed", - Help: "Total count of integers summed via the Sum method.", - }, []string{}) - chars = prometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "example", - Subsystem: "addsvc", - Name: "characters_concatenated", - Help: "Total count of characters concatenated via the Concat method.", - }, []string{}) - } - var duration metrics.Histogram - { - // Endpoint-level metrics. - duration = prometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "example", - Subsystem: "addsvc", - Name: "request_duration_seconds", - Help: "Request duration in seconds.", - }, []string{"method", "success"}) - } - http.DefaultServeMux.Handle("/metrics", promhttp.Handler()) - - // Build the layers of the service "onion" from the inside out. First, the - // business logic service; then, the set of endpoints that wrap the service; - // and finally, a series of concrete transport adapters. The adapters, like - // the HTTP handler or the gRPC server, are the bridge between Go kit and - // the interfaces that the transports expect. Note that we're not binding - // them to ports or anything yet; we'll do that next. - var ( - service = addservice.New(logger, ints, chars) - endpoints = addendpoint.New(service, logger, duration, tracer, zipkinTracer) - httpHandler = addtransport.NewHTTPHandler(endpoints, tracer, zipkinTracer, logger) - grpcServer = addtransport.NewGRPCServer(endpoints, tracer, zipkinTracer, logger) - thriftServer = addtransport.NewThriftServer(endpoints) - jsonrpcHandler = addtransport.NewJSONRPCHandler(endpoints, logger) - ) - - // Now we're to the part of the func main where we want to start actually - // running things, like servers bound to listeners to receive connections. - // - // The method is the same for each component: add a new actor to the group - // struct, which is a combination of 2 anonymous functions: the first - // function actually runs the component, and the second function should - // interrupt the first function and cause it to return. It's in these - // functions that we actually bind the Go kit server/handler structs to the - // concrete transports and run them. - // - // Putting each component into its own block is mostly for aesthetics: it - // clearly demarcates the scope in which each listener/socket may be used. - var g group.Group - { - // The debug listener mounts the http.DefaultServeMux, and serves up - // stuff like the Prometheus metrics route, the Go debug and profiling - // routes, and so on. - debugListener, err := net.Listen("tcp", *debugAddr) - if err != nil { - logger.Log("transport", "debug/HTTP", "during", "Listen", "err", err) - os.Exit(1) - } - g.Add(func() error { - logger.Log("transport", "debug/HTTP", "addr", *debugAddr) - return http.Serve(debugListener, http.DefaultServeMux) - }, func(error) { - debugListener.Close() - }) - } - { - // The HTTP listener mounts the Go kit HTTP handler we created. - httpListener, err := net.Listen("tcp", *httpAddr) - if err != nil { - logger.Log("transport", "HTTP", "during", "Listen", "err", err) - os.Exit(1) - } - g.Add(func() error { - logger.Log("transport", "HTTP", "addr", *httpAddr) - return http.Serve(httpListener, httpHandler) - }, func(error) { - httpListener.Close() - }) - } - { - // The gRPC listener mounts the Go kit gRPC server we created. - grpcListener, err := net.Listen("tcp", *grpcAddr) - if err != nil { - logger.Log("transport", "gRPC", "during", "Listen", "err", err) - os.Exit(1) - } - g.Add(func() error { - logger.Log("transport", "gRPC", "addr", *grpcAddr) - // we add the Go Kit gRPC Interceptor to our gRPC service as it is used by - // the here demonstrated zipkin tracing middleware. - baseServer := grpc.NewServer(grpc.UnaryInterceptor(kitgrpc.Interceptor)) - addpb.RegisterAddServer(baseServer, grpcServer) - return baseServer.Serve(grpcListener) - }, func(error) { - grpcListener.Close() - }) - } - { - // The Thrift socket mounts the Go kit Thrift server we created earlier. - // There's a lot of boilerplate involved here, related to configuring - // the protocol and transport; blame Thrift. - thriftSocket, err := thrift.NewTServerSocket(*thriftAddr) - if err != nil { - logger.Log("transport", "Thrift", "during", "Listen", "err", err) - os.Exit(1) - } - g.Add(func() error { - logger.Log("transport", "Thrift", "addr", *thriftAddr) - var protocolFactory thrift.TProtocolFactory - switch *thriftProtocol { - case "binary": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - default: - return fmt.Errorf("invalid Thrift protocol %q", *thriftProtocol) - } - var transportFactory thrift.TTransportFactory - if *thriftBuffer > 0 { - transportFactory = thrift.NewTBufferedTransportFactory(*thriftBuffer) - } else { - transportFactory = thrift.NewTTransportFactory() - } - if *thriftFramed { - transportFactory = thrift.NewTFramedTransportFactory(transportFactory) - } - return thrift.NewTSimpleServer4( - addthrift.NewAddServiceProcessor(thriftServer), - thriftSocket, - transportFactory, - protocolFactory, - ).Serve() - }, func(error) { - thriftSocket.Close() - }) - } - { - httpListener, err := net.Listen("tcp", *jsonRPCAddr) - if err != nil { - logger.Log("transport", "JSONRPC over HTTP", "during", "Listen", "err", err) - os.Exit(1) - } - g.Add(func() error { - logger.Log("transport", "JSONRPC over HTTP", "addr", *jsonRPCAddr) - return http.Serve(httpListener, jsonrpcHandler) - }, func(error) { - httpListener.Close() - }) - } - { - // This function just sits and waits for ctrl-C. - cancelInterrupt := make(chan struct{}) - g.Add(func() error { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - select { - case sig := <-c: - return fmt.Errorf("received signal %s", sig) - case <-cancelInterrupt: - return nil - } - }, func(error) { - close(cancelInterrupt) - }) - } - logger.Log("exit", g.Run()) -} - -func usageFor(fs *flag.FlagSet, short string) func() { - return func() { - fmt.Fprintf(os.Stderr, "USAGE\n") - fmt.Fprintf(os.Stderr, " %s\n", short) - fmt.Fprintf(os.Stderr, "\n") - fmt.Fprintf(os.Stderr, "FLAGS\n") - w := tabwriter.NewWriter(os.Stderr, 0, 2, 2, ' ', 0) - fs.VisitAll(func(f *flag.Flag) { - fmt.Fprintf(w, "\t-%s %s\t%s\n", f.Name, f.DefValue, f.Usage) - }) - w.Flush() - fmt.Fprintf(os.Stderr, "\n") - } -} diff --git a/examples/addsvc/cmd/addsvc/pact_test.go b/examples/addsvc/cmd/addsvc/pact_test.go deleted file mode 100644 index 2f62ff3bc..000000000 --- a/examples/addsvc/cmd/addsvc/pact_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "os" - "strings" - "testing" - - "github.com/pact-foundation/pact-go/dsl" -) - -func TestPactStringsvcUppercase(t *testing.T) { - if os.Getenv("WRITE_PACTS") == "" { - t.Skip("skipping Pact contracts; set WRITE_PACTS environment variable to enable") - } - - pact := dsl.Pact{ - Consumer: "addsvc", - Provider: "stringsvc", - } - defer pact.Teardown() - - pact.AddInteraction(). - UponReceiving("stringsvc uppercase"). - WithRequest(dsl.Request{ - Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json; charset=utf-8")}, - Method: "POST", - Path: dsl.String("/uppercase"), - Body: `{"s":"foo"}`, - }). - WillRespondWith(dsl.Response{ - Status: 200, - Headers: dsl.MapMatcher{"Content-Type": dsl.String("application/json; charset=utf-8")}, - Body: `{"v":"FOO"}`, - }) - - if err := pact.Verify(func() error { - u := fmt.Sprintf("http://localhost:%d/uppercase", pact.Server.Port) - req, err := http.NewRequest("POST", u, strings.NewReader(`{"s":"foo"}`)) - if err != nil { - return err - } - req.Header.Set("Content-Type", "application/json; charset=utf-8") - if _, err = http.DefaultClient.Do(req); err != nil { - return err - } - return nil - }); err != nil { - t.Fatal(err) - } - - pact.WritePact() -} diff --git a/examples/addsvc/cmd/addsvc/wiring_test.go b/examples/addsvc/cmd/addsvc/wiring_test.go deleted file mode 100644 index f9b3551b2..000000000 --- a/examples/addsvc/cmd/addsvc/wiring_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "io/ioutil" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/opentracing/opentracing-go" - zipkin "github.com/openzipkin/zipkin-go" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics/discard" - - "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" - "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" -) - -func TestHTTP(t *testing.T) { - zkt, _ := zipkin.NewTracer(nil, zipkin.WithNoopTracer(true)) - svc := addservice.New(log.NewNopLogger(), discard.NewCounter(), discard.NewCounter()) - eps := addendpoint.New(svc, log.NewNopLogger(), discard.NewHistogram(), opentracing.GlobalTracer(), zkt) - mux := addtransport.NewHTTPHandler(eps, opentracing.GlobalTracer(), zkt, log.NewNopLogger()) - srv := httptest.NewServer(mux) - defer srv.Close() - - for _, testcase := range []struct { - method, url, body, want string - }{ - {"GET", srv.URL + "/concat", `{"a":"1","b":"2"}`, `{"v":"12"}`}, - {"GET", srv.URL + "/sum", `{"a":1,"b":2}`, `{"v":3}`}, - } { - req, _ := http.NewRequest(testcase.method, testcase.url, strings.NewReader(testcase.body)) - resp, _ := http.DefaultClient.Do(req) - body, _ := ioutil.ReadAll(resp.Body) - if want, have := testcase.want, strings.TrimSpace(string(body)); want != have { - t.Errorf("%s %s %s: want %q, have %q", testcase.method, testcase.url, testcase.body, want, have) - } - } -} diff --git a/examples/addsvc/pb/addsvc.pb.go b/examples/addsvc/pb/addsvc.pb.go deleted file mode 100644 index 0e992f59d..000000000 --- a/examples/addsvc/pb/addsvc.pb.go +++ /dev/null @@ -1,349 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// source: addsvc.proto - -package pb - -import ( - context "context" - fmt "fmt" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - math "math" -) - -// 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.ProtoPackageIsVersion3 // please upgrade the proto package - -// The sum request contains two parameters. -type SumRequest struct { - A int64 `protobuf:"varint,1,opt,name=a,proto3" json:"a,omitempty"` - B int64 `protobuf:"varint,2,opt,name=b,proto3" json:"b,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SumRequest) Reset() { *m = SumRequest{} } -func (m *SumRequest) String() string { return proto.CompactTextString(m) } -func (*SumRequest) ProtoMessage() {} -func (*SumRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_174367f558d60c26, []int{0} -} - -func (m *SumRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SumRequest.Unmarshal(m, b) -} -func (m *SumRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SumRequest.Marshal(b, m, deterministic) -} -func (m *SumRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_SumRequest.Merge(m, src) -} -func (m *SumRequest) XXX_Size() int { - return xxx_messageInfo_SumRequest.Size(m) -} -func (m *SumRequest) XXX_DiscardUnknown() { - xxx_messageInfo_SumRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_SumRequest proto.InternalMessageInfo - -func (m *SumRequest) GetA() int64 { - if m != nil { - return m.A - } - return 0 -} - -func (m *SumRequest) GetB() int64 { - if m != nil { - return m.B - } - return 0 -} - -// The sum response contains the result of the calculation. -type SumReply struct { - V int64 `protobuf:"varint,1,opt,name=v,proto3" json:"v,omitempty"` - Err string `protobuf:"bytes,2,opt,name=err,proto3" json:"err,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *SumReply) Reset() { *m = SumReply{} } -func (m *SumReply) String() string { return proto.CompactTextString(m) } -func (*SumReply) ProtoMessage() {} -func (*SumReply) Descriptor() ([]byte, []int) { - return fileDescriptor_174367f558d60c26, []int{1} -} - -func (m *SumReply) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_SumReply.Unmarshal(m, b) -} -func (m *SumReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_SumReply.Marshal(b, m, deterministic) -} -func (m *SumReply) XXX_Merge(src proto.Message) { - xxx_messageInfo_SumReply.Merge(m, src) -} -func (m *SumReply) XXX_Size() int { - return xxx_messageInfo_SumReply.Size(m) -} -func (m *SumReply) XXX_DiscardUnknown() { - xxx_messageInfo_SumReply.DiscardUnknown(m) -} - -var xxx_messageInfo_SumReply proto.InternalMessageInfo - -func (m *SumReply) GetV() int64 { - if m != nil { - return m.V - } - return 0 -} - -func (m *SumReply) GetErr() string { - if m != nil { - return m.Err - } - return "" -} - -// The Concat request contains two parameters. -type ConcatRequest struct { - A string `protobuf:"bytes,1,opt,name=a,proto3" json:"a,omitempty"` - B string `protobuf:"bytes,2,opt,name=b,proto3" json:"b,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ConcatRequest) Reset() { *m = ConcatRequest{} } -func (m *ConcatRequest) String() string { return proto.CompactTextString(m) } -func (*ConcatRequest) ProtoMessage() {} -func (*ConcatRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_174367f558d60c26, []int{2} -} - -func (m *ConcatRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ConcatRequest.Unmarshal(m, b) -} -func (m *ConcatRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ConcatRequest.Marshal(b, m, deterministic) -} -func (m *ConcatRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConcatRequest.Merge(m, src) -} -func (m *ConcatRequest) XXX_Size() int { - return xxx_messageInfo_ConcatRequest.Size(m) -} -func (m *ConcatRequest) XXX_DiscardUnknown() { - xxx_messageInfo_ConcatRequest.DiscardUnknown(m) -} - -var xxx_messageInfo_ConcatRequest proto.InternalMessageInfo - -func (m *ConcatRequest) GetA() string { - if m != nil { - return m.A - } - return "" -} - -func (m *ConcatRequest) GetB() string { - if m != nil { - return m.B - } - return "" -} - -// The Concat response contains the result of the concatenation. -type ConcatReply struct { - V string `protobuf:"bytes,1,opt,name=v,proto3" json:"v,omitempty"` - Err string `protobuf:"bytes,2,opt,name=err,proto3" json:"err,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *ConcatReply) Reset() { *m = ConcatReply{} } -func (m *ConcatReply) String() string { return proto.CompactTextString(m) } -func (*ConcatReply) ProtoMessage() {} -func (*ConcatReply) Descriptor() ([]byte, []int) { - return fileDescriptor_174367f558d60c26, []int{3} -} - -func (m *ConcatReply) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_ConcatReply.Unmarshal(m, b) -} -func (m *ConcatReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_ConcatReply.Marshal(b, m, deterministic) -} -func (m *ConcatReply) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConcatReply.Merge(m, src) -} -func (m *ConcatReply) XXX_Size() int { - return xxx_messageInfo_ConcatReply.Size(m) -} -func (m *ConcatReply) XXX_DiscardUnknown() { - xxx_messageInfo_ConcatReply.DiscardUnknown(m) -} - -var xxx_messageInfo_ConcatReply proto.InternalMessageInfo - -func (m *ConcatReply) GetV() string { - if m != nil { - return m.V - } - return "" -} - -func (m *ConcatReply) GetErr() string { - if m != nil { - return m.Err - } - return "" -} - -func init() { - proto.RegisterType((*SumRequest)(nil), "pb.SumRequest") - proto.RegisterType((*SumReply)(nil), "pb.SumReply") - proto.RegisterType((*ConcatRequest)(nil), "pb.ConcatRequest") - proto.RegisterType((*ConcatReply)(nil), "pb.ConcatReply") -} - -func init() { proto.RegisterFile("addsvc.proto", fileDescriptor_174367f558d60c26) } - -var fileDescriptor_174367f558d60c26 = []byte{ - // 189 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x49, 0x4c, 0x49, 0x29, - 0x2e, 0x4b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2a, 0x48, 0x52, 0xd2, 0xe0, 0xe2, - 0x0a, 0x2e, 0xcd, 0x0d, 0x4a, 0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0xe2, 0xe1, 0x62, 0x4c, 0x94, - 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0e, 0x62, 0x4c, 0x04, 0xf1, 0x92, 0x24, 0x98, 0x20, 0xbc, 0x24, - 0x25, 0x2d, 0x2e, 0x0e, 0xb0, 0xca, 0x82, 0x9c, 0x4a, 0x90, 0x4c, 0x19, 0x4c, 0x5d, 0x99, 0x90, - 0x00, 0x17, 0x73, 0x6a, 0x51, 0x11, 0x58, 0x25, 0x67, 0x10, 0x88, 0xa9, 0xa4, 0xcd, 0xc5, 0xeb, - 0x9c, 0x9f, 0x97, 0x9c, 0x58, 0x82, 0x61, 0x30, 0x27, 0x8a, 0xc1, 0x9c, 0x20, 0x83, 0x75, 0xb9, - 0xb8, 0x61, 0x8a, 0x51, 0xcc, 0xe6, 0xc4, 0x6a, 0xb6, 0x51, 0x0c, 0x17, 0xb3, 0x63, 0x4a, 0x8a, - 0x90, 0x2a, 0x17, 0x73, 0x70, 0x69, 0xae, 0x10, 0x9f, 0x5e, 0x41, 0x92, 0x1e, 0xc2, 0x07, 0x52, - 0x3c, 0x70, 0x7e, 0x41, 0x4e, 0xa5, 0x12, 0x83, 0x90, 0x1e, 0x17, 0x1b, 0xc4, 0x70, 0x21, 0x41, - 0x90, 0x0c, 0x8a, 0xab, 0xa4, 0xf8, 0x91, 0x85, 0xc0, 0xea, 0x93, 0xd8, 0xc0, 0x41, 0x63, 0x0c, - 0x08, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x37, 0x81, 0x99, 0x2a, 0x01, 0x00, 0x00, -} - -// 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 - -// AddClient is the client API for Add service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type AddClient interface { - // Sums two integers. - Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error) - // Concatenates two strings - Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error) -} - -type addClient struct { - cc *grpc.ClientConn -} - -func NewAddClient(cc *grpc.ClientConn) AddClient { - return &addClient{cc} -} - -func (c *addClient) Sum(ctx context.Context, in *SumRequest, opts ...grpc.CallOption) (*SumReply, error) { - out := new(SumReply) - err := c.cc.Invoke(ctx, "/pb.Add/Sum", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *addClient) Concat(ctx context.Context, in *ConcatRequest, opts ...grpc.CallOption) (*ConcatReply, error) { - out := new(ConcatReply) - err := c.cc.Invoke(ctx, "/pb.Add/Concat", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// AddServer is the server API for Add service. -type AddServer interface { - // Sums two integers. - Sum(context.Context, *SumRequest) (*SumReply, error) - // Concatenates two strings - Concat(context.Context, *ConcatRequest) (*ConcatReply, error) -} - -func RegisterAddServer(s *grpc.Server, srv AddServer) { - s.RegisterService(&_Add_serviceDesc, srv) -} - -func _Add_Sum_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SumRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AddServer).Sum(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.Add/Sum", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AddServer).Sum(ctx, req.(*SumRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _Add_Concat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ConcatRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AddServer).Concat(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/pb.Add/Concat", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AddServer).Concat(ctx, req.(*ConcatRequest)) - } - return interceptor(ctx, in, info, handler) -} - -var _Add_serviceDesc = grpc.ServiceDesc{ - ServiceName: "pb.Add", - HandlerType: (*AddServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Sum", - Handler: _Add_Sum_Handler, - }, - { - MethodName: "Concat", - Handler: _Add_Concat_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "addsvc.proto", -} diff --git a/examples/addsvc/pb/addsvc.proto b/examples/addsvc/pb/addsvc.proto deleted file mode 100644 index cf61532f3..000000000 --- a/examples/addsvc/pb/addsvc.proto +++ /dev/null @@ -1,36 +0,0 @@ -syntax = "proto3"; - -package pb; - -// The Add service definition. -service Add { - // Sums two integers. - rpc Sum (SumRequest) returns (SumReply) {} - - // Concatenates two strings - rpc Concat (ConcatRequest) returns (ConcatReply) {} -} - -// The sum request contains two parameters. -message SumRequest { - int64 a = 1; - int64 b = 2; -} - -// The sum response contains the result of the calculation. -message SumReply { - int64 v = 1; - string err = 2; -} - -// The Concat request contains two parameters. -message ConcatRequest { - string a = 1; - string b = 2; -} - -// The Concat response contains the result of the concatenation. -message ConcatReply { - string v = 1; - string err = 2; -} diff --git a/examples/addsvc/pb/compile.sh b/examples/addsvc/pb/compile.sh deleted file mode 100755 index c0268442a..000000000 --- a/examples/addsvc/pb/compile.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env sh - -# Install proto3 from source -# brew install autoconf automake libtool -# git clone https://github.com/google/protobuf -# ./autogen.sh ; ./configure ; make ; make install -# -# Update protoc Go bindings via -# go get -u github.com/golang/protobuf/{proto,protoc-gen-go} -# -# See also -# https://github.com/grpc/grpc-go/tree/master/examples - -protoc addsvc.proto --go_out=plugins=grpc:. diff --git a/examples/addsvc/pkg/addendpoint/middleware.go b/examples/addsvc/pkg/addendpoint/middleware.go deleted file mode 100644 index c83047b76..000000000 --- a/examples/addsvc/pkg/addendpoint/middleware.go +++ /dev/null @@ -1,43 +0,0 @@ -package addendpoint - -import ( - "context" - "fmt" - "time" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" -) - -// InstrumentingMiddleware returns an endpoint middleware that records -// the duration of each invocation to the passed histogram. The middleware adds -// a single field: "success", which is "true" if no error is returned, and -// "false" otherwise. -func InstrumentingMiddleware(duration metrics.Histogram) endpoint.Middleware { - return func(next endpoint.Endpoint) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - - defer func(begin time.Time) { - duration.With("success", fmt.Sprint(err == nil)).Observe(time.Since(begin).Seconds()) - }(time.Now()) - return next(ctx, request) - - } - } -} - -// LoggingMiddleware returns an endpoint middleware that logs the -// duration of each invocation, and the resulting error, if any. -func LoggingMiddleware(logger log.Logger) endpoint.Middleware { - return func(next endpoint.Endpoint) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - - defer func(begin time.Time) { - logger.Log("transport_error", err, "took", time.Since(begin)) - }(time.Now()) - return next(ctx, request) - - } - } -} diff --git a/examples/addsvc/pkg/addendpoint/set.go b/examples/addsvc/pkg/addendpoint/set.go deleted file mode 100644 index 8f8dd644b..000000000 --- a/examples/addsvc/pkg/addendpoint/set.go +++ /dev/null @@ -1,141 +0,0 @@ -package addendpoint - -import ( - "context" - "time" - - "golang.org/x/time/rate" - - stdopentracing "github.com/opentracing/opentracing-go" - stdzipkin "github.com/openzipkin/zipkin-go" - "github.com/sony/gobreaker" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" - "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/tracing/opentracing" - "github.com/go-kit/kit/tracing/zipkin" - - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" -) - -// Set collects all of the endpoints that compose an add service. It's meant to -// be used as a helper struct, to collect all of the endpoints into a single -// parameter. -type Set struct { - SumEndpoint endpoint.Endpoint - ConcatEndpoint endpoint.Endpoint -} - -// New returns a Set that wraps the provided server, and wires in all of the -// expected endpoint middlewares via the various parameters. -func New(svc addservice.Service, logger log.Logger, duration metrics.Histogram, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer) Set { - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = MakeSumEndpoint(svc) - // Sum is limited to 1 request per second with burst of 1 request. - // Note, rate is defined as a time interval between requests. - sumEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 1))(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(sumEndpoint) - sumEndpoint = opentracing.TraceServer(otTracer, "Sum")(sumEndpoint) - if zipkinTracer != nil { - sumEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Sum")(sumEndpoint) - } - sumEndpoint = LoggingMiddleware(log.With(logger, "method", "Sum"))(sumEndpoint) - sumEndpoint = InstrumentingMiddleware(duration.With("method", "Sum"))(sumEndpoint) - } - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = MakeConcatEndpoint(svc) - // Concat is limited to 1 request per second with burst of 100 requests. - // Note, rate is defined as a number of requests per second. - concatEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Limit(1), 100))(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(concatEndpoint) - concatEndpoint = opentracing.TraceServer(otTracer, "Concat")(concatEndpoint) - if zipkinTracer != nil { - concatEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Concat")(concatEndpoint) - } - concatEndpoint = LoggingMiddleware(log.With(logger, "method", "Concat"))(concatEndpoint) - concatEndpoint = InstrumentingMiddleware(duration.With("method", "Concat"))(concatEndpoint) - } - return Set{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - } -} - -// Sum implements the service interface, so Set may be used as a service. -// This is primarily useful in the context of a client library. -func (s Set) Sum(ctx context.Context, a, b int) (int, error) { - resp, err := s.SumEndpoint(ctx, SumRequest{A: a, B: b}) - if err != nil { - return 0, err - } - response := resp.(SumResponse) - return response.V, response.Err -} - -// Concat implements the service interface, so Set may be used as a -// service. This is primarily useful in the context of a client library. -func (s Set) Concat(ctx context.Context, a, b string) (string, error) { - resp, err := s.ConcatEndpoint(ctx, ConcatRequest{A: a, B: b}) - if err != nil { - return "", err - } - response := resp.(ConcatResponse) - return response.V, response.Err -} - -// MakeSumEndpoint constructs a Sum endpoint wrapping the service. -func MakeSumEndpoint(s addservice.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(SumRequest) - v, err := s.Sum(ctx, req.A, req.B) - return SumResponse{V: v, Err: err}, nil - } -} - -// MakeConcatEndpoint constructs a Concat endpoint wrapping the service. -func MakeConcatEndpoint(s addservice.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(ConcatRequest) - v, err := s.Concat(ctx, req.A, req.B) - return ConcatResponse{V: v, Err: err}, nil - } -} - -// compile time assertions for our response types implementing endpoint.Failer. -var ( - _ endpoint.Failer = SumResponse{} - _ endpoint.Failer = ConcatResponse{} -) - -// SumRequest collects the request parameters for the Sum method. -type SumRequest struct { - A, B int -} - -// SumResponse collects the response values for the Sum method. -type SumResponse struct { - V int `json:"v"` - Err error `json:"-"` // should be intercepted by Failed/errorEncoder -} - -// Failed implements endpoint.Failer. -func (r SumResponse) Failed() error { return r.Err } - -// ConcatRequest collects the request parameters for the Concat method. -type ConcatRequest struct { - A, B string -} - -// ConcatResponse collects the response values for the Concat method. -type ConcatResponse struct { - V string `json:"v"` - Err error `json:"-"` -} - -// Failed implements endpoint.Failer. -func (r ConcatResponse) Failed() error { return r.Err } diff --git a/examples/addsvc/pkg/addservice/middleware.go b/examples/addsvc/pkg/addservice/middleware.go deleted file mode 100644 index 87436136c..000000000 --- a/examples/addsvc/pkg/addservice/middleware.go +++ /dev/null @@ -1,69 +0,0 @@ -package addservice - -import ( - "context" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" -) - -// Middleware describes a service (as opposed to endpoint) middleware. -type Middleware func(Service) Service - -// LoggingMiddleware takes a logger as a dependency -// and returns a service Middleware. -func LoggingMiddleware(logger log.Logger) Middleware { - return func(next Service) Service { - return loggingMiddleware{logger, next} - } -} - -type loggingMiddleware struct { - logger log.Logger - next Service -} - -func (mw loggingMiddleware) Sum(ctx context.Context, a, b int) (v int, err error) { - defer func() { - mw.logger.Log("method", "Sum", "a", a, "b", b, "v", v, "err", err) - }() - return mw.next.Sum(ctx, a, b) -} - -func (mw loggingMiddleware) Concat(ctx context.Context, a, b string) (v string, err error) { - defer func() { - mw.logger.Log("method", "Concat", "a", a, "b", b, "v", v, "err", err) - }() - return mw.next.Concat(ctx, a, b) -} - -// InstrumentingMiddleware returns a service middleware that instruments -// the number of integers summed and characters concatenated over the lifetime of -// the service. -func InstrumentingMiddleware(ints, chars metrics.Counter) Middleware { - return func(next Service) Service { - return instrumentingMiddleware{ - ints: ints, - chars: chars, - next: next, - } - } -} - -type instrumentingMiddleware struct { - ints metrics.Counter - chars metrics.Counter - next Service -} - -func (mw instrumentingMiddleware) Sum(ctx context.Context, a, b int) (int, error) { - v, err := mw.next.Sum(ctx, a, b) - mw.ints.Add(float64(v)) - return v, err -} - -func (mw instrumentingMiddleware) Concat(ctx context.Context, a, b string) (string, error) { - v, err := mw.next.Concat(ctx, a, b) - mw.chars.Add(float64(len(v))) - return v, err -} diff --git a/examples/addsvc/pkg/addservice/service.go b/examples/addsvc/pkg/addservice/service.go deleted file mode 100644 index d884373bf..000000000 --- a/examples/addsvc/pkg/addservice/service.go +++ /dev/null @@ -1,71 +0,0 @@ -package addservice - -import ( - "context" - "errors" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/metrics" -) - -// Service describes a service that adds things together. -type Service interface { - Sum(ctx context.Context, a, b int) (int, error) - Concat(ctx context.Context, a, b string) (string, error) -} - -// New returns a basic Service with all of the expected middlewares wired in. -func New(logger log.Logger, ints, chars metrics.Counter) Service { - var svc Service - { - svc = NewBasicService() - svc = LoggingMiddleware(logger)(svc) - svc = InstrumentingMiddleware(ints, chars)(svc) - } - return svc -} - -var ( - // ErrTwoZeroes is an arbitrary business rule for the Add method. - ErrTwoZeroes = errors.New("can't sum two zeroes") - - // ErrIntOverflow protects the Add method. We've decided that this error - // indicates a misbehaving service and should count against e.g. circuit - // breakers. So, we return it directly in endpoints, to illustrate the - // difference. In a real service, this probably wouldn't be the case. - ErrIntOverflow = errors.New("integer overflow") - - // ErrMaxSizeExceeded protects the Concat method. - ErrMaxSizeExceeded = errors.New("result exceeds maximum size") -) - -// NewBasicService returns a naïve, stateless implementation of Service. -func NewBasicService() Service { - return basicService{} -} - -type basicService struct{} - -const ( - intMax = 1<<31 - 1 - intMin = -(intMax + 1) - maxLen = 10 -) - -func (s basicService) Sum(_ context.Context, a, b int) (int, error) { - if a == 0 && b == 0 { - return 0, ErrTwoZeroes - } - if (b > 0 && a > (intMax-b)) || (b < 0 && a < (intMin-b)) { - return 0, ErrIntOverflow - } - return a + b, nil -} - -// Concat implements Service. -func (s basicService) Concat(_ context.Context, a, b string) (string, error) { - if len(a)+len(b) > maxLen { - return "", ErrMaxSizeExceeded - } - return a + b, nil -} diff --git a/examples/addsvc/pkg/addtransport/grpc.go b/examples/addsvc/pkg/addtransport/grpc.go deleted file mode 100644 index c6441a6b2..000000000 --- a/examples/addsvc/pkg/addtransport/grpc.go +++ /dev/null @@ -1,240 +0,0 @@ -package addtransport - -import ( - "context" - "errors" - "time" - - "google.golang.org/grpc" - - stdopentracing "github.com/opentracing/opentracing-go" - stdzipkin "github.com/openzipkin/zipkin-go" - "github.com/sony/gobreaker" - "golang.org/x/time/rate" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/tracing/opentracing" - "github.com/go-kit/kit/tracing/zipkin" - "github.com/go-kit/kit/transport" - grpctransport "github.com/go-kit/kit/transport/grpc" - - "github.com/go-kit/kit/examples/addsvc/pb" - "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" -) - -type grpcServer struct { - sum grpctransport.Handler - concat grpctransport.Handler -} - -// NewGRPCServer makes a set of endpoints available as a gRPC AddServer. -func NewGRPCServer(endpoints addendpoint.Set, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) pb.AddServer { - options := []grpctransport.ServerOption{ - grpctransport.ServerErrorHandler(transport.NewLogErrorHandler(logger)), - } - - if zipkinTracer != nil { - // Zipkin GRPC Server Trace can either be instantiated per gRPC method with a - // provided operation name or a global tracing service can be instantiated - // without an operation name and fed to each Go kit gRPC server as a - // ServerOption. - // In the latter case, the operation name will be the endpoint's grpc method - // path if used in combination with the Go kit gRPC Interceptor. - // - // In this example, we demonstrate a global Zipkin tracing service with - // Go kit gRPC Interceptor. - options = append(options, zipkin.GRPCServerTrace(zipkinTracer)) - } - - return &grpcServer{ - sum: grpctransport.NewServer( - endpoints.SumEndpoint, - decodeGRPCSumRequest, - encodeGRPCSumResponse, - append(options, grpctransport.ServerBefore(opentracing.GRPCToContext(otTracer, "Sum", logger)))..., - ), - concat: grpctransport.NewServer( - endpoints.ConcatEndpoint, - decodeGRPCConcatRequest, - encodeGRPCConcatResponse, - append(options, grpctransport.ServerBefore(opentracing.GRPCToContext(otTracer, "Concat", logger)))..., - ), - } -} - -func (s *grpcServer) Sum(ctx context.Context, req *pb.SumRequest) (*pb.SumReply, error) { - _, rep, err := s.sum.ServeGRPC(ctx, req) - if err != nil { - return nil, err - } - return rep.(*pb.SumReply), nil -} - -func (s *grpcServer) Concat(ctx context.Context, req *pb.ConcatRequest) (*pb.ConcatReply, error) { - _, rep, err := s.concat.ServeGRPC(ctx, req) - if err != nil { - return nil, err - } - return rep.(*pb.ConcatReply), nil -} - -// NewGRPCClient returns an AddService backed by a gRPC server at the other end -// of the conn. The caller is responsible for constructing the conn, and -// eventually closing the underlying transport. We bake-in certain middlewares, -// implementing the client library pattern. -func NewGRPCClient(conn *grpc.ClientConn, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) addservice.Service { - // We construct a single ratelimiter middleware, to limit the total outgoing - // QPS from this client to all methods on the remote instance. We also - // construct per-endpoint circuitbreaker middlewares to demonstrate how - // that's done, although they could easily be combined into a single breaker - // for the entire remote instance, too. - limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100)) - - // global client middlewares - var options []grpctransport.ClientOption - - if zipkinTracer != nil { - // Zipkin GRPC Client Trace can either be instantiated per gRPC method with a - // provided operation name or a global tracing client can be instantiated - // without an operation name and fed to each Go kit client as ClientOption. - // In the latter case, the operation name will be the endpoint's grpc method - // path. - // - // In this example, we demonstrace a global tracing client. - options = append(options, zipkin.GRPCClientTrace(zipkinTracer)) - - } - // Each individual endpoint is an grpc/transport.Client (which implements - // endpoint.Endpoint) that gets wrapped with various middlewares. If you - // made your own client library, you'd do this work there, so your server - // could rely on a consistent set of client behavior. - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = grpctransport.NewClient( - conn, - "pb.Add", - "Sum", - encodeGRPCSumRequest, - decodeGRPCSumResponse, - pb.SumReply{}, - append(options, grpctransport.ClientBefore(opentracing.ContextToGRPC(otTracer, logger)))..., - ).Endpoint() - sumEndpoint = opentracing.TraceClient(otTracer, "Sum")(sumEndpoint) - sumEndpoint = limiter(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Sum", - Timeout: 30 * time.Second, - }))(sumEndpoint) - } - - // The Concat endpoint is the same thing, with slightly different - // middlewares to demonstrate how to specialize per-endpoint. - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = grpctransport.NewClient( - conn, - "pb.Add", - "Concat", - encodeGRPCConcatRequest, - decodeGRPCConcatResponse, - pb.ConcatReply{}, - append(options, grpctransport.ClientBefore(opentracing.ContextToGRPC(otTracer, logger)))..., - ).Endpoint() - concatEndpoint = opentracing.TraceClient(otTracer, "Concat")(concatEndpoint) - concatEndpoint = limiter(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Concat", - Timeout: 10 * time.Second, - }))(concatEndpoint) - } - - // Returning the endpoint.Set as a service.Service relies on the - // endpoint.Set implementing the Service methods. That's just a simple bit - // of glue code. - return addendpoint.Set{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - } -} - -// decodeGRPCSumRequest is a transport/grpc.DecodeRequestFunc that converts a -// gRPC sum request to a user-domain sum request. Primarily useful in a server. -func decodeGRPCSumRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*pb.SumRequest) - return addendpoint.SumRequest{A: int(req.A), B: int(req.B)}, nil -} - -// decodeGRPCConcatRequest is a transport/grpc.DecodeRequestFunc that converts a -// gRPC concat request to a user-domain concat request. Primarily useful in a -// server. -func decodeGRPCConcatRequest(_ context.Context, grpcReq interface{}) (interface{}, error) { - req := grpcReq.(*pb.ConcatRequest) - return addendpoint.ConcatRequest{A: req.A, B: req.B}, nil -} - -// decodeGRPCSumResponse is a transport/grpc.DecodeResponseFunc that converts a -// gRPC sum reply to a user-domain sum response. Primarily useful in a client. -func decodeGRPCSumResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { - reply := grpcReply.(*pb.SumReply) - return addendpoint.SumResponse{V: int(reply.V), Err: str2err(reply.Err)}, nil -} - -// decodeGRPCConcatResponse is a transport/grpc.DecodeResponseFunc that converts -// a gRPC concat reply to a user-domain concat response. Primarily useful in a -// client. -func decodeGRPCConcatResponse(_ context.Context, grpcReply interface{}) (interface{}, error) { - reply := grpcReply.(*pb.ConcatReply) - return addendpoint.ConcatResponse{V: reply.V, Err: str2err(reply.Err)}, nil -} - -// encodeGRPCSumResponse is a transport/grpc.EncodeResponseFunc that converts a -// user-domain sum response to a gRPC sum reply. Primarily useful in a server. -func encodeGRPCSumResponse(_ context.Context, response interface{}) (interface{}, error) { - resp := response.(addendpoint.SumResponse) - return &pb.SumReply{V: int64(resp.V), Err: err2str(resp.Err)}, nil -} - -// encodeGRPCConcatResponse is a transport/grpc.EncodeResponseFunc that converts -// a user-domain concat response to a gRPC concat reply. Primarily useful in a -// server. -func encodeGRPCConcatResponse(_ context.Context, response interface{}) (interface{}, error) { - resp := response.(addendpoint.ConcatResponse) - return &pb.ConcatReply{V: resp.V, Err: err2str(resp.Err)}, nil -} - -// encodeGRPCSumRequest is a transport/grpc.EncodeRequestFunc that converts a -// user-domain sum request to a gRPC sum request. Primarily useful in a client. -func encodeGRPCSumRequest(_ context.Context, request interface{}) (interface{}, error) { - req := request.(addendpoint.SumRequest) - return &pb.SumRequest{A: int64(req.A), B: int64(req.B)}, nil -} - -// encodeGRPCConcatRequest is a transport/grpc.EncodeRequestFunc that converts a -// user-domain concat request to a gRPC concat request. Primarily useful in a -// client. -func encodeGRPCConcatRequest(_ context.Context, request interface{}) (interface{}, error) { - req := request.(addendpoint.ConcatRequest) - return &pb.ConcatRequest{A: req.A, B: req.B}, nil -} - -// These annoying helper functions are required to translate Go error types to -// and from strings, which is the type we use in our IDLs to represent errors. -// There is special casing to treat empty strings as nil errors. - -func str2err(s string) error { - if s == "" { - return nil - } - return errors.New(s) -} - -func err2str(err error) string { - if err == nil { - return "" - } - return err.Error() -} diff --git a/examples/addsvc/pkg/addtransport/http.go b/examples/addsvc/pkg/addtransport/http.go deleted file mode 100644 index 6500be04a..000000000 --- a/examples/addsvc/pkg/addtransport/http.go +++ /dev/null @@ -1,250 +0,0 @@ -package addtransport - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "io/ioutil" - "net/http" - "net/url" - "strings" - "time" - - "golang.org/x/time/rate" - - stdopentracing "github.com/opentracing/opentracing-go" - stdzipkin "github.com/openzipkin/zipkin-go" - "github.com/sony/gobreaker" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/tracing/opentracing" - "github.com/go-kit/kit/tracing/zipkin" - "github.com/go-kit/kit/transport" - httptransport "github.com/go-kit/kit/transport/http" - - "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" -) - -// NewHTTPHandler returns an HTTP handler that makes a set of endpoints -// available on predefined paths. -func NewHTTPHandler(endpoints addendpoint.Set, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) http.Handler { - options := []httptransport.ServerOption{ - httptransport.ServerErrorEncoder(errorEncoder), - httptransport.ServerErrorHandler(transport.NewLogErrorHandler(logger)), - } - - if zipkinTracer != nil { - // Zipkin HTTP Server Trace can either be instantiated per endpoint with a - // provided operation name or a global tracing service can be instantiated - // without an operation name and fed to each Go kit endpoint as ServerOption. - // In the latter case, the operation name will be the endpoint's http method. - // We demonstrate a global tracing service here. - options = append(options, zipkin.HTTPServerTrace(zipkinTracer)) - } - - m := http.NewServeMux() - m.Handle("/sum", httptransport.NewServer( - endpoints.SumEndpoint, - decodeHTTPSumRequest, - encodeHTTPGenericResponse, - append(options, httptransport.ServerBefore(opentracing.HTTPToContext(otTracer, "Sum", logger)))..., - )) - m.Handle("/concat", httptransport.NewServer( - endpoints.ConcatEndpoint, - decodeHTTPConcatRequest, - encodeHTTPGenericResponse, - append(options, httptransport.ServerBefore(opentracing.HTTPToContext(otTracer, "Concat", logger)))..., - )) - return m -} - -// NewHTTPClient returns an AddService backed by an HTTP server living at the -// remote instance. We expect instance to come from a service discovery system, -// so likely of the form "host:port". We bake-in certain middlewares, -// implementing the client library pattern. -func NewHTTPClient(instance string, otTracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) (addservice.Service, error) { - // Quickly sanitize the instance string. - if !strings.HasPrefix(instance, "http") { - instance = "http://" + instance - } - u, err := url.Parse(instance) - if err != nil { - return nil, err - } - - // We construct a single ratelimiter middleware, to limit the total outgoing - // QPS from this client to all methods on the remote instance. We also - // construct per-endpoint circuitbreaker middlewares to demonstrate how - // that's done, although they could easily be combined into a single breaker - // for the entire remote instance, too. - limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100)) - - // global client middlewares - var options []httptransport.ClientOption - - if zipkinTracer != nil { - // Zipkin HTTP Client Trace can either be instantiated per endpoint with a - // provided operation name or a global tracing client can be instantiated - // without an operation name and fed to each Go kit endpoint as ClientOption. - // In the latter case, the operation name will be the endpoint's http method. - options = append(options, zipkin.HTTPClientTrace(zipkinTracer)) - } - - // Each individual endpoint is an http/transport.Client (which implements - // endpoint.Endpoint) that gets wrapped with various middlewares. If you - // made your own client library, you'd do this work there, so your server - // could rely on a consistent set of client behavior. - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = httptransport.NewClient( - "POST", - copyURL(u, "/sum"), - encodeHTTPGenericRequest, - decodeHTTPSumResponse, - append(options, httptransport.ClientBefore(opentracing.ContextToHTTP(otTracer, logger)))..., - ).Endpoint() - sumEndpoint = opentracing.TraceClient(otTracer, "Sum")(sumEndpoint) - if zipkinTracer != nil { - sumEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Sum")(sumEndpoint) - } - sumEndpoint = limiter(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Sum", - Timeout: 30 * time.Second, - }))(sumEndpoint) - } - - // The Concat endpoint is the same thing, with slightly different - // middlewares to demonstrate how to specialize per-endpoint. - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = httptransport.NewClient( - "POST", - copyURL(u, "/concat"), - encodeHTTPGenericRequest, - decodeHTTPConcatResponse, - append(options, httptransport.ClientBefore(opentracing.ContextToHTTP(otTracer, logger)))..., - ).Endpoint() - concatEndpoint = opentracing.TraceClient(otTracer, "Concat")(concatEndpoint) - if zipkinTracer != nil { - concatEndpoint = zipkin.TraceEndpoint(zipkinTracer, "Concat")(concatEndpoint) - } - concatEndpoint = limiter(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Concat", - Timeout: 10 * time.Second, - }))(concatEndpoint) - } - - // Returning the endpoint.Set as a service.Service relies on the - // endpoint.Set implementing the Service methods. That's just a simple bit - // of glue code. - return addendpoint.Set{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - }, nil -} - -func copyURL(base *url.URL, path string) *url.URL { - next := *base - next.Path = path - return &next -} - -func errorEncoder(_ context.Context, err error, w http.ResponseWriter) { - w.WriteHeader(err2code(err)) - json.NewEncoder(w).Encode(errorWrapper{Error: err.Error()}) -} - -func err2code(err error) int { - switch err { - case addservice.ErrTwoZeroes, addservice.ErrMaxSizeExceeded, addservice.ErrIntOverflow: - return http.StatusBadRequest - } - return http.StatusInternalServerError -} - -func errorDecoder(r *http.Response) error { - var w errorWrapper - if err := json.NewDecoder(r.Body).Decode(&w); err != nil { - return err - } - return errors.New(w.Error) -} - -type errorWrapper struct { - Error string `json:"error"` -} - -// decodeHTTPSumRequest is a transport/http.DecodeRequestFunc that decodes a -// JSON-encoded sum request from the HTTP request body. Primarily useful in a -// server. -func decodeHTTPSumRequest(_ context.Context, r *http.Request) (interface{}, error) { - var req addendpoint.SumRequest - err := json.NewDecoder(r.Body).Decode(&req) - return req, err -} - -// decodeHTTPConcatRequest is a transport/http.DecodeRequestFunc that decodes a -// JSON-encoded concat request from the HTTP request body. Primarily useful in a -// server. -func decodeHTTPConcatRequest(_ context.Context, r *http.Request) (interface{}, error) { - var req addendpoint.ConcatRequest - err := json.NewDecoder(r.Body).Decode(&req) - return req, err -} - -// decodeHTTPSumResponse is a transport/http.DecodeResponseFunc that decodes a -// JSON-encoded sum response from the HTTP response body. If the response has a -// non-200 status code, we will interpret that as an error and attempt to decode -// the specific error message from the response body. Primarily useful in a -// client. -func decodeHTTPSumResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errors.New(r.Status) - } - var resp addendpoint.SumResponse - err := json.NewDecoder(r.Body).Decode(&resp) - return resp, err -} - -// decodeHTTPConcatResponse is a transport/http.DecodeResponseFunc that decodes -// a JSON-encoded concat response from the HTTP response body. If the response -// has a non-200 status code, we will interpret that as an error and attempt to -// decode the specific error message from the response body. Primarily useful in -// a client. -func decodeHTTPConcatResponse(_ context.Context, r *http.Response) (interface{}, error) { - if r.StatusCode != http.StatusOK { - return nil, errors.New(r.Status) - } - var resp addendpoint.ConcatResponse - err := json.NewDecoder(r.Body).Decode(&resp) - return resp, err -} - -// encodeHTTPGenericRequest is a transport/http.EncodeRequestFunc that -// JSON-encodes any request to the request body. Primarily useful in a client. -func encodeHTTPGenericRequest(_ context.Context, r *http.Request, request interface{}) error { - var buf bytes.Buffer - if err := json.NewEncoder(&buf).Encode(request); err != nil { - return err - } - r.Body = ioutil.NopCloser(&buf) - return nil -} - -// encodeHTTPGenericResponse is a transport/http.EncodeResponseFunc that encodes -// the response as JSON to the response writer. Primarily useful in a server. -func encodeHTTPGenericResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { - if f, ok := response.(endpoint.Failer); ok && f.Failed() != nil { - errorEncoder(ctx, f.Failed(), w) - return nil - } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - return json.NewEncoder(w).Encode(response) -} diff --git a/examples/addsvc/pkg/addtransport/jsonrpc.go b/examples/addsvc/pkg/addtransport/jsonrpc.go deleted file mode 100644 index a8975ef49..000000000 --- a/examples/addsvc/pkg/addtransport/jsonrpc.go +++ /dev/null @@ -1,213 +0,0 @@ -package addtransport - -import ( - "context" - "encoding/json" - "fmt" - "net/url" - "strings" - "time" - - "golang.org/x/time/rate" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/tracing/opentracing" - "github.com/go-kit/kit/transport/http/jsonrpc" - stdopentracing "github.com/opentracing/opentracing-go" - "github.com/sony/gobreaker" -) - -// NewJSONRPCHandler returns a JSON RPC Server/Handler that can be passed to http.Handle() -func NewJSONRPCHandler(endpoints addendpoint.Set, logger log.Logger) *jsonrpc.Server { - handler := jsonrpc.NewServer( - makeEndpointCodecMap(endpoints), - jsonrpc.ServerErrorLogger(logger), - ) - return handler -} - -// NewJSONRPCClient returns an addservice backed by a JSON RPC over HTTP server -// living at the remote instance. We expect instance to come from a service -// discovery system, so likely of the form "host:port". We bake-in certain -// middlewares, implementing the client library pattern. -func NewJSONRPCClient(instance string, tracer stdopentracing.Tracer, logger log.Logger) (addservice.Service, error) { - // Quickly sanitize the instance string. - if !strings.HasPrefix(instance, "http") { - instance = "http://" + instance - } - u, err := url.Parse(instance) - if err != nil { - return nil, err - } - - // We construct a single ratelimiter middleware, to limit the total outgoing - // QPS from this client to all methods on the remote instance. We also - // construct per-endpoint circuitbreaker middlewares to demonstrate how - // that's done, although they could easily be combined into a single breaker - // for the entire remote instance, too. - limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100)) - - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = jsonrpc.NewClient( - u, - "sum", - jsonrpc.ClientRequestEncoder(encodeSumRequest), - jsonrpc.ClientResponseDecoder(decodeSumResponse), - ).Endpoint() - sumEndpoint = opentracing.TraceClient(tracer, "Sum")(sumEndpoint) - sumEndpoint = limiter(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Sum", - Timeout: 30 * time.Second, - }))(sumEndpoint) - } - - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = jsonrpc.NewClient( - u, - "concat", - jsonrpc.ClientRequestEncoder(encodeConcatRequest), - jsonrpc.ClientResponseDecoder(decodeConcatResponse), - ).Endpoint() - concatEndpoint = opentracing.TraceClient(tracer, "Concat")(concatEndpoint) - concatEndpoint = limiter(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Concat", - Timeout: 30 * time.Second, - }))(concatEndpoint) - } - - // Returning the endpoint.Set as a service.Service relies on the - // endpoint.Set implementing the Service methods. That's just a simple bit - // of glue code. - return addendpoint.Set{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - }, nil - -} - -// makeEndpointCodecMap returns a codec map configured for the addsvc. -func makeEndpointCodecMap(endpoints addendpoint.Set) jsonrpc.EndpointCodecMap { - return jsonrpc.EndpointCodecMap{ - "sum": jsonrpc.EndpointCodec{ - Endpoint: endpoints.SumEndpoint, - Decode: decodeSumRequest, - Encode: encodeSumResponse, - }, - "concat": jsonrpc.EndpointCodec{ - Endpoint: endpoints.ConcatEndpoint, - Decode: decodeConcatRequest, - Encode: encodeConcatResponse, - }, - } -} - -func decodeSumRequest(_ context.Context, msg json.RawMessage) (interface{}, error) { - var req addendpoint.SumRequest - err := json.Unmarshal(msg, &req) - if err != nil { - return nil, &jsonrpc.Error{ - Code: -32000, - Message: fmt.Sprintf("couldn't unmarshal body to sum request: %s", err), - } - } - return req, nil -} - -func encodeSumResponse(_ context.Context, obj interface{}) (json.RawMessage, error) { - res, ok := obj.(addendpoint.SumResponse) - if !ok { - return nil, &jsonrpc.Error{ - Code: -32000, - Message: fmt.Sprintf("Asserting result to *SumResponse failed. Got %T, %+v", obj, obj), - } - } - b, err := json.Marshal(res) - if err != nil { - return nil, fmt.Errorf("couldn't marshal response: %s", err) - } - return b, nil -} - -func decodeSumResponse(_ context.Context, res jsonrpc.Response) (interface{}, error) { - if res.Error != nil { - return nil, *res.Error - } - var sumres addendpoint.SumResponse - err := json.Unmarshal(res.Result, &sumres) - if err != nil { - return nil, fmt.Errorf("couldn't unmarshal body to SumResponse: %s", err) - } - return sumres, nil -} - -func encodeSumRequest(_ context.Context, obj interface{}) (json.RawMessage, error) { - req, ok := obj.(addendpoint.SumRequest) - if !ok { - return nil, fmt.Errorf("couldn't assert request as SumRequest, got %T", obj) - } - b, err := json.Marshal(req) - if err != nil { - return nil, fmt.Errorf("couldn't marshal request: %s", err) - } - return b, nil -} - -func decodeConcatRequest(_ context.Context, msg json.RawMessage) (interface{}, error) { - var req addendpoint.ConcatRequest - err := json.Unmarshal(msg, &req) - if err != nil { - return nil, &jsonrpc.Error{ - Code: -32000, - Message: fmt.Sprintf("couldn't unmarshal body to concat request: %s", err), - } - } - return req, nil -} - -func encodeConcatResponse(_ context.Context, obj interface{}) (json.RawMessage, error) { - res, ok := obj.(addendpoint.ConcatResponse) - if !ok { - return nil, &jsonrpc.Error{ - Code: -32000, - Message: fmt.Sprintf("Asserting result to *ConcatResponse failed. Got %T, %+v", obj, obj), - } - } - b, err := json.Marshal(res) - if err != nil { - return nil, fmt.Errorf("couldn't marshal response: %s", err) - } - return b, nil -} - -func decodeConcatResponse(_ context.Context, res jsonrpc.Response) (interface{}, error) { - if res.Error != nil { - return nil, *res.Error - } - var concatres addendpoint.ConcatResponse - err := json.Unmarshal(res.Result, &concatres) - if err != nil { - return nil, fmt.Errorf("couldn't unmarshal body to ConcatResponse: %s", err) - } - return concatres, nil -} - -func encodeConcatRequest(_ context.Context, obj interface{}) (json.RawMessage, error) { - req, ok := obj.(addendpoint.ConcatRequest) - if !ok { - return nil, fmt.Errorf("couldn't assert request as ConcatRequest, got %T", obj) - } - b, err := json.Marshal(req) - if err != nil { - return nil, fmt.Errorf("couldn't marshal request: %s", err) - } - return b, nil -} diff --git a/examples/addsvc/pkg/addtransport/thrift.go b/examples/addsvc/pkg/addtransport/thrift.go deleted file mode 100644 index 485840fe0..000000000 --- a/examples/addsvc/pkg/addtransport/thrift.go +++ /dev/null @@ -1,120 +0,0 @@ -package addtransport - -import ( - "context" - "time" - - "golang.org/x/time/rate" - - "github.com/sony/gobreaker" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/ratelimit" - - "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" - addthrift "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" -) - -type thriftServer struct { - ctx context.Context - endpoints addendpoint.Set -} - -// NewThriftServer makes a set of endpoints available as a Thrift service. -func NewThriftServer(endpoints addendpoint.Set) addthrift.AddService { - return &thriftServer{ - endpoints: endpoints, - } -} - -func (s *thriftServer) Sum(ctx context.Context, a int64, b int64) (*addthrift.SumReply, error) { - request := addendpoint.SumRequest{A: int(a), B: int(b)} - response, err := s.endpoints.SumEndpoint(ctx, request) - if err != nil { - return nil, err - } - resp := response.(addendpoint.SumResponse) - return &addthrift.SumReply{Value: int64(resp.V), Err: err2str(resp.Err)}, nil -} - -func (s *thriftServer) Concat(ctx context.Context, a string, b string) (*addthrift.ConcatReply, error) { - request := addendpoint.ConcatRequest{A: a, B: b} - response, err := s.endpoints.ConcatEndpoint(ctx, request) - if err != nil { - return nil, err - } - resp := response.(addendpoint.ConcatResponse) - return &addthrift.ConcatReply{Value: resp.V, Err: err2str(resp.Err)}, nil -} - -// NewThriftClient returns an AddService backed by a Thrift server described by -// the provided client. The caller is responsible for constructing the client, -// and eventually closing the underlying transport. We bake-in certain middlewares, -// implementing the client library pattern. -func NewThriftClient(client *addthrift.AddServiceClient) addservice.Service { - // We construct a single ratelimiter middleware, to limit the total outgoing - // QPS from this client to all methods on the remote instance. We also - // construct per-endpoint circuitbreaker middlewares to demonstrate how - // that's done, although they could easily be combined into a single breaker - // for the entire remote instance, too. - limiter := ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 100)) - - // Each individual endpoint is an http/transport.Client (which implements - // endpoint.Endpoint) that gets wrapped with various middlewares. If you - // could rely on a consistent set of client behavior. - var sumEndpoint endpoint.Endpoint - { - sumEndpoint = MakeThriftSumEndpoint(client) - sumEndpoint = limiter(sumEndpoint) - sumEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Sum", - Timeout: 30 * time.Second, - }))(sumEndpoint) - } - - // The Concat endpoint is the same thing, with slightly different - // middlewares to demonstrate how to specialize per-endpoint. - var concatEndpoint endpoint.Endpoint - { - concatEndpoint = MakeThriftConcatEndpoint(client) - concatEndpoint = limiter(concatEndpoint) - concatEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{ - Name: "Concat", - Timeout: 10 * time.Second, - }))(concatEndpoint) - } - - // Returning the endpoint.Set as a service.Service relies on the - // endpoint.Set implementing the Service methods. That's just a simple bit - // of glue code. - return addendpoint.Set{ - SumEndpoint: sumEndpoint, - ConcatEndpoint: concatEndpoint, - } -} - -// MakeThriftSumEndpoint returns an endpoint that invokes the passed Thrift client. -// Useful only in clients, and only until a proper transport/thrift.Client exists. -func MakeThriftSumEndpoint(client *addthrift.AddServiceClient) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(addendpoint.SumRequest) - reply, err := client.Sum(ctx, int64(req.A), int64(req.B)) - if err == addservice.ErrIntOverflow { - return nil, err // special case; see comment on ErrIntOverflow - } - return addendpoint.SumResponse{V: int(reply.Value), Err: err}, nil - } -} - -// MakeThriftConcatEndpoint returns an endpoint that invokes the passed Thrift -// client. Useful only in clients, and only until a proper -// transport/thrift.Client exists. -func MakeThriftConcatEndpoint(client *addthrift.AddServiceClient) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(addendpoint.ConcatRequest) - reply, err := client.Concat(ctx, req.A, req.B) - return addendpoint.ConcatResponse{V: reply.Value, Err: err}, nil - } -} diff --git a/examples/addsvc/thrift/addsvc.thrift b/examples/addsvc/thrift/addsvc.thrift deleted file mode 100644 index e67ce1b21..000000000 --- a/examples/addsvc/thrift/addsvc.thrift +++ /dev/null @@ -1,14 +0,0 @@ -struct SumReply { - 1: i64 value - 2: string err -} - -struct ConcatReply { - 1: string value - 2: string err -} - -service AddService { - SumReply Sum(1: i64 a, 2: i64 b) - ConcatReply Concat(1: string a, 2: string b) -} diff --git a/examples/addsvc/thrift/compile.sh b/examples/addsvc/thrift/compile.sh deleted file mode 100755 index 293e68e0e..000000000 --- a/examples/addsvc/thrift/compile.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env sh - -# See also https://thrift.apache.org/tutorial/go. -# -# An old version can be obtained via `brew install thrift`. -# For the latest, here's the annoying dance: -# -# brew install automake bison pkg-config openssl -# ln -s /usr/local/opt/openssl/include/openssl /usr/local/include # if it isn't already -# git clone git@github.com:apache/thrift -# ./bootstrap.sh -# bash -# export PATH=/usr/local/Cellar/bison/*/bin:$PATH -# ./configure ./configure --without-qt4 --without-qt5 --without-c_glib --without-csharp --without-java --without-erlang --without-nodejs --without-lua --without-python --without-perl --without-php --without-php_extension --without-dart --without-ruby --without-haskell --without-rs --without-cl --without-haxe --without-dotnetcore --without-d -# make -# sudo make install - -thrift -r --gen "go:package_prefix=github.com/go-kit/kit/examples/addsvc/thrift/gen-go/,thrift_import=github.com/apache/thrift/lib/go/thrift" addsvc.thrift diff --git a/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go b/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go deleted file mode 100644 index 272dacc00..000000000 --- a/examples/addsvc/thrift/gen-go/addsvc/GoUnusedProtection__.go +++ /dev/null @@ -1,5 +0,0 @@ -// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. - -package addsvc - -var GoUnusedProtection__ int diff --git a/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go b/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go deleted file mode 100755 index ee8ec5602..000000000 --- a/examples/addsvc/thrift/gen-go/addsvc/add_service-remote/add_service-remote.go +++ /dev/null @@ -1,186 +0,0 @@ -// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. - -package main - -import ( - "context" - "flag" - "fmt" - "github.com/apache/thrift/lib/go/thrift" - "github.com/go-kit/kit/examples/addsvc/thrift/gen-go/addsvc" - "math" - "net" - "net/url" - "os" - "strconv" - "strings" -) - -var _ = addsvc.GoUnusedProtection__ - -func Usage() { - fmt.Fprintln(os.Stderr, "Usage of ", os.Args[0], " [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]:") - flag.PrintDefaults() - fmt.Fprintln(os.Stderr, "\nFunctions:") - fmt.Fprintln(os.Stderr, " SumReply Sum(i64 a, i64 b)") - fmt.Fprintln(os.Stderr, " ConcatReply Concat(string a, string b)") - fmt.Fprintln(os.Stderr) - os.Exit(0) -} - -type httpHeaders map[string]string - -func (h httpHeaders) String() string { - var m map[string]string = h - return fmt.Sprintf("%s", m) -} - -func (h httpHeaders) Set(value string) error { - parts := strings.Split(value, ": ") - if len(parts) != 2 { - return fmt.Errorf("header should be of format 'Key: Value'") - } - h[parts[0]] = parts[1] - return nil -} - -func main() { - flag.Usage = Usage - var host string - var port int - var protocol string - var urlString string - var framed bool - var useHttp bool - headers := make(httpHeaders) - var parsedUrl *url.URL - var trans thrift.TTransport - _ = strconv.Atoi - _ = math.Abs - flag.Usage = Usage - flag.StringVar(&host, "h", "localhost", "Specify host and port") - flag.IntVar(&port, "p", 9090, "Specify port") - flag.StringVar(&protocol, "P", "binary", "Specify the protocol (binary, compact, simplejson, json)") - flag.StringVar(&urlString, "u", "", "Specify the url") - flag.BoolVar(&framed, "framed", false, "Use framed transport") - flag.BoolVar(&useHttp, "http", false, "Use http") - flag.Var(headers, "H", "Headers to set on the http(s) request (e.g. -H \"Key: Value\")") - flag.Parse() - - if len(urlString) > 0 { - var err error - parsedUrl, err = url.Parse(urlString) - if err != nil { - fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) - flag.Usage() - } - host = parsedUrl.Host - useHttp = len(parsedUrl.Scheme) <= 0 || parsedUrl.Scheme == "http" || parsedUrl.Scheme == "https" - } else if useHttp { - _, err := url.Parse(fmt.Sprint("http://", host, ":", port)) - if err != nil { - fmt.Fprintln(os.Stderr, "Error parsing URL: ", err) - flag.Usage() - } - } - - cmd := flag.Arg(0) - var err error - if useHttp { - trans, err = thrift.NewTHttpClient(parsedUrl.String()) - if len(headers) > 0 { - httptrans := trans.(*thrift.THttpClient) - for key, value := range headers { - httptrans.SetHeader(key, value) - } - } - } else { - portStr := fmt.Sprint(port) - if strings.Contains(host, ":") { - host, portStr, err = net.SplitHostPort(host) - if err != nil { - fmt.Fprintln(os.Stderr, "error with host:", err) - os.Exit(1) - } - } - trans, err = thrift.NewTSocket(net.JoinHostPort(host, portStr)) - if err != nil { - fmt.Fprintln(os.Stderr, "error resolving address:", err) - os.Exit(1) - } - if framed { - trans = thrift.NewTFramedTransport(trans) - } - } - if err != nil { - fmt.Fprintln(os.Stderr, "Error creating transport", err) - os.Exit(1) - } - defer trans.Close() - var protocolFactory thrift.TProtocolFactory - switch protocol { - case "compact": - protocolFactory = thrift.NewTCompactProtocolFactory() - break - case "simplejson": - protocolFactory = thrift.NewTSimpleJSONProtocolFactory() - break - case "json": - protocolFactory = thrift.NewTJSONProtocolFactory() - break - case "binary", "": - protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() - break - default: - fmt.Fprintln(os.Stderr, "Invalid protocol specified: ", protocol) - Usage() - os.Exit(1) - } - iprot := protocolFactory.GetProtocol(trans) - oprot := protocolFactory.GetProtocol(trans) - client := addsvc.NewAddServiceClient(thrift.NewTStandardClient(iprot, oprot)) - if err := trans.Open(); err != nil { - fmt.Fprintln(os.Stderr, "Error opening socket to ", host, ":", port, " ", err) - os.Exit(1) - } - - switch cmd { - case "Sum": - if flag.NArg()-1 != 2 { - fmt.Fprintln(os.Stderr, "Sum requires 2 args") - flag.Usage() - } - argvalue0, err8 := (strconv.ParseInt(flag.Arg(1), 10, 64)) - if err8 != nil { - Usage() - return - } - value0 := argvalue0 - argvalue1, err9 := (strconv.ParseInt(flag.Arg(2), 10, 64)) - if err9 != nil { - Usage() - return - } - value1 := argvalue1 - fmt.Print(client.Sum(context.Background(), value0, value1)) - fmt.Print("\n") - break - case "Concat": - if flag.NArg()-1 != 2 { - fmt.Fprintln(os.Stderr, "Concat requires 2 args") - flag.Usage() - } - argvalue0 := flag.Arg(1) - value0 := argvalue0 - argvalue1 := flag.Arg(2) - value1 := argvalue1 - fmt.Print(client.Concat(context.Background(), value0, value1)) - fmt.Print("\n") - break - case "": - Usage() - break - default: - fmt.Fprintln(os.Stderr, "Invalid function ", cmd) - } -} diff --git a/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go b/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go deleted file mode 100644 index 9e269a15c..000000000 --- a/examples/addsvc/thrift/gen-go/addsvc/addsvc-consts.go +++ /dev/null @@ -1,21 +0,0 @@ -// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. - -package addsvc - -import ( - "bytes" - "context" - "fmt" - "github.com/apache/thrift/lib/go/thrift" - "time" -) - -// (needed to ensure safety because of naive import list construction.) -var _ = thrift.ZERO -var _ = fmt.Printf -var _ = context.Background -var _ = time.Now -var _ = bytes.Equal - -func init() { -} diff --git a/examples/addsvc/thrift/gen-go/addsvc/addsvc.go b/examples/addsvc/thrift/gen-go/addsvc/addsvc.go deleted file mode 100644 index 15dcc9737..000000000 --- a/examples/addsvc/thrift/gen-go/addsvc/addsvc.go +++ /dev/null @@ -1,1111 +0,0 @@ -// Code generated by Thrift Compiler (0.14.1). DO NOT EDIT. - -package addsvc - -import ( - "bytes" - "context" - "fmt" - "github.com/apache/thrift/lib/go/thrift" - "time" -) - -// (needed to ensure safety because of naive import list construction.) -var _ = thrift.ZERO -var _ = fmt.Printf -var _ = context.Background -var _ = time.Now -var _ = bytes.Equal - -// Attributes: -// - Value -// - Err -type SumReply struct { - Value int64 `thrift:"value,1" db:"value" json:"value"` - Err string `thrift:"err,2" db:"err" json:"err"` -} - -func NewSumReply() *SumReply { - return &SumReply{} -} - -func (p *SumReply) GetValue() int64 { - return p.Value -} - -func (p *SumReply) GetErr() string { - return p.Err -} -func (p *SumReply) Read(ctx context.Context, iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if fieldTypeId == thrift.I64 { - if err := p.ReadField1(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - case 2: - if fieldTypeId == thrift.STRING { - if err := p.ReadField2(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - default: - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(ctx); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *SumReply) ReadField1(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadI64(ctx); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.Value = v - } - return nil -} - -func (p *SumReply) ReadField2(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(ctx); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.Err = v - } - return nil -} - -func (p *SumReply) Write(ctx context.Context, oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin(ctx, "SumReply"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if p != nil { - if err := p.writeField1(ctx, oprot); err != nil { - return err - } - if err := p.writeField2(ctx, oprot); err != nil { - return err - } - } - if err := oprot.WriteFieldStop(ctx); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(ctx); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *SumReply) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "value", thrift.I64, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) - } - if err := oprot.WriteI64(ctx, int64(p.Value)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) - } - return err -} - -func (p *SumReply) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "err", thrift.STRING, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) - } - if err := oprot.WriteString(ctx, string(p.Err)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) - } - return err -} - -func (p *SumReply) Equals(other *SumReply) bool { - if p == other { - return true - } else if p == nil || other == nil { - return false - } - if p.Value != other.Value { - return false - } - if p.Err != other.Err { - return false - } - return true -} - -func (p *SumReply) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("SumReply(%+v)", *p) -} - -// Attributes: -// - Value -// - Err -type ConcatReply struct { - Value string `thrift:"value,1" db:"value" json:"value"` - Err string `thrift:"err,2" db:"err" json:"err"` -} - -func NewConcatReply() *ConcatReply { - return &ConcatReply{} -} - -func (p *ConcatReply) GetValue() string { - return p.Value -} - -func (p *ConcatReply) GetErr() string { - return p.Err -} -func (p *ConcatReply) Read(ctx context.Context, iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if fieldTypeId == thrift.STRING { - if err := p.ReadField1(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - case 2: - if fieldTypeId == thrift.STRING { - if err := p.ReadField2(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - default: - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(ctx); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *ConcatReply) ReadField1(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(ctx); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.Value = v - } - return nil -} - -func (p *ConcatReply) ReadField2(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(ctx); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.Err = v - } - return nil -} - -func (p *ConcatReply) Write(ctx context.Context, oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin(ctx, "ConcatReply"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if p != nil { - if err := p.writeField1(ctx, oprot); err != nil { - return err - } - if err := p.writeField2(ctx, oprot); err != nil { - return err - } - } - if err := oprot.WriteFieldStop(ctx); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(ctx); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *ConcatReply) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "value", thrift.STRING, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:value: ", p), err) - } - if err := oprot.WriteString(ctx, string(p.Value)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.value (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:value: ", p), err) - } - return err -} - -func (p *ConcatReply) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "err", thrift.STRING, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:err: ", p), err) - } - if err := oprot.WriteString(ctx, string(p.Err)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.err (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:err: ", p), err) - } - return err -} - -func (p *ConcatReply) Equals(other *ConcatReply) bool { - if p == other { - return true - } else if p == nil || other == nil { - return false - } - if p.Value != other.Value { - return false - } - if p.Err != other.Err { - return false - } - return true -} - -func (p *ConcatReply) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("ConcatReply(%+v)", *p) -} - -type AddService interface { - // Parameters: - // - A - // - B - Sum(ctx context.Context, a int64, b int64) (_r *SumReply, _err error) - // Parameters: - // - A - // - B - Concat(ctx context.Context, a string, b string) (_r *ConcatReply, _err error) -} - -type AddServiceClient struct { - c thrift.TClient - meta thrift.ResponseMeta -} - -func NewAddServiceClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *AddServiceClient { - return &AddServiceClient{ - c: thrift.NewTStandardClient(f.GetProtocol(t), f.GetProtocol(t)), - } -} - -func NewAddServiceClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *AddServiceClient { - return &AddServiceClient{ - c: thrift.NewTStandardClient(iprot, oprot), - } -} - -func NewAddServiceClient(c thrift.TClient) *AddServiceClient { - return &AddServiceClient{ - c: c, - } -} - -func (p *AddServiceClient) Client_() thrift.TClient { - return p.c -} - -func (p *AddServiceClient) LastResponseMeta_() thrift.ResponseMeta { - return p.meta -} - -func (p *AddServiceClient) SetLastResponseMeta_(meta thrift.ResponseMeta) { - p.meta = meta -} - -// Parameters: -// - A -// - B -func (p *AddServiceClient) Sum(ctx context.Context, a int64, b int64) (_r *SumReply, _err error) { - var _args0 AddServiceSumArgs - _args0.A = a - _args0.B = b - var _result2 AddServiceSumResult - var _meta1 thrift.ResponseMeta - _meta1, _err = p.Client_().Call(ctx, "Sum", &_args0, &_result2) - p.SetLastResponseMeta_(_meta1) - if _err != nil { - return - } - return _result2.GetSuccess(), nil -} - -// Parameters: -// - A -// - B -func (p *AddServiceClient) Concat(ctx context.Context, a string, b string) (_r *ConcatReply, _err error) { - var _args3 AddServiceConcatArgs - _args3.A = a - _args3.B = b - var _result5 AddServiceConcatResult - var _meta4 thrift.ResponseMeta - _meta4, _err = p.Client_().Call(ctx, "Concat", &_args3, &_result5) - p.SetLastResponseMeta_(_meta4) - if _err != nil { - return - } - return _result5.GetSuccess(), nil -} - -type AddServiceProcessor struct { - processorMap map[string]thrift.TProcessorFunction - handler AddService -} - -func (p *AddServiceProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) { - p.processorMap[key] = processor -} - -func (p *AddServiceProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) { - processor, ok = p.processorMap[key] - return processor, ok -} - -func (p *AddServiceProcessor) ProcessorMap() map[string]thrift.TProcessorFunction { - return p.processorMap -} - -func NewAddServiceProcessor(handler AddService) *AddServiceProcessor { - - self6 := &AddServiceProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)} - self6.processorMap["Sum"] = &addServiceProcessorSum{handler: handler} - self6.processorMap["Concat"] = &addServiceProcessorConcat{handler: handler} - return self6 -} - -func (p *AddServiceProcessor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { - name, _, seqId, err2 := iprot.ReadMessageBegin(ctx) - if err2 != nil { - return false, thrift.WrapTException(err2) - } - if processor, ok := p.GetProcessorFunction(name); ok { - return processor.Process(ctx, seqId, iprot, oprot) - } - iprot.Skip(ctx, thrift.STRUCT) - iprot.ReadMessageEnd(ctx) - x7 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name) - oprot.WriteMessageBegin(ctx, name, thrift.EXCEPTION, seqId) - x7.Write(ctx, oprot) - oprot.WriteMessageEnd(ctx) - oprot.Flush(ctx) - return false, x7 - -} - -type addServiceProcessorSum struct { - handler AddService -} - -func (p *addServiceProcessorSum) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { - args := AddServiceSumArgs{} - var err2 error - if err2 = args.Read(ctx, iprot); err2 != nil { - iprot.ReadMessageEnd(ctx) - x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err2.Error()) - oprot.WriteMessageBegin(ctx, "Sum", thrift.EXCEPTION, seqId) - x.Write(ctx, oprot) - oprot.WriteMessageEnd(ctx) - oprot.Flush(ctx) - return false, thrift.WrapTException(err2) - } - iprot.ReadMessageEnd(ctx) - - tickerCancel := func() {} - // Start a goroutine to do server side connectivity check. - if thrift.ServerConnectivityCheckInterval > 0 { - var cancel context.CancelFunc - ctx, cancel = context.WithCancel(ctx) - defer cancel() - var tickerCtx context.Context - tickerCtx, tickerCancel = context.WithCancel(context.Background()) - defer tickerCancel() - go func(ctx context.Context, cancel context.CancelFunc) { - ticker := time.NewTicker(thrift.ServerConnectivityCheckInterval) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - if !iprot.Transport().IsOpen() { - cancel() - return - } - } - } - }(tickerCtx, cancel) - } - - result := AddServiceSumResult{} - var retval *SumReply - if retval, err2 = p.handler.Sum(ctx, args.A, args.B); err2 != nil { - tickerCancel() - if err2 == thrift.ErrAbandonRequest { - return false, thrift.WrapTException(err2) - } - x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Sum: "+err2.Error()) - oprot.WriteMessageBegin(ctx, "Sum", thrift.EXCEPTION, seqId) - x.Write(ctx, oprot) - oprot.WriteMessageEnd(ctx) - oprot.Flush(ctx) - return true, thrift.WrapTException(err2) - } else { - result.Success = retval - } - tickerCancel() - if err2 = oprot.WriteMessageBegin(ctx, "Sum", thrift.REPLY, seqId); err2 != nil { - err = thrift.WrapTException(err2) - } - if err2 = result.Write(ctx, oprot); err == nil && err2 != nil { - err = thrift.WrapTException(err2) - } - if err2 = oprot.WriteMessageEnd(ctx); err == nil && err2 != nil { - err = thrift.WrapTException(err2) - } - if err2 = oprot.Flush(ctx); err == nil && err2 != nil { - err = thrift.WrapTException(err2) - } - if err != nil { - return - } - return true, err -} - -type addServiceProcessorConcat struct { - handler AddService -} - -func (p *addServiceProcessorConcat) Process(ctx context.Context, seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) { - args := AddServiceConcatArgs{} - var err2 error - if err2 = args.Read(ctx, iprot); err2 != nil { - iprot.ReadMessageEnd(ctx) - x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err2.Error()) - oprot.WriteMessageBegin(ctx, "Concat", thrift.EXCEPTION, seqId) - x.Write(ctx, oprot) - oprot.WriteMessageEnd(ctx) - oprot.Flush(ctx) - return false, thrift.WrapTException(err2) - } - iprot.ReadMessageEnd(ctx) - - tickerCancel := func() {} - // Start a goroutine to do server side connectivity check. - if thrift.ServerConnectivityCheckInterval > 0 { - var cancel context.CancelFunc - ctx, cancel = context.WithCancel(ctx) - defer cancel() - var tickerCtx context.Context - tickerCtx, tickerCancel = context.WithCancel(context.Background()) - defer tickerCancel() - go func(ctx context.Context, cancel context.CancelFunc) { - ticker := time.NewTicker(thrift.ServerConnectivityCheckInterval) - defer ticker.Stop() - for { - select { - case <-ctx.Done(): - return - case <-ticker.C: - if !iprot.Transport().IsOpen() { - cancel() - return - } - } - } - }(tickerCtx, cancel) - } - - result := AddServiceConcatResult{} - var retval *ConcatReply - if retval, err2 = p.handler.Concat(ctx, args.A, args.B); err2 != nil { - tickerCancel() - if err2 == thrift.ErrAbandonRequest { - return false, thrift.WrapTException(err2) - } - x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing Concat: "+err2.Error()) - oprot.WriteMessageBegin(ctx, "Concat", thrift.EXCEPTION, seqId) - x.Write(ctx, oprot) - oprot.WriteMessageEnd(ctx) - oprot.Flush(ctx) - return true, thrift.WrapTException(err2) - } else { - result.Success = retval - } - tickerCancel() - if err2 = oprot.WriteMessageBegin(ctx, "Concat", thrift.REPLY, seqId); err2 != nil { - err = thrift.WrapTException(err2) - } - if err2 = result.Write(ctx, oprot); err == nil && err2 != nil { - err = thrift.WrapTException(err2) - } - if err2 = oprot.WriteMessageEnd(ctx); err == nil && err2 != nil { - err = thrift.WrapTException(err2) - } - if err2 = oprot.Flush(ctx); err == nil && err2 != nil { - err = thrift.WrapTException(err2) - } - if err != nil { - return - } - return true, err -} - -// HELPER FUNCTIONS AND STRUCTURES - -// Attributes: -// - A -// - B -type AddServiceSumArgs struct { - A int64 `thrift:"a,1" db:"a" json:"a"` - B int64 `thrift:"b,2" db:"b" json:"b"` -} - -func NewAddServiceSumArgs() *AddServiceSumArgs { - return &AddServiceSumArgs{} -} - -func (p *AddServiceSumArgs) GetA() int64 { - return p.A -} - -func (p *AddServiceSumArgs) GetB() int64 { - return p.B -} -func (p *AddServiceSumArgs) Read(ctx context.Context, iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if fieldTypeId == thrift.I64 { - if err := p.ReadField1(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - case 2: - if fieldTypeId == thrift.I64 { - if err := p.ReadField2(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - default: - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(ctx); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceSumArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadI64(ctx); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.A = v - } - return nil -} - -func (p *AddServiceSumArgs) ReadField2(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadI64(ctx); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.B = v - } - return nil -} - -func (p *AddServiceSumArgs) Write(ctx context.Context, oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin(ctx, "Sum_args"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if p != nil { - if err := p.writeField1(ctx, oprot); err != nil { - return err - } - if err := p.writeField2(ctx, oprot); err != nil { - return err - } - } - if err := oprot.WriteFieldStop(ctx); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(ctx); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceSumArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "a", thrift.I64, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) - } - if err := oprot.WriteI64(ctx, int64(p.A)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) - } - return err -} - -func (p *AddServiceSumArgs) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "b", thrift.I64, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) - } - if err := oprot.WriteI64(ctx, int64(p.B)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) - } - return err -} - -func (p *AddServiceSumArgs) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceSumArgs(%+v)", *p) -} - -// Attributes: -// - Success -type AddServiceSumResult struct { - Success *SumReply `thrift:"success,0" db:"success" json:"success,omitempty"` -} - -func NewAddServiceSumResult() *AddServiceSumResult { - return &AddServiceSumResult{} -} - -var AddServiceSumResult_Success_DEFAULT *SumReply - -func (p *AddServiceSumResult) GetSuccess() *SumReply { - if !p.IsSetSuccess() { - return AddServiceSumResult_Success_DEFAULT - } - return p.Success -} -func (p *AddServiceSumResult) IsSetSuccess() bool { - return p.Success != nil -} - -func (p *AddServiceSumResult) Read(ctx context.Context, iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 0: - if fieldTypeId == thrift.STRUCT { - if err := p.ReadField0(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - default: - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(ctx); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceSumResult) ReadField0(ctx context.Context, iprot thrift.TProtocol) error { - p.Success = &SumReply{} - if err := p.Success.Read(ctx, iprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err) - } - return nil -} - -func (p *AddServiceSumResult) Write(ctx context.Context, oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin(ctx, "Sum_result"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if p != nil { - if err := p.writeField0(ctx, oprot); err != nil { - return err - } - } - if err := oprot.WriteFieldStop(ctx); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(ctx); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceSumResult) writeField0(ctx context.Context, oprot thrift.TProtocol) (err error) { - if p.IsSetSuccess() { - if err := oprot.WriteFieldBegin(ctx, "success", thrift.STRUCT, 0); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) - } - if err := p.Success.Write(ctx, oprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) - } - } - return err -} - -func (p *AddServiceSumResult) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceSumResult(%+v)", *p) -} - -// Attributes: -// - A -// - B -type AddServiceConcatArgs struct { - A string `thrift:"a,1" db:"a" json:"a"` - B string `thrift:"b,2" db:"b" json:"b"` -} - -func NewAddServiceConcatArgs() *AddServiceConcatArgs { - return &AddServiceConcatArgs{} -} - -func (p *AddServiceConcatArgs) GetA() string { - return p.A -} - -func (p *AddServiceConcatArgs) GetB() string { - return p.B -} -func (p *AddServiceConcatArgs) Read(ctx context.Context, iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 1: - if fieldTypeId == thrift.STRING { - if err := p.ReadField1(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - case 2: - if fieldTypeId == thrift.STRING { - if err := p.ReadField2(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - default: - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(ctx); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceConcatArgs) ReadField1(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(ctx); err != nil { - return thrift.PrependError("error reading field 1: ", err) - } else { - p.A = v - } - return nil -} - -func (p *AddServiceConcatArgs) ReadField2(ctx context.Context, iprot thrift.TProtocol) error { - if v, err := iprot.ReadString(ctx); err != nil { - return thrift.PrependError("error reading field 2: ", err) - } else { - p.B = v - } - return nil -} - -func (p *AddServiceConcatArgs) Write(ctx context.Context, oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin(ctx, "Concat_args"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if p != nil { - if err := p.writeField1(ctx, oprot); err != nil { - return err - } - if err := p.writeField2(ctx, oprot); err != nil { - return err - } - } - if err := oprot.WriteFieldStop(ctx); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(ctx); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceConcatArgs) writeField1(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "a", thrift.STRING, 1); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:a: ", p), err) - } - if err := oprot.WriteString(ctx, string(p.A)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.a (1) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 1:a: ", p), err) - } - return err -} - -func (p *AddServiceConcatArgs) writeField2(ctx context.Context, oprot thrift.TProtocol) (err error) { - if err := oprot.WriteFieldBegin(ctx, "b", thrift.STRING, 2); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:b: ", p), err) - } - if err := oprot.WriteString(ctx, string(p.B)); err != nil { - return thrift.PrependError(fmt.Sprintf("%T.b (2) field write error: ", p), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 2:b: ", p), err) - } - return err -} - -func (p *AddServiceConcatArgs) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceConcatArgs(%+v)", *p) -} - -// Attributes: -// - Success -type AddServiceConcatResult struct { - Success *ConcatReply `thrift:"success,0" db:"success" json:"success,omitempty"` -} - -func NewAddServiceConcatResult() *AddServiceConcatResult { - return &AddServiceConcatResult{} -} - -var AddServiceConcatResult_Success_DEFAULT *ConcatReply - -func (p *AddServiceConcatResult) GetSuccess() *ConcatReply { - if !p.IsSetSuccess() { - return AddServiceConcatResult_Success_DEFAULT - } - return p.Success -} -func (p *AddServiceConcatResult) IsSetSuccess() bool { - return p.Success != nil -} - -func (p *AddServiceConcatResult) Read(ctx context.Context, iprot thrift.TProtocol) error { - if _, err := iprot.ReadStructBegin(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err) - } - - for { - _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin(ctx) - if err != nil { - return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err) - } - if fieldTypeId == thrift.STOP { - break - } - switch fieldId { - case 0: - if fieldTypeId == thrift.STRUCT { - if err := p.ReadField0(ctx, iprot); err != nil { - return err - } - } else { - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - default: - if err := iprot.Skip(ctx, fieldTypeId); err != nil { - return err - } - } - if err := iprot.ReadFieldEnd(ctx); err != nil { - return err - } - } - if err := iprot.ReadStructEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err) - } - return nil -} - -func (p *AddServiceConcatResult) ReadField0(ctx context.Context, iprot thrift.TProtocol) error { - p.Success = &ConcatReply{} - if err := p.Success.Read(ctx, iprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", p.Success), err) - } - return nil -} - -func (p *AddServiceConcatResult) Write(ctx context.Context, oprot thrift.TProtocol) error { - if err := oprot.WriteStructBegin(ctx, "Concat_result"); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err) - } - if p != nil { - if err := p.writeField0(ctx, oprot); err != nil { - return err - } - } - if err := oprot.WriteFieldStop(ctx); err != nil { - return thrift.PrependError("write field stop error: ", err) - } - if err := oprot.WriteStructEnd(ctx); err != nil { - return thrift.PrependError("write struct stop error: ", err) - } - return nil -} - -func (p *AddServiceConcatResult) writeField0(ctx context.Context, oprot thrift.TProtocol) (err error) { - if p.IsSetSuccess() { - if err := oprot.WriteFieldBegin(ctx, "success", thrift.STRUCT, 0); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err) - } - if err := p.Success.Write(ctx, oprot); err != nil { - return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", p.Success), err) - } - if err := oprot.WriteFieldEnd(ctx); err != nil { - return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err) - } - } - return err -} - -func (p *AddServiceConcatResult) String() string { - if p == nil { - return "" - } - return fmt.Sprintf("AddServiceConcatResult(%+v)", *p) -} diff --git a/examples/apigateway/main.go b/examples/apigateway/main.go deleted file mode 100644 index 5891241d1..000000000 --- a/examples/apigateway/main.go +++ /dev/null @@ -1,287 +0,0 @@ -package main - -import ( - "bytes" - "context" - "encoding/json" - "flag" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/url" - "os" - "os/signal" - "strings" - "syscall" - "time" - - consulsd "github.com/go-kit/kit/sd/consul" - "github.com/gorilla/mux" - "github.com/hashicorp/consul/api" - stdopentracing "github.com/opentracing/opentracing-go" - stdzipkin "github.com/openzipkin/zipkin-go" - "google.golang.org/grpc" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/sd" - "github.com/go-kit/kit/sd/lb" - httptransport "github.com/go-kit/kit/transport/http" - - "github.com/go-kit/kit/examples/addsvc/pkg/addendpoint" - "github.com/go-kit/kit/examples/addsvc/pkg/addservice" - "github.com/go-kit/kit/examples/addsvc/pkg/addtransport" -) - -func main() { - var ( - httpAddr = flag.String("http.addr", ":8000", "Address for HTTP (JSON) server") - consulAddr = flag.String("consul.addr", "", "Consul agent address") - retryMax = flag.Int("retry.max", 3, "per-request retries to different instances") - retryTimeout = flag.Duration("retry.timeout", 500*time.Millisecond, "per-request timeout, including retries") - ) - flag.Parse() - - // Logging domain. - var logger log.Logger - { - logger = log.NewLogfmtLogger(os.Stderr) - logger = log.With(logger, "ts", log.DefaultTimestampUTC) - logger = log.With(logger, "caller", log.DefaultCaller) - } - - // Service discovery domain. In this example we use Consul. - var client consulsd.Client - { - consulConfig := api.DefaultConfig() - if len(*consulAddr) > 0 { - consulConfig.Address = *consulAddr - } - consulClient, err := api.NewClient(consulConfig) - if err != nil { - logger.Log("err", err) - os.Exit(1) - } - client = consulsd.NewClient(consulClient) - } - - // Transport domain. - tracer := stdopentracing.GlobalTracer() // no-op - zipkinTracer, _ := stdzipkin.NewTracer(nil, stdzipkin.WithNoopTracer(true)) - ctx := context.Background() - r := mux.NewRouter() - - // Now we begin installing the routes. Each route corresponds to a single - // method: sum, concat, uppercase, and count. - - // addsvc routes. - { - // Each method gets constructed with a factory. Factories take an - // instance string, and return a specific endpoint. In the factory we - // dial the instance string we get from Consul, and then leverage an - // addsvc client package to construct a complete service. We can then - // leverage the addsvc.Make{Sum,Concat}Endpoint constructors to convert - // the complete service to specific endpoint. - var ( - tags = []string{} - passingOnly = true - endpoints = addendpoint.Set{} - instancer = consulsd.NewInstancer(client, logger, "addsvc", tags, passingOnly) - ) - { - factory := addsvcFactory(addendpoint.MakeSumEndpoint, tracer, zipkinTracer, logger) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(*retryMax, *retryTimeout, balancer) - endpoints.SumEndpoint = retry - } - { - factory := addsvcFactory(addendpoint.MakeConcatEndpoint, tracer, zipkinTracer, logger) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(*retryMax, *retryTimeout, balancer) - endpoints.ConcatEndpoint = retry - } - - // Here we leverage the fact that addsvc comes with a constructor for an - // HTTP handler, and just install it under a particular path prefix in - // our router. - - r.PathPrefix("/addsvc").Handler(http.StripPrefix("/addsvc", addtransport.NewHTTPHandler(endpoints, tracer, zipkinTracer, logger))) - } - - // stringsvc routes. - { - // addsvc had lots of nice importable Go packages we could leverage. - // With stringsvc we are not so fortunate, it just has some endpoints - // that we assume will exist. So we have to write that logic here. This - // is by design, so you can see two totally different methods of - // proxying to a remote service. - - var ( - tags = []string{} - passingOnly = true - uppercase endpoint.Endpoint - count endpoint.Endpoint - instancer = consulsd.NewInstancer(client, logger, "stringsvc", tags, passingOnly) - ) - { - factory := stringsvcFactory(ctx, "GET", "/uppercase") - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(*retryMax, *retryTimeout, balancer) - uppercase = retry - } - { - factory := stringsvcFactory(ctx, "GET", "/count") - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(*retryMax, *retryTimeout, balancer) - count = retry - } - - // We can use the transport/http.Server to act as our handler, all we - // have to do provide it with the encode and decode functions for our - // stringsvc methods. - - r.Handle("/stringsvc/uppercase", httptransport.NewServer(uppercase, decodeUppercaseRequest, encodeJSONResponse)) - r.Handle("/stringsvc/count", httptransport.NewServer(count, decodeCountRequest, encodeJSONResponse)) - } - - // Interrupt handler. - errc := make(chan error) - go func() { - c := make(chan os.Signal) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - errc <- fmt.Errorf("%s", <-c) - }() - - // HTTP transport. - go func() { - logger.Log("transport", "HTTP", "addr", *httpAddr) - errc <- http.ListenAndServe(*httpAddr, r) - }() - - // Run! - logger.Log("exit", <-errc) -} - -func addsvcFactory(makeEndpoint func(addservice.Service) endpoint.Endpoint, tracer stdopentracing.Tracer, zipkinTracer *stdzipkin.Tracer, logger log.Logger) sd.Factory { - return func(instance string) (endpoint.Endpoint, io.Closer, error) { - // We could just as easily use the HTTP or Thrift client package to make - // the connection to addsvc. We've chosen gRPC arbitrarily. Note that - // the transport is an implementation detail: it doesn't leak out of - // this function. Nice! - - conn, err := grpc.Dial(instance, grpc.WithInsecure()) - if err != nil { - return nil, nil, err - } - service := addtransport.NewGRPCClient(conn, tracer, zipkinTracer, logger) - endpoint := makeEndpoint(service) - - // Notice that the addsvc gRPC client converts the connection to a - // complete addsvc, and we just throw away everything except the method - // we're interested in. A smarter factory would mux multiple methods - // over the same connection. But that would require more work to manage - // the returned io.Closer, e.g. reference counting. Since this is for - // the purposes of demonstration, we'll just keep it simple. - - return endpoint, conn, nil - } -} - -func stringsvcFactory(ctx context.Context, method, path string) sd.Factory { - return func(instance string) (endpoint.Endpoint, io.Closer, error) { - if !strings.HasPrefix(instance, "http") { - instance = "http://" + instance - } - tgt, err := url.Parse(instance) - if err != nil { - return nil, nil, err - } - tgt.Path = path - - // Since stringsvc doesn't have any kind of package we can import, or - // any formal spec, we are forced to just assert where the endpoints - // live, and write our own code to encode and decode requests and - // responses. Ideally, if you write the service, you will want to - // provide stronger guarantees to your clients. - - var ( - enc httptransport.EncodeRequestFunc - dec httptransport.DecodeResponseFunc - ) - switch path { - case "/uppercase": - enc, dec = encodeJSONRequest, decodeUppercaseResponse - case "/count": - enc, dec = encodeJSONRequest, decodeCountResponse - default: - return nil, nil, fmt.Errorf("unknown stringsvc path %q", path) - } - - return httptransport.NewClient(method, tgt, enc, dec).Endpoint(), nil, nil - } -} - -func encodeJSONRequest(_ context.Context, req *http.Request, request interface{}) error { - // Both uppercase and count requests are encoded in the same way: - // simple JSON serialization to the request body. - var buf bytes.Buffer - if err := json.NewEncoder(&buf).Encode(request); err != nil { - return err - } - req.Body = ioutil.NopCloser(&buf) - return nil -} - -func encodeJSONResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - return json.NewEncoder(w).Encode(response) -} - -// I've just copied these functions from stringsvc3/transport.go, inlining the -// struct definitions. - -func decodeUppercaseResponse(ctx context.Context, resp *http.Response) (interface{}, error) { - var response struct { - V string `json:"v"` - Err string `json:"err,omitempty"` - } - if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { - return nil, err - } - return response, nil -} - -func decodeCountResponse(ctx context.Context, resp *http.Response) (interface{}, error) { - var response struct { - V int `json:"v"` - } - if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { - return nil, err - } - return response, nil -} - -func decodeUppercaseRequest(ctx context.Context, req *http.Request) (interface{}, error) { - var request struct { - S string `json:"s"` - } - if err := json.NewDecoder(req.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func decodeCountRequest(ctx context.Context, req *http.Request) (interface{}, error) { - var request struct { - S string `json:"s"` - } - if err := json.NewDecoder(req.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} diff --git a/examples/profilesvc/README.md b/examples/profilesvc/README.md deleted file mode 100644 index 34a06e710..000000000 --- a/examples/profilesvc/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# profilesvc - -This example demonstrates how to use Go kit to implement a REST-y HTTP service. -It leverages the excellent [gorilla mux package](https://github.com/gorilla/mux) for routing. - -Run the example with the optional port address for the service: - -```bash -$ go run ./cmd/profilesvc/main.go -http.addr :8080 -ts=2018-05-01T16:13:12.849086255Z caller=main.go:47 transport=HTTP addr=:8080 -``` - -Create a Profile: - -```bash -$ curl -d '{"id":"1234","Name":"Go Kit"}' -H "Content-Type: application/json" -X POST http://localhost:8080/profiles/ -{} -``` - -Get the profile you just created - -```bash -$ curl localhost:8080/profiles/1234 -{"profile":{"id":"1234","name":"Go Kit"}} -``` diff --git a/examples/profilesvc/client/client.go b/examples/profilesvc/client/client.go deleted file mode 100644 index 03c1dc7a7..000000000 --- a/examples/profilesvc/client/client.go +++ /dev/null @@ -1,121 +0,0 @@ -// Package client provides a profilesvc client based on a predefined Consul -// service name and relevant tags. Users must only provide the address of a -// Consul server. -package client - -import ( - "io" - "time" - - consulapi "github.com/hashicorp/consul/api" - - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/examples/profilesvc" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/sd" - "github.com/go-kit/kit/sd/consul" - "github.com/go-kit/kit/sd/lb" -) - -// New returns a service that's load-balanced over instances of profilesvc found -// in the provided Consul server. The mechanism of looking up profilesvc -// instances in Consul is hard-coded into the client. -func New(consulAddr string, logger log.Logger) (profilesvc.Service, error) { - apiclient, err := consulapi.NewClient(&consulapi.Config{ - Address: consulAddr, - }) - if err != nil { - return nil, err - } - - // As the implementer of profilesvc, we declare and enforce these - // parameters for all of the profilesvc consumers. - var ( - consulService = "profilesvc" - consulTags = []string{"prod"} - passingOnly = true - retryMax = 3 - retryTimeout = 500 * time.Millisecond - ) - - var ( - sdclient = consul.NewClient(apiclient) - instancer = consul.NewInstancer(sdclient, logger, consulService, consulTags, passingOnly) - endpoints profilesvc.Endpoints - ) - { - factory := factoryFor(profilesvc.MakePostProfileEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.PostProfileEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakeGetProfileEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.GetProfileEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakePutProfileEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.PutProfileEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakePatchProfileEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.PatchProfileEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakeDeleteProfileEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.DeleteProfileEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakeGetAddressesEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.GetAddressesEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakeGetAddressEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.GetAddressEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakePostAddressEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.PostAddressEndpoint = retry - } - { - factory := factoryFor(profilesvc.MakeDeleteAddressEndpoint) - endpointer := sd.NewEndpointer(instancer, factory, logger) - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(retryMax, retryTimeout, balancer) - endpoints.DeleteAddressEndpoint = retry - } - - return endpoints, nil -} - -func factoryFor(makeEndpoint func(profilesvc.Service) endpoint.Endpoint) sd.Factory { - return func(instance string) (endpoint.Endpoint, io.Closer, error) { - service, err := profilesvc.MakeClientEndpoints(instance) - if err != nil { - return nil, nil, err - } - return makeEndpoint(service), nil, nil - } -} diff --git a/examples/profilesvc/cmd/profilesvc/main.go b/examples/profilesvc/cmd/profilesvc/main.go deleted file mode 100644 index fda752952..000000000 --- a/examples/profilesvc/cmd/profilesvc/main.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "net/http" - "os" - "os/signal" - "syscall" - - "github.com/go-kit/kit/examples/profilesvc" - "github.com/go-kit/kit/log" -) - -func main() { - var ( - httpAddr = flag.String("http.addr", ":8080", "HTTP listen address") - ) - flag.Parse() - - var logger log.Logger - { - logger = log.NewLogfmtLogger(os.Stderr) - logger = log.With(logger, "ts", log.DefaultTimestampUTC) - logger = log.With(logger, "caller", log.DefaultCaller) - } - - var s profilesvc.Service - { - s = profilesvc.NewInmemService() - s = profilesvc.LoggingMiddleware(logger)(s) - } - - var h http.Handler - { - h = profilesvc.MakeHTTPHandler(s, log.With(logger, "component", "HTTP")) - } - - errs := make(chan error) - go func() { - c := make(chan os.Signal) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - errs <- fmt.Errorf("%s", <-c) - }() - - go func() { - logger.Log("transport", "HTTP", "addr", *httpAddr) - errs <- http.ListenAndServe(*httpAddr, h) - }() - - logger.Log("exit", <-errs) -} diff --git a/examples/profilesvc/endpoints.go b/examples/profilesvc/endpoints.go deleted file mode 100644 index 794d0f178..000000000 --- a/examples/profilesvc/endpoints.go +++ /dev/null @@ -1,387 +0,0 @@ -package profilesvc - -import ( - "context" - "net/url" - "strings" - - "github.com/go-kit/kit/endpoint" - httptransport "github.com/go-kit/kit/transport/http" -) - -// Endpoints collects all of the endpoints that compose a profile service. It's -// meant to be used as a helper struct, to collect all of the endpoints into a -// single parameter. -// -// In a server, it's useful for functions that need to operate on a per-endpoint -// basis. For example, you might pass an Endpoints to a function that produces -// an http.Handler, with each method (endpoint) wired up to a specific path. (It -// is probably a mistake in design to invoke the Service methods on the -// Endpoints struct in a server.) -// -// In a client, it's useful to collect individually constructed endpoints into a -// single type that implements the Service interface. For example, you might -// construct individual endpoints using transport/http.NewClient, combine them -// into an Endpoints, and return it to the caller as a Service. -type Endpoints struct { - PostProfileEndpoint endpoint.Endpoint - GetProfileEndpoint endpoint.Endpoint - PutProfileEndpoint endpoint.Endpoint - PatchProfileEndpoint endpoint.Endpoint - DeleteProfileEndpoint endpoint.Endpoint - GetAddressesEndpoint endpoint.Endpoint - GetAddressEndpoint endpoint.Endpoint - PostAddressEndpoint endpoint.Endpoint - DeleteAddressEndpoint endpoint.Endpoint -} - -// MakeServerEndpoints returns an Endpoints struct where each endpoint invokes -// the corresponding method on the provided service. Useful in a profilesvc -// server. -func MakeServerEndpoints(s Service) Endpoints { - return Endpoints{ - PostProfileEndpoint: MakePostProfileEndpoint(s), - GetProfileEndpoint: MakeGetProfileEndpoint(s), - PutProfileEndpoint: MakePutProfileEndpoint(s), - PatchProfileEndpoint: MakePatchProfileEndpoint(s), - DeleteProfileEndpoint: MakeDeleteProfileEndpoint(s), - GetAddressesEndpoint: MakeGetAddressesEndpoint(s), - GetAddressEndpoint: MakeGetAddressEndpoint(s), - PostAddressEndpoint: MakePostAddressEndpoint(s), - DeleteAddressEndpoint: MakeDeleteAddressEndpoint(s), - } -} - -// MakeClientEndpoints returns an Endpoints struct where each endpoint invokes -// the corresponding method on the remote instance, via a transport/http.Client. -// Useful in a profilesvc client. -func MakeClientEndpoints(instance string) (Endpoints, error) { - if !strings.HasPrefix(instance, "http") { - instance = "http://" + instance - } - tgt, err := url.Parse(instance) - if err != nil { - return Endpoints{}, err - } - tgt.Path = "" - - options := []httptransport.ClientOption{} - - // Note that the request encoders need to modify the request URL, changing - // the path. That's fine: we simply need to provide specific encoders for - // each endpoint. - - return Endpoints{ - PostProfileEndpoint: httptransport.NewClient("POST", tgt, encodePostProfileRequest, decodePostProfileResponse, options...).Endpoint(), - GetProfileEndpoint: httptransport.NewClient("GET", tgt, encodeGetProfileRequest, decodeGetProfileResponse, options...).Endpoint(), - PutProfileEndpoint: httptransport.NewClient("PUT", tgt, encodePutProfileRequest, decodePutProfileResponse, options...).Endpoint(), - PatchProfileEndpoint: httptransport.NewClient("PATCH", tgt, encodePatchProfileRequest, decodePatchProfileResponse, options...).Endpoint(), - DeleteProfileEndpoint: httptransport.NewClient("DELETE", tgt, encodeDeleteProfileRequest, decodeDeleteProfileResponse, options...).Endpoint(), - GetAddressesEndpoint: httptransport.NewClient("GET", tgt, encodeGetAddressesRequest, decodeGetAddressesResponse, options...).Endpoint(), - GetAddressEndpoint: httptransport.NewClient("GET", tgt, encodeGetAddressRequest, decodeGetAddressResponse, options...).Endpoint(), - PostAddressEndpoint: httptransport.NewClient("POST", tgt, encodePostAddressRequest, decodePostAddressResponse, options...).Endpoint(), - DeleteAddressEndpoint: httptransport.NewClient("DELETE", tgt, encodeDeleteAddressRequest, decodeDeleteAddressResponse, options...).Endpoint(), - }, nil -} - -// PostProfile implements Service. Primarily useful in a client. -func (e Endpoints) PostProfile(ctx context.Context, p Profile) error { - request := postProfileRequest{Profile: p} - response, err := e.PostProfileEndpoint(ctx, request) - if err != nil { - return err - } - resp := response.(postProfileResponse) - return resp.Err -} - -// GetProfile implements Service. Primarily useful in a client. -func (e Endpoints) GetProfile(ctx context.Context, id string) (Profile, error) { - request := getProfileRequest{ID: id} - response, err := e.GetProfileEndpoint(ctx, request) - if err != nil { - return Profile{}, err - } - resp := response.(getProfileResponse) - return resp.Profile, resp.Err -} - -// PutProfile implements Service. Primarily useful in a client. -func (e Endpoints) PutProfile(ctx context.Context, id string, p Profile) error { - request := putProfileRequest{ID: id, Profile: p} - response, err := e.PutProfileEndpoint(ctx, request) - if err != nil { - return err - } - resp := response.(putProfileResponse) - return resp.Err -} - -// PatchProfile implements Service. Primarily useful in a client. -func (e Endpoints) PatchProfile(ctx context.Context, id string, p Profile) error { - request := patchProfileRequest{ID: id, Profile: p} - response, err := e.PatchProfileEndpoint(ctx, request) - if err != nil { - return err - } - resp := response.(patchProfileResponse) - return resp.Err -} - -// DeleteProfile implements Service. Primarily useful in a client. -func (e Endpoints) DeleteProfile(ctx context.Context, id string) error { - request := deleteProfileRequest{ID: id} - response, err := e.DeleteProfileEndpoint(ctx, request) - if err != nil { - return err - } - resp := response.(deleteProfileResponse) - return resp.Err -} - -// GetAddresses implements Service. Primarily useful in a client. -func (e Endpoints) GetAddresses(ctx context.Context, profileID string) ([]Address, error) { - request := getAddressesRequest{ProfileID: profileID} - response, err := e.GetAddressesEndpoint(ctx, request) - if err != nil { - return nil, err - } - resp := response.(getAddressesResponse) - return resp.Addresses, resp.Err -} - -// GetAddress implements Service. Primarily useful in a client. -func (e Endpoints) GetAddress(ctx context.Context, profileID string, addressID string) (Address, error) { - request := getAddressRequest{ProfileID: profileID, AddressID: addressID} - response, err := e.GetAddressEndpoint(ctx, request) - if err != nil { - return Address{}, err - } - resp := response.(getAddressResponse) - return resp.Address, resp.Err -} - -// PostAddress implements Service. Primarily useful in a client. -func (e Endpoints) PostAddress(ctx context.Context, profileID string, a Address) error { - request := postAddressRequest{ProfileID: profileID, Address: a} - response, err := e.PostAddressEndpoint(ctx, request) - if err != nil { - return err - } - resp := response.(postAddressResponse) - return resp.Err -} - -// DeleteAddress implements Service. Primarily useful in a client. -func (e Endpoints) DeleteAddress(ctx context.Context, profileID string, addressID string) error { - request := deleteAddressRequest{ProfileID: profileID, AddressID: addressID} - response, err := e.DeleteAddressEndpoint(ctx, request) - if err != nil { - return err - } - resp := response.(deleteAddressResponse) - return resp.Err -} - -// MakePostProfileEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakePostProfileEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(postProfileRequest) - e := s.PostProfile(ctx, req.Profile) - return postProfileResponse{Err: e}, nil - } -} - -// MakeGetProfileEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakeGetProfileEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(getProfileRequest) - p, e := s.GetProfile(ctx, req.ID) - return getProfileResponse{Profile: p, Err: e}, nil - } -} - -// MakePutProfileEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakePutProfileEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(putProfileRequest) - e := s.PutProfile(ctx, req.ID, req.Profile) - return putProfileResponse{Err: e}, nil - } -} - -// MakePatchProfileEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakePatchProfileEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(patchProfileRequest) - e := s.PatchProfile(ctx, req.ID, req.Profile) - return patchProfileResponse{Err: e}, nil - } -} - -// MakeDeleteProfileEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakeDeleteProfileEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(deleteProfileRequest) - e := s.DeleteProfile(ctx, req.ID) - return deleteProfileResponse{Err: e}, nil - } -} - -// MakeGetAddressesEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakeGetAddressesEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(getAddressesRequest) - a, e := s.GetAddresses(ctx, req.ProfileID) - return getAddressesResponse{Addresses: a, Err: e}, nil - } -} - -// MakeGetAddressEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakeGetAddressEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(getAddressRequest) - a, e := s.GetAddress(ctx, req.ProfileID, req.AddressID) - return getAddressResponse{Address: a, Err: e}, nil - } -} - -// MakePostAddressEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakePostAddressEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(postAddressRequest) - e := s.PostAddress(ctx, req.ProfileID, req.Address) - return postAddressResponse{Err: e}, nil - } -} - -// MakeDeleteAddressEndpoint returns an endpoint via the passed service. -// Primarily useful in a server. -func MakeDeleteAddressEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (response interface{}, err error) { - req := request.(deleteAddressRequest) - e := s.DeleteAddress(ctx, req.ProfileID, req.AddressID) - return deleteAddressResponse{Err: e}, nil - } -} - -// We have two options to return errors from the business logic. -// -// We could return the error via the endpoint itself. That makes certain things -// a little bit easier, like providing non-200 HTTP responses to the client. But -// Go kit assumes that endpoint errors are (or may be treated as) -// transport-domain errors. For example, an endpoint error will count against a -// circuit breaker error count. -// -// Therefore, it's often better to return service (business logic) errors in the -// response object. This means we have to do a bit more work in the HTTP -// response encoder to detect e.g. a not-found error and provide a proper HTTP -// status code. That work is done with the errorer interface, in transport.go. -// Response types that may contain business-logic errors implement that -// interface. - -type postProfileRequest struct { - Profile Profile -} - -type postProfileResponse struct { - Err error `json:"err,omitempty"` -} - -func (r postProfileResponse) error() error { return r.Err } - -type getProfileRequest struct { - ID string -} - -type getProfileResponse struct { - Profile Profile `json:"profile,omitempty"` - Err error `json:"err,omitempty"` -} - -func (r getProfileResponse) error() error { return r.Err } - -type putProfileRequest struct { - ID string - Profile Profile -} - -type putProfileResponse struct { - Err error `json:"err,omitempty"` -} - -func (r putProfileResponse) error() error { return nil } - -type patchProfileRequest struct { - ID string - Profile Profile -} - -type patchProfileResponse struct { - Err error `json:"err,omitempty"` -} - -func (r patchProfileResponse) error() error { return r.Err } - -type deleteProfileRequest struct { - ID string -} - -type deleteProfileResponse struct { - Err error `json:"err,omitempty"` -} - -func (r deleteProfileResponse) error() error { return r.Err } - -type getAddressesRequest struct { - ProfileID string -} - -type getAddressesResponse struct { - Addresses []Address `json:"addresses,omitempty"` - Err error `json:"err,omitempty"` -} - -func (r getAddressesResponse) error() error { return r.Err } - -type getAddressRequest struct { - ProfileID string - AddressID string -} - -type getAddressResponse struct { - Address Address `json:"address,omitempty"` - Err error `json:"err,omitempty"` -} - -func (r getAddressResponse) error() error { return r.Err } - -type postAddressRequest struct { - ProfileID string - Address Address -} - -type postAddressResponse struct { - Err error `json:"err,omitempty"` -} - -func (r postAddressResponse) error() error { return r.Err } - -type deleteAddressRequest struct { - ProfileID string - AddressID string -} - -type deleteAddressResponse struct { - Err error `json:"err,omitempty"` -} - -func (r deleteAddressResponse) error() error { return r.Err } diff --git a/examples/profilesvc/middlewares.go b/examples/profilesvc/middlewares.go deleted file mode 100644 index 1b738f5b5..000000000 --- a/examples/profilesvc/middlewares.go +++ /dev/null @@ -1,88 +0,0 @@ -package profilesvc - -import ( - "context" - "time" - - "github.com/go-kit/kit/log" -) - -// Middleware describes a service (as opposed to endpoint) middleware. -type Middleware func(Service) Service - -func LoggingMiddleware(logger log.Logger) Middleware { - return func(next Service) Service { - return &loggingMiddleware{ - next: next, - logger: logger, - } - } -} - -type loggingMiddleware struct { - next Service - logger log.Logger -} - -func (mw loggingMiddleware) PostProfile(ctx context.Context, p Profile) (err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "PostProfile", "id", p.ID, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.PostProfile(ctx, p) -} - -func (mw loggingMiddleware) GetProfile(ctx context.Context, id string) (p Profile, err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "GetProfile", "id", id, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.GetProfile(ctx, id) -} - -func (mw loggingMiddleware) PutProfile(ctx context.Context, id string, p Profile) (err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "PutProfile", "id", id, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.PutProfile(ctx, id, p) -} - -func (mw loggingMiddleware) PatchProfile(ctx context.Context, id string, p Profile) (err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "PatchProfile", "id", id, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.PatchProfile(ctx, id, p) -} - -func (mw loggingMiddleware) DeleteProfile(ctx context.Context, id string) (err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "DeleteProfile", "id", id, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.DeleteProfile(ctx, id) -} - -func (mw loggingMiddleware) GetAddresses(ctx context.Context, profileID string) (addresses []Address, err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "GetAddresses", "profileID", profileID, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.GetAddresses(ctx, profileID) -} - -func (mw loggingMiddleware) GetAddress(ctx context.Context, profileID string, addressID string) (a Address, err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "GetAddress", "profileID", profileID, "addressID", addressID, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.GetAddress(ctx, profileID, addressID) -} - -func (mw loggingMiddleware) PostAddress(ctx context.Context, profileID string, a Address) (err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "PostAddress", "profileID", profileID, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.PostAddress(ctx, profileID, a) -} - -func (mw loggingMiddleware) DeleteAddress(ctx context.Context, profileID string, addressID string) (err error) { - defer func(begin time.Time) { - mw.logger.Log("method", "DeleteAddress", "profileID", profileID, "addressID", addressID, "took", time.Since(begin), "err", err) - }(time.Now()) - return mw.next.DeleteAddress(ctx, profileID, addressID) -} diff --git a/examples/profilesvc/service.go b/examples/profilesvc/service.go deleted file mode 100644 index cd34ecd9e..000000000 --- a/examples/profilesvc/service.go +++ /dev/null @@ -1,185 +0,0 @@ -package profilesvc - -import ( - "context" - "errors" - "sync" -) - -// Service is a simple CRUD interface for user profiles. -type Service interface { - PostProfile(ctx context.Context, p Profile) error - GetProfile(ctx context.Context, id string) (Profile, error) - PutProfile(ctx context.Context, id string, p Profile) error - PatchProfile(ctx context.Context, id string, p Profile) error - DeleteProfile(ctx context.Context, id string) error - GetAddresses(ctx context.Context, profileID string) ([]Address, error) - GetAddress(ctx context.Context, profileID string, addressID string) (Address, error) - PostAddress(ctx context.Context, profileID string, a Address) error - DeleteAddress(ctx context.Context, profileID string, addressID string) error -} - -// Profile represents a single user profile. -// ID should be globally unique. -type Profile struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Addresses []Address `json:"addresses,omitempty"` -} - -// Address is a field of a user profile. -// ID should be unique within the profile (at a minimum). -type Address struct { - ID string `json:"id"` - Location string `json:"location,omitempty"` -} - -var ( - ErrInconsistentIDs = errors.New("inconsistent IDs") - ErrAlreadyExists = errors.New("already exists") - ErrNotFound = errors.New("not found") -) - -type inmemService struct { - mtx sync.RWMutex - m map[string]Profile -} - -func NewInmemService() Service { - return &inmemService{ - m: map[string]Profile{}, - } -} - -func (s *inmemService) PostProfile(ctx context.Context, p Profile) error { - s.mtx.Lock() - defer s.mtx.Unlock() - if _, ok := s.m[p.ID]; ok { - return ErrAlreadyExists // POST = create, don't overwrite - } - s.m[p.ID] = p - return nil -} - -func (s *inmemService) GetProfile(ctx context.Context, id string) (Profile, error) { - s.mtx.RLock() - defer s.mtx.RUnlock() - p, ok := s.m[id] - if !ok { - return Profile{}, ErrNotFound - } - return p, nil -} - -func (s *inmemService) PutProfile(ctx context.Context, id string, p Profile) error { - if id != p.ID { - return ErrInconsistentIDs - } - s.mtx.Lock() - defer s.mtx.Unlock() - s.m[id] = p // PUT = create or update - return nil -} - -func (s *inmemService) PatchProfile(ctx context.Context, id string, p Profile) error { - if p.ID != "" && id != p.ID { - return ErrInconsistentIDs - } - - s.mtx.Lock() - defer s.mtx.Unlock() - - existing, ok := s.m[id] - if !ok { - return ErrNotFound // PATCH = update existing, don't create - } - - // We assume that it's not possible to PATCH the ID, and that it's not - // possible to PATCH any field to its zero value. That is, the zero value - // means not specified. The way around this is to use e.g. Name *string in - // the Profile definition. But since this is just a demonstrative example, - // I'm leaving that out. - - if p.Name != "" { - existing.Name = p.Name - } - if len(p.Addresses) > 0 { - existing.Addresses = p.Addresses - } - s.m[id] = existing - return nil -} - -func (s *inmemService) DeleteProfile(ctx context.Context, id string) error { - s.mtx.Lock() - defer s.mtx.Unlock() - if _, ok := s.m[id]; !ok { - return ErrNotFound - } - delete(s.m, id) - return nil -} - -func (s *inmemService) GetAddresses(ctx context.Context, profileID string) ([]Address, error) { - s.mtx.RLock() - defer s.mtx.RUnlock() - p, ok := s.m[profileID] - if !ok { - return []Address{}, ErrNotFound - } - return p.Addresses, nil -} - -func (s *inmemService) GetAddress(ctx context.Context, profileID string, addressID string) (Address, error) { - s.mtx.RLock() - defer s.mtx.RUnlock() - p, ok := s.m[profileID] - if !ok { - return Address{}, ErrNotFound - } - for _, address := range p.Addresses { - if address.ID == addressID { - return address, nil - } - } - return Address{}, ErrNotFound -} - -func (s *inmemService) PostAddress(ctx context.Context, profileID string, a Address) error { - s.mtx.Lock() - defer s.mtx.Unlock() - p, ok := s.m[profileID] - if !ok { - return ErrNotFound - } - for _, address := range p.Addresses { - if address.ID == a.ID { - return ErrAlreadyExists - } - } - p.Addresses = append(p.Addresses, a) - s.m[profileID] = p - return nil -} - -func (s *inmemService) DeleteAddress(ctx context.Context, profileID string, addressID string) error { - s.mtx.Lock() - defer s.mtx.Unlock() - p, ok := s.m[profileID] - if !ok { - return ErrNotFound - } - newAddresses := make([]Address, 0, len(p.Addresses)) - for _, address := range p.Addresses { - if address.ID == addressID { - continue // delete - } - newAddresses = append(newAddresses, address) - } - if len(newAddresses) == len(p.Addresses) { - return ErrNotFound - } - p.Addresses = newAddresses - s.m[profileID] = p - return nil -} diff --git a/examples/profilesvc/transport.go b/examples/profilesvc/transport.go deleted file mode 100644 index 9700dc8cd..000000000 --- a/examples/profilesvc/transport.go +++ /dev/null @@ -1,401 +0,0 @@ -package profilesvc - -// The profilesvc is just over HTTP, so we just have a single transport.go. - -import ( - "bytes" - "context" - "encoding/json" - "errors" - "io/ioutil" - "net/http" - "net/url" - - "github.com/gorilla/mux" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/transport" - httptransport "github.com/go-kit/kit/transport/http" -) - -var ( - // ErrBadRouting is returned when an expected path variable is missing. - // It always indicates programmer error. - ErrBadRouting = errors.New("inconsistent mapping between route and handler (programmer error)") -) - -// MakeHTTPHandler mounts all of the service endpoints into an http.Handler. -// Useful in a profilesvc server. -func MakeHTTPHandler(s Service, logger log.Logger) http.Handler { - r := mux.NewRouter() - e := MakeServerEndpoints(s) - options := []httptransport.ServerOption{ - httptransport.ServerErrorHandler(transport.NewLogErrorHandler(logger)), - httptransport.ServerErrorEncoder(encodeError), - } - - // POST /profiles/ adds another profile - // GET /profiles/:id retrieves the given profile by id - // PUT /profiles/:id post updated profile information about the profile - // PATCH /profiles/:id partial updated profile information - // DELETE /profiles/:id remove the given profile - // GET /profiles/:id/addresses/ retrieve addresses associated with the profile - // GET /profiles/:id/addresses/:addressID retrieve a particular profile address - // POST /profiles/:id/addresses/ add a new address - // DELETE /profiles/:id/addresses/:addressID remove an address - - r.Methods("POST").Path("/profiles/").Handler(httptransport.NewServer( - e.PostProfileEndpoint, - decodePostProfileRequest, - encodeResponse, - options..., - )) - r.Methods("GET").Path("/profiles/{id}").Handler(httptransport.NewServer( - e.GetProfileEndpoint, - decodeGetProfileRequest, - encodeResponse, - options..., - )) - r.Methods("PUT").Path("/profiles/{id}").Handler(httptransport.NewServer( - e.PutProfileEndpoint, - decodePutProfileRequest, - encodeResponse, - options..., - )) - r.Methods("PATCH").Path("/profiles/{id}").Handler(httptransport.NewServer( - e.PatchProfileEndpoint, - decodePatchProfileRequest, - encodeResponse, - options..., - )) - r.Methods("DELETE").Path("/profiles/{id}").Handler(httptransport.NewServer( - e.DeleteProfileEndpoint, - decodeDeleteProfileRequest, - encodeResponse, - options..., - )) - r.Methods("GET").Path("/profiles/{id}/addresses/").Handler(httptransport.NewServer( - e.GetAddressesEndpoint, - decodeGetAddressesRequest, - encodeResponse, - options..., - )) - r.Methods("GET").Path("/profiles/{id}/addresses/{addressID}").Handler(httptransport.NewServer( - e.GetAddressEndpoint, - decodeGetAddressRequest, - encodeResponse, - options..., - )) - r.Methods("POST").Path("/profiles/{id}/addresses/").Handler(httptransport.NewServer( - e.PostAddressEndpoint, - decodePostAddressRequest, - encodeResponse, - options..., - )) - r.Methods("DELETE").Path("/profiles/{id}/addresses/{addressID}").Handler(httptransport.NewServer( - e.DeleteAddressEndpoint, - decodeDeleteAddressRequest, - encodeResponse, - options..., - )) - return r -} - -func decodePostProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - var req postProfileRequest - if e := json.NewDecoder(r.Body).Decode(&req.Profile); e != nil { - return nil, e - } - return req, nil -} - -func decodeGetProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - return getProfileRequest{ID: id}, nil -} - -func decodePutProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - var profile Profile - if err := json.NewDecoder(r.Body).Decode(&profile); err != nil { - return nil, err - } - return putProfileRequest{ - ID: id, - Profile: profile, - }, nil -} - -func decodePatchProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - var profile Profile - if err := json.NewDecoder(r.Body).Decode(&profile); err != nil { - return nil, err - } - return patchProfileRequest{ - ID: id, - Profile: profile, - }, nil -} - -func decodeDeleteProfileRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - return deleteProfileRequest{ID: id}, nil -} - -func decodeGetAddressesRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - return getAddressesRequest{ProfileID: id}, nil -} - -func decodeGetAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - addressID, ok := vars["addressID"] - if !ok { - return nil, ErrBadRouting - } - return getAddressRequest{ - ProfileID: id, - AddressID: addressID, - }, nil -} - -func decodePostAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - var address Address - if err := json.NewDecoder(r.Body).Decode(&address); err != nil { - return nil, err - } - return postAddressRequest{ - ProfileID: id, - Address: address, - }, nil -} - -func decodeDeleteAddressRequest(_ context.Context, r *http.Request) (request interface{}, err error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, ErrBadRouting - } - addressID, ok := vars["addressID"] - if !ok { - return nil, ErrBadRouting - } - return deleteAddressRequest{ - ProfileID: id, - AddressID: addressID, - }, nil -} - -func encodePostProfileRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("POST").Path("/profiles/") - req.URL.Path = "/profiles/" - return encodeRequest(ctx, req, request) -} - -func encodeGetProfileRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("GET").Path("/profiles/{id}") - r := request.(getProfileRequest) - profileID := url.QueryEscape(r.ID) - req.URL.Path = "/profiles/" + profileID - return encodeRequest(ctx, req, request) -} - -func encodePutProfileRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("PUT").Path("/profiles/{id}") - r := request.(putProfileRequest) - profileID := url.QueryEscape(r.ID) - req.URL.Path = "/profiles/" + profileID - return encodeRequest(ctx, req, request) -} - -func encodePatchProfileRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("PATCH").Path("/profiles/{id}") - r := request.(patchProfileRequest) - profileID := url.QueryEscape(r.ID) - req.URL.Path = "/profiles/" + profileID - return encodeRequest(ctx, req, request) -} - -func encodeDeleteProfileRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("DELETE").Path("/profiles/{id}") - r := request.(deleteProfileRequest) - profileID := url.QueryEscape(r.ID) - req.URL.Path = "/profiles/" + profileID - return encodeRequest(ctx, req, request) -} - -func encodeGetAddressesRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("GET").Path("/profiles/{id}/addresses/") - r := request.(getAddressesRequest) - profileID := url.QueryEscape(r.ProfileID) - req.URL.Path = "/profiles/" + profileID + "/addresses/" - return encodeRequest(ctx, req, request) -} - -func encodeGetAddressRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("GET").Path("/profiles/{id}/addresses/{addressID}") - r := request.(getAddressRequest) - profileID := url.QueryEscape(r.ProfileID) - addressID := url.QueryEscape(r.AddressID) - req.URL.Path = "/profiles/" + profileID + "/addresses/" + addressID - return encodeRequest(ctx, req, request) -} - -func encodePostAddressRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("POST").Path("/profiles/{id}/addresses/") - r := request.(postAddressRequest) - profileID := url.QueryEscape(r.ProfileID) - req.URL.Path = "/profiles/" + profileID + "/addresses/" - return encodeRequest(ctx, req, request) -} - -func encodeDeleteAddressRequest(ctx context.Context, req *http.Request, request interface{}) error { - // r.Methods("DELETE").Path("/profiles/{id}/addresses/{addressID}") - r := request.(deleteAddressRequest) - profileID := url.QueryEscape(r.ProfileID) - addressID := url.QueryEscape(r.AddressID) - req.URL.Path = "/profiles/" + profileID + "/addresses/" + addressID - return encodeRequest(ctx, req, request) -} - -func decodePostProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response postProfileResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodeGetProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response getProfileResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodePutProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response putProfileResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodePatchProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response patchProfileResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodeDeleteProfileResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response deleteProfileResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodeGetAddressesResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response getAddressesResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodeGetAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response getAddressResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodePostAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response postAddressResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -func decodeDeleteAddressResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response deleteAddressResponse - err := json.NewDecoder(resp.Body).Decode(&response) - return response, err -} - -// errorer is implemented by all concrete response types that may contain -// errors. It allows us to change the HTTP response code without needing to -// trigger an endpoint (transport-level) error. For more information, read the -// big comment in endpoints.go. -type errorer interface { - error() error -} - -// encodeResponse is the common method to encode all response types to the -// client. I chose to do it this way because, since we're using JSON, there's no -// reason to provide anything more specific. It's certainly possible to -// specialize on a per-response (per-method) basis. -func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { - if e, ok := response.(errorer); ok && e.error() != nil { - // Not a Go kit transport error, but a business-logic error. - // Provide those as HTTP errors. - encodeError(ctx, e.error(), w) - return nil - } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - return json.NewEncoder(w).Encode(response) -} - -// encodeRequest likewise JSON-encodes the request to the HTTP request body. -// Don't use it directly as a transport/http.Client EncodeRequestFunc: -// profilesvc endpoints require mutating the HTTP method and request path. -func encodeRequest(_ context.Context, req *http.Request, request interface{}) error { - var buf bytes.Buffer - err := json.NewEncoder(&buf).Encode(request) - if err != nil { - return err - } - req.Body = ioutil.NopCloser(&buf) - return nil -} - -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - if err == nil { - panic("encodeError with nil error") - } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.WriteHeader(codeFrom(err)) - json.NewEncoder(w).Encode(map[string]interface{}{ - "error": err.Error(), - }) -} - -func codeFrom(err error) int { - switch err { - case ErrNotFound: - return http.StatusNotFound - case ErrAlreadyExists, ErrInconsistentIDs: - return http.StatusBadRequest - default: - return http.StatusInternalServerError - } -} diff --git a/examples/shipping/README.md b/examples/shipping/README.md deleted file mode 100644 index 1a9a14eea..000000000 --- a/examples/shipping/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# shipping - -This example demonstrates a more real-world application consisting of multiple services. - -## Description - -The implementation is based on the container shipping domain from the [Domain Driven Design](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215) book by Eric Evans, which was [originally](http://dddsample.sourceforge.net/) implemented in Java but has since been ported to Go. This example is a somewhat stripped down version to demonstrate the use of Go kit. The [original Go application](https://github.com/marcusolsson/goddd) is maintained separately and accompanied by an [AngularJS application](https://github.com/marcusolsson/dddelivery-angularjs) as well as a mock [routing service](https://github.com/marcusolsson/pathfinder). - -### Organization - -The application consists of three application services, `booking`, `handling` and `tracking`. Each of these is an individual Go kit service as seen in previous examples. - -- __booking__ - used by the shipping company to book and route cargos. -- __handling__ - used by our staff around the world to register whenever the cargo has been received, loaded etc. -- __tracking__ - used by the customer to track the cargo along the route - -There are also a few pure domain packages that contain some intricate business-logic. They provide domain objects and services that are used by each application service to provide interesting use-cases for the user. - -`inmem` contains in-memory implementations for the repositories found in the domain packages. - -The `routing` package provides a _domain service_ that is used to query an external application for possible routes. - -## Contributing - -As with all Go kit examples you are more than welcome to contribute. If you do however, please consider contributing back to the original project as well. diff --git a/examples/shipping/booking/endpoint.go b/examples/shipping/booking/endpoint.go deleted file mode 100644 index abe83f751..000000000 --- a/examples/shipping/booking/endpoint.go +++ /dev/null @@ -1,139 +0,0 @@ -package booking - -import ( - "context" - "time" - - "github.com/go-kit/kit/endpoint" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" -) - -type bookCargoRequest struct { - Origin location.UNLocode - Destination location.UNLocode - ArrivalDeadline time.Time -} - -type bookCargoResponse struct { - ID cargo.TrackingID `json:"tracking_id,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r bookCargoResponse) error() error { return r.Err } - -func makeBookCargoEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(bookCargoRequest) - id, err := s.BookNewCargo(req.Origin, req.Destination, req.ArrivalDeadline) - return bookCargoResponse{ID: id, Err: err}, nil - } -} - -type loadCargoRequest struct { - ID cargo.TrackingID -} - -type loadCargoResponse struct { - Cargo *Cargo `json:"cargo,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r loadCargoResponse) error() error { return r.Err } - -func makeLoadCargoEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(loadCargoRequest) - c, err := s.LoadCargo(req.ID) - return loadCargoResponse{Cargo: &c, Err: err}, nil - } -} - -type requestRoutesRequest struct { - ID cargo.TrackingID -} - -type requestRoutesResponse struct { - Routes []cargo.Itinerary `json:"routes,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r requestRoutesResponse) error() error { return r.Err } - -func makeRequestRoutesEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(requestRoutesRequest) - itin := s.RequestPossibleRoutesForCargo(req.ID) - return requestRoutesResponse{Routes: itin, Err: nil}, nil - } -} - -type assignToRouteRequest struct { - ID cargo.TrackingID - Itinerary cargo.Itinerary -} - -type assignToRouteResponse struct { - Err error `json:"error,omitempty"` -} - -func (r assignToRouteResponse) error() error { return r.Err } - -func makeAssignToRouteEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(assignToRouteRequest) - err := s.AssignCargoToRoute(req.ID, req.Itinerary) - return assignToRouteResponse{Err: err}, nil - } -} - -type changeDestinationRequest struct { - ID cargo.TrackingID - Destination location.UNLocode -} - -type changeDestinationResponse struct { - Err error `json:"error,omitempty"` -} - -func (r changeDestinationResponse) error() error { return r.Err } - -func makeChangeDestinationEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(changeDestinationRequest) - err := s.ChangeDestination(req.ID, req.Destination) - return changeDestinationResponse{Err: err}, nil - } -} - -type listCargosRequest struct{} - -type listCargosResponse struct { - Cargos []Cargo `json:"cargos,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r listCargosResponse) error() error { return r.Err } - -func makeListCargosEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - _ = request.(listCargosRequest) - return listCargosResponse{Cargos: s.Cargos(), Err: nil}, nil - } -} - -type listLocationsRequest struct { -} - -type listLocationsResponse struct { - Locations []Location `json:"locations,omitempty"` - Err error `json:"error,omitempty"` -} - -func makeListLocationsEndpoint(s Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - _ = request.(listLocationsRequest) - return listLocationsResponse{Locations: s.Locations(), Err: nil}, nil - } -} diff --git a/examples/shipping/booking/instrumenting.go b/examples/shipping/booking/instrumenting.go deleted file mode 100644 index b9b03b91c..000000000 --- a/examples/shipping/booking/instrumenting.go +++ /dev/null @@ -1,88 +0,0 @@ -package booking - -import ( - "time" - - "github.com/go-kit/kit/metrics" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" -) - -type instrumentingService struct { - requestCount metrics.Counter - requestLatency metrics.Histogram - Service -} - -// NewInstrumentingService returns an instance of an instrumenting Service. -func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service { - return &instrumentingService{ - requestCount: counter, - requestLatency: latency, - Service: s, - } -} - -func (s *instrumentingService) BookNewCargo(origin, destination location.UNLocode, deadline time.Time) (cargo.TrackingID, error) { - defer func(begin time.Time) { - s.requestCount.With("method", "book").Add(1) - s.requestLatency.With("method", "book").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.BookNewCargo(origin, destination, deadline) -} - -func (s *instrumentingService) LoadCargo(id cargo.TrackingID) (c Cargo, err error) { - defer func(begin time.Time) { - s.requestCount.With("method", "load").Add(1) - s.requestLatency.With("method", "load").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.LoadCargo(id) -} - -func (s *instrumentingService) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary { - defer func(begin time.Time) { - s.requestCount.With("method", "request_routes").Add(1) - s.requestLatency.With("method", "request_routes").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.RequestPossibleRoutesForCargo(id) -} - -func (s *instrumentingService) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) (err error) { - defer func(begin time.Time) { - s.requestCount.With("method", "assign_to_route").Add(1) - s.requestLatency.With("method", "assign_to_route").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.AssignCargoToRoute(id, itinerary) -} - -func (s *instrumentingService) ChangeDestination(id cargo.TrackingID, l location.UNLocode) (err error) { - defer func(begin time.Time) { - s.requestCount.With("method", "change_destination").Add(1) - s.requestLatency.With("method", "change_destination").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.ChangeDestination(id, l) -} - -func (s *instrumentingService) Cargos() []Cargo { - defer func(begin time.Time) { - s.requestCount.With("method", "list_cargos").Add(1) - s.requestLatency.With("method", "list_cargos").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.Cargos() -} - -func (s *instrumentingService) Locations() []Location { - defer func(begin time.Time) { - s.requestCount.With("method", "list_locations").Add(1) - s.requestLatency.With("method", "list_locations").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.Locations() -} diff --git a/examples/shipping/booking/logging.go b/examples/shipping/booking/logging.go deleted file mode 100644 index 931d43073..000000000 --- a/examples/shipping/booking/logging.go +++ /dev/null @@ -1,102 +0,0 @@ -package booking - -import ( - "time" - - "github.com/go-kit/kit/log" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" -) - -type loggingService struct { - logger log.Logger - Service -} - -// NewLoggingService returns a new instance of a logging Service. -func NewLoggingService(logger log.Logger, s Service) Service { - return &loggingService{logger, s} -} - -func (s *loggingService) BookNewCargo(origin location.UNLocode, destination location.UNLocode, deadline time.Time) (id cargo.TrackingID, err error) { - defer func(begin time.Time) { - s.logger.Log( - "method", "book", - "origin", origin, - "destination", destination, - "arrival_deadline", deadline, - "took", time.Since(begin), - "err", err, - ) - }(time.Now()) - return s.Service.BookNewCargo(origin, destination, deadline) -} - -func (s *loggingService) LoadCargo(id cargo.TrackingID) (c Cargo, err error) { - defer func(begin time.Time) { - s.logger.Log( - "method", "load", - "tracking_id", id, - "took", time.Since(begin), - "err", err, - ) - }(time.Now()) - return s.Service.LoadCargo(id) -} - -func (s *loggingService) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary { - defer func(begin time.Time) { - s.logger.Log( - "method", "request_routes", - "tracking_id", id, - "took", time.Since(begin), - ) - }(time.Now()) - return s.Service.RequestPossibleRoutesForCargo(id) -} - -func (s *loggingService) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) (err error) { - defer func(begin time.Time) { - s.logger.Log( - "method", "assign_to_route", - "tracking_id", id, - "took", time.Since(begin), - "err", err, - ) - }(time.Now()) - return s.Service.AssignCargoToRoute(id, itinerary) -} - -func (s *loggingService) ChangeDestination(id cargo.TrackingID, l location.UNLocode) (err error) { - defer func(begin time.Time) { - s.logger.Log( - "method", "change_destination", - "tracking_id", id, - "destination", l, - "took", time.Since(begin), - "err", err, - ) - }(time.Now()) - return s.Service.ChangeDestination(id, l) -} - -func (s *loggingService) Cargos() []Cargo { - defer func(begin time.Time) { - s.logger.Log( - "method", "list_cargos", - "took", time.Since(begin), - ) - }(time.Now()) - return s.Service.Cargos() -} - -func (s *loggingService) Locations() []Location { - defer func(begin time.Time) { - s.logger.Log( - "method", "list_locations", - "took", time.Since(begin), - ) - }(time.Now()) - return s.Service.Locations() -} diff --git a/examples/shipping/booking/service.go b/examples/shipping/booking/service.go deleted file mode 100644 index 8689a5a51..000000000 --- a/examples/shipping/booking/service.go +++ /dev/null @@ -1,197 +0,0 @@ -// Package booking provides the use-case of booking a cargo. Used by views -// facing an administrator. -package booking - -import ( - "errors" - "time" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/routing" -) - -// ErrInvalidArgument is returned when one or more arguments are invalid. -var ErrInvalidArgument = errors.New("invalid argument") - -// Service is the interface that provides booking methods. -type Service interface { - // BookNewCargo registers a new cargo in the tracking system, not yet - // routed. - BookNewCargo(origin location.UNLocode, destination location.UNLocode, deadline time.Time) (cargo.TrackingID, error) - - // LoadCargo returns a read model of a cargo. - LoadCargo(id cargo.TrackingID) (Cargo, error) - - // RequestPossibleRoutesForCargo requests a list of itineraries describing - // possible routes for this cargo. - RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary - - // AssignCargoToRoute assigns a cargo to the route specified by the - // itinerary. - AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) error - - // ChangeDestination changes the destination of a cargo. - ChangeDestination(id cargo.TrackingID, destination location.UNLocode) error - - // Cargos returns a list of all cargos that have been booked. - Cargos() []Cargo - - // Locations returns a list of registered locations. - Locations() []Location -} - -type service struct { - cargos cargo.Repository - locations location.Repository - handlingEvents cargo.HandlingEventRepository - routingService routing.Service -} - -func (s *service) AssignCargoToRoute(id cargo.TrackingID, itinerary cargo.Itinerary) error { - if id == "" || len(itinerary.Legs) == 0 { - return ErrInvalidArgument - } - - c, err := s.cargos.Find(id) - if err != nil { - return err - } - - c.AssignToRoute(itinerary) - - return s.cargos.Store(c) -} - -func (s *service) BookNewCargo(origin, destination location.UNLocode, deadline time.Time) (cargo.TrackingID, error) { - if origin == "" || destination == "" || deadline.IsZero() { - return "", ErrInvalidArgument - } - - id := cargo.NextTrackingID() - rs := cargo.RouteSpecification{ - Origin: origin, - Destination: destination, - ArrivalDeadline: deadline, - } - - c := cargo.New(id, rs) - - if err := s.cargos.Store(c); err != nil { - return "", err - } - - return c.TrackingID, nil -} - -func (s *service) LoadCargo(id cargo.TrackingID) (Cargo, error) { - if id == "" { - return Cargo{}, ErrInvalidArgument - } - - c, err := s.cargos.Find(id) - if err != nil { - return Cargo{}, err - } - - return assemble(c, s.handlingEvents), nil -} - -func (s *service) ChangeDestination(id cargo.TrackingID, destination location.UNLocode) error { - if id == "" || destination == "" { - return ErrInvalidArgument - } - - c, err := s.cargos.Find(id) - if err != nil { - return err - } - - l, err := s.locations.Find(destination) - if err != nil { - return err - } - - c.SpecifyNewRoute(cargo.RouteSpecification{ - Origin: c.Origin, - Destination: l.UNLocode, - ArrivalDeadline: c.RouteSpecification.ArrivalDeadline, - }) - - if err := s.cargos.Store(c); err != nil { - return err - } - - return nil -} - -func (s *service) RequestPossibleRoutesForCargo(id cargo.TrackingID) []cargo.Itinerary { - if id == "" { - return nil - } - - c, err := s.cargos.Find(id) - if err != nil { - return []cargo.Itinerary{} - } - - return s.routingService.FetchRoutesForSpecification(c.RouteSpecification) -} - -func (s *service) Cargos() []Cargo { - var result []Cargo - for _, c := range s.cargos.FindAll() { - result = append(result, assemble(c, s.handlingEvents)) - } - return result -} - -func (s *service) Locations() []Location { - var result []Location - for _, v := range s.locations.FindAll() { - result = append(result, Location{ - UNLocode: string(v.UNLocode), - Name: v.Name, - }) - } - return result -} - -// NewService creates a booking service with necessary dependencies. -func NewService(cargos cargo.Repository, locations location.Repository, events cargo.HandlingEventRepository, rs routing.Service) Service { - return &service{ - cargos: cargos, - locations: locations, - handlingEvents: events, - routingService: rs, - } -} - -// Location is a read model for booking views. -type Location struct { - UNLocode string `json:"locode"` - Name string `json:"name"` -} - -// Cargo is a read model for booking views. -type Cargo struct { - ArrivalDeadline time.Time `json:"arrival_deadline"` - Destination string `json:"destination"` - Legs []cargo.Leg `json:"legs,omitempty"` - Misrouted bool `json:"misrouted"` - Origin string `json:"origin"` - Routed bool `json:"routed"` - TrackingID string `json:"tracking_id"` -} - -func assemble(c *cargo.Cargo, events cargo.HandlingEventRepository) Cargo { - return Cargo{ - TrackingID: string(c.TrackingID), - Origin: string(c.Origin), - Destination: string(c.RouteSpecification.Destination), - Misrouted: c.Delivery.RoutingStatus == cargo.Misrouted, - Routed: !c.Itinerary.IsEmpty(), - ArrivalDeadline: c.RouteSpecification.ArrivalDeadline, - Legs: c.Itinerary.Legs, - } -} diff --git a/examples/shipping/booking/transport.go b/examples/shipping/booking/transport.go deleted file mode 100644 index a1e9a10e4..000000000 --- a/examples/shipping/booking/transport.go +++ /dev/null @@ -1,195 +0,0 @@ -package booking - -import ( - "context" - "encoding/json" - "errors" - "net/http" - "time" - - "github.com/gorilla/mux" - - kitlog "github.com/go-kit/kit/log" - "github.com/go-kit/kit/transport" - kithttp "github.com/go-kit/kit/transport/http" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" -) - -// MakeHandler returns a handler for the booking service. -func MakeHandler(bs Service, logger kitlog.Logger) http.Handler { - opts := []kithttp.ServerOption{ - kithttp.ServerErrorHandler(transport.NewLogErrorHandler(logger)), - kithttp.ServerErrorEncoder(encodeError), - } - - bookCargoHandler := kithttp.NewServer( - makeBookCargoEndpoint(bs), - decodeBookCargoRequest, - encodeResponse, - opts..., - ) - loadCargoHandler := kithttp.NewServer( - makeLoadCargoEndpoint(bs), - decodeLoadCargoRequest, - encodeResponse, - opts..., - ) - requestRoutesHandler := kithttp.NewServer( - makeRequestRoutesEndpoint(bs), - decodeRequestRoutesRequest, - encodeResponse, - opts..., - ) - assignToRouteHandler := kithttp.NewServer( - makeAssignToRouteEndpoint(bs), - decodeAssignToRouteRequest, - encodeResponse, - opts..., - ) - changeDestinationHandler := kithttp.NewServer( - makeChangeDestinationEndpoint(bs), - decodeChangeDestinationRequest, - encodeResponse, - opts..., - ) - listCargosHandler := kithttp.NewServer( - makeListCargosEndpoint(bs), - decodeListCargosRequest, - encodeResponse, - opts..., - ) - listLocationsHandler := kithttp.NewServer( - makeListLocationsEndpoint(bs), - decodeListLocationsRequest, - encodeResponse, - opts..., - ) - - r := mux.NewRouter() - - r.Handle("/booking/v1/cargos", bookCargoHandler).Methods("POST") - r.Handle("/booking/v1/cargos", listCargosHandler).Methods("GET") - r.Handle("/booking/v1/cargos/{id}", loadCargoHandler).Methods("GET") - r.Handle("/booking/v1/cargos/{id}/request_routes", requestRoutesHandler).Methods("GET") - r.Handle("/booking/v1/cargos/{id}/assign_to_route", assignToRouteHandler).Methods("POST") - r.Handle("/booking/v1/cargos/{id}/change_destination", changeDestinationHandler).Methods("POST") - r.Handle("/booking/v1/locations", listLocationsHandler).Methods("GET") - - return r -} - -var errBadRoute = errors.New("bad route") - -func decodeBookCargoRequest(_ context.Context, r *http.Request) (interface{}, error) { - var body struct { - Origin string `json:"origin"` - Destination string `json:"destination"` - ArrivalDeadline time.Time `json:"arrival_deadline"` - } - - if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - return nil, err - } - - return bookCargoRequest{ - Origin: location.UNLocode(body.Origin), - Destination: location.UNLocode(body.Destination), - ArrivalDeadline: body.ArrivalDeadline, - }, nil -} - -func decodeLoadCargoRequest(_ context.Context, r *http.Request) (interface{}, error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, errBadRoute - } - return loadCargoRequest{ID: cargo.TrackingID(id)}, nil -} - -func decodeRequestRoutesRequest(_ context.Context, r *http.Request) (interface{}, error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, errBadRoute - } - return requestRoutesRequest{ID: cargo.TrackingID(id)}, nil -} - -func decodeAssignToRouteRequest(_ context.Context, r *http.Request) (interface{}, error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, errBadRoute - } - - var itinerary cargo.Itinerary - if err := json.NewDecoder(r.Body).Decode(&itinerary); err != nil { - return nil, err - } - - return assignToRouteRequest{ - ID: cargo.TrackingID(id), - Itinerary: itinerary, - }, nil -} - -func decodeChangeDestinationRequest(_ context.Context, r *http.Request) (interface{}, error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, errBadRoute - } - - var body struct { - Destination string `json:"destination"` - } - - if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - return nil, err - } - - return changeDestinationRequest{ - ID: cargo.TrackingID(id), - Destination: location.UNLocode(body.Destination), - }, nil -} - -func decodeListCargosRequest(_ context.Context, r *http.Request) (interface{}, error) { - return listCargosRequest{}, nil -} - -func decodeListLocationsRequest(_ context.Context, r *http.Request) (interface{}, error) { - return listLocationsRequest{}, nil -} - -func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { - if e, ok := response.(errorer); ok && e.error() != nil { - encodeError(ctx, e.error(), w) - return nil - } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - return json.NewEncoder(w).Encode(response) -} - -type errorer interface { - error() error -} - -// encode errors from business-logic -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - switch err { - case cargo.ErrUnknown: - w.WriteHeader(http.StatusNotFound) - case ErrInvalidArgument: - w.WriteHeader(http.StatusBadRequest) - default: - w.WriteHeader(http.StatusInternalServerError) - } - json.NewEncoder(w).Encode(map[string]interface{}{ - "error": err.Error(), - }) -} diff --git a/examples/shipping/cargo/cargo.go b/examples/shipping/cargo/cargo.go deleted file mode 100644 index 4b2fc5b4c..000000000 --- a/examples/shipping/cargo/cargo.go +++ /dev/null @@ -1,137 +0,0 @@ -// Package cargo contains the heart of the domain model. -package cargo - -import ( - "errors" - "strings" - "time" - - "github.com/pborman/uuid" - - "github.com/go-kit/kit/examples/shipping/location" -) - -// TrackingID uniquely identifies a particular cargo. -type TrackingID string - -// Cargo is the central class in the domain model. -type Cargo struct { - TrackingID TrackingID - Origin location.UNLocode - RouteSpecification RouteSpecification - Itinerary Itinerary - Delivery Delivery -} - -// SpecifyNewRoute specifies a new route for this cargo. -func (c *Cargo) SpecifyNewRoute(rs RouteSpecification) { - c.RouteSpecification = rs - c.Delivery = c.Delivery.UpdateOnRouting(c.RouteSpecification, c.Itinerary) -} - -// AssignToRoute attaches a new itinerary to this cargo. -func (c *Cargo) AssignToRoute(itinerary Itinerary) { - c.Itinerary = itinerary - c.Delivery = c.Delivery.UpdateOnRouting(c.RouteSpecification, c.Itinerary) -} - -// DeriveDeliveryProgress updates all aspects of the cargo aggregate status -// based on the current route specification, itinerary and handling of the cargo. -func (c *Cargo) DeriveDeliveryProgress(history HandlingHistory) { - c.Delivery = DeriveDeliveryFrom(c.RouteSpecification, c.Itinerary, history) -} - -// New creates a new, unrouted cargo. -func New(id TrackingID, rs RouteSpecification) *Cargo { - itinerary := Itinerary{} - history := HandlingHistory{make([]HandlingEvent, 0)} - - return &Cargo{ - TrackingID: id, - Origin: rs.Origin, - RouteSpecification: rs, - Delivery: DeriveDeliveryFrom(rs, itinerary, history), - } -} - -// Repository provides access to a cargo store. -type Repository interface { - Store(cargo *Cargo) error - Find(id TrackingID) (*Cargo, error) - FindAll() []*Cargo -} - -// ErrUnknown is used when a cargo could not be found. -var ErrUnknown = errors.New("unknown cargo") - -// NextTrackingID generates a new tracking ID. -// TODO: Move to infrastructure(?) -func NextTrackingID() TrackingID { - return TrackingID(strings.Split(strings.ToUpper(uuid.New()), "-")[0]) -} - -// RouteSpecification Contains information about a route: its origin, -// destination and arrival deadline. -type RouteSpecification struct { - Origin location.UNLocode - Destination location.UNLocode - ArrivalDeadline time.Time -} - -// IsSatisfiedBy checks whether provided itinerary satisfies this -// specification. -func (s RouteSpecification) IsSatisfiedBy(itinerary Itinerary) bool { - return itinerary.Legs != nil && - s.Origin == itinerary.InitialDepartureLocation() && - s.Destination == itinerary.FinalArrivalLocation() -} - -// RoutingStatus describes status of cargo routing. -type RoutingStatus int - -// Valid routing statuses. -const ( - NotRouted RoutingStatus = iota - Misrouted - Routed -) - -func (s RoutingStatus) String() string { - switch s { - case NotRouted: - return "Not routed" - case Misrouted: - return "Misrouted" - case Routed: - return "Routed" - } - return "" -} - -// TransportStatus describes status of cargo transportation. -type TransportStatus int - -// Valid transport statuses. -const ( - NotReceived TransportStatus = iota - InPort - OnboardCarrier - Claimed - Unknown -) - -func (s TransportStatus) String() string { - switch s { - case NotReceived: - return "Not received" - case InPort: - return "In port" - case OnboardCarrier: - return "Onboard carrier" - case Claimed: - return "Claimed" - case Unknown: - return "Unknown" - } - return "" -} diff --git a/examples/shipping/cargo/delivery.go b/examples/shipping/cargo/delivery.go deleted file mode 100644 index 34f079dcc..000000000 --- a/examples/shipping/cargo/delivery.go +++ /dev/null @@ -1,174 +0,0 @@ -package cargo - -import ( - "time" - - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -// Delivery is the actual transportation of the cargo, as opposed to the -// customer requirement (RouteSpecification) and the plan (Itinerary). -type Delivery struct { - Itinerary Itinerary - RouteSpecification RouteSpecification - RoutingStatus RoutingStatus - TransportStatus TransportStatus - NextExpectedActivity HandlingActivity - LastEvent HandlingEvent - LastKnownLocation location.UNLocode - CurrentVoyage voyage.Number - ETA time.Time - IsMisdirected bool - IsUnloadedAtDestination bool -} - -// UpdateOnRouting creates a new delivery snapshot to reflect changes in -// routing, i.e. when the route specification or the itinerary has changed but -// no additional handling of the cargo has been performed. -func (d Delivery) UpdateOnRouting(rs RouteSpecification, itinerary Itinerary) Delivery { - return newDelivery(d.LastEvent, itinerary, rs) -} - -// IsOnTrack checks if the delivery is on track. -func (d Delivery) IsOnTrack() bool { - return d.RoutingStatus == Routed && !d.IsMisdirected -} - -// DeriveDeliveryFrom creates a new delivery snapshot based on the complete -// handling history of a cargo, as well as its route specification and -// itinerary. -func DeriveDeliveryFrom(rs RouteSpecification, itinerary Itinerary, history HandlingHistory) Delivery { - lastEvent, _ := history.MostRecentlyCompletedEvent() - return newDelivery(lastEvent, itinerary, rs) -} - -// newDelivery creates a up-to-date delivery based on an handling event, -// itinerary and a route specification. -func newDelivery(lastEvent HandlingEvent, itinerary Itinerary, rs RouteSpecification) Delivery { - var ( - routingStatus = calculateRoutingStatus(itinerary, rs) - transportStatus = calculateTransportStatus(lastEvent) - lastKnownLocation = calculateLastKnownLocation(lastEvent) - isMisdirected = calculateMisdirectedStatus(lastEvent, itinerary) - isUnloadedAtDestination = calculateUnloadedAtDestination(lastEvent, rs) - currentVoyage = calculateCurrentVoyage(transportStatus, lastEvent) - ) - - d := Delivery{ - LastEvent: lastEvent, - Itinerary: itinerary, - RouteSpecification: rs, - RoutingStatus: routingStatus, - TransportStatus: transportStatus, - LastKnownLocation: lastKnownLocation, - IsMisdirected: isMisdirected, - IsUnloadedAtDestination: isUnloadedAtDestination, - CurrentVoyage: currentVoyage, - } - - d.NextExpectedActivity = calculateNextExpectedActivity(d) - d.ETA = calculateETA(d) - - return d -} - -// Below are internal functions used when creating a new delivery. - -func calculateRoutingStatus(itinerary Itinerary, rs RouteSpecification) RoutingStatus { - if itinerary.Legs == nil { - return NotRouted - } - - if rs.IsSatisfiedBy(itinerary) { - return Routed - } - - return Misrouted -} - -func calculateMisdirectedStatus(event HandlingEvent, itinerary Itinerary) bool { - if event.Activity.Type == NotHandled { - return false - } - - return !itinerary.IsExpected(event) -} - -func calculateUnloadedAtDestination(event HandlingEvent, rs RouteSpecification) bool { - if event.Activity.Type == NotHandled { - return false - } - - return event.Activity.Type == Unload && rs.Destination == event.Activity.Location -} - -func calculateTransportStatus(event HandlingEvent) TransportStatus { - switch event.Activity.Type { - case NotHandled: - return NotReceived - case Load: - return OnboardCarrier - case Unload: - return InPort - case Receive: - return InPort - case Customs: - return InPort - case Claim: - return Claimed - } - return Unknown -} - -func calculateLastKnownLocation(event HandlingEvent) location.UNLocode { - return event.Activity.Location -} - -func calculateNextExpectedActivity(d Delivery) HandlingActivity { - if !d.IsOnTrack() { - return HandlingActivity{} - } - - switch d.LastEvent.Activity.Type { - case NotHandled: - return HandlingActivity{Type: Receive, Location: d.RouteSpecification.Origin} - case Receive: - l := d.Itinerary.Legs[0] - return HandlingActivity{Type: Load, Location: l.LoadLocation, VoyageNumber: l.VoyageNumber} - case Load: - for _, l := range d.Itinerary.Legs { - if l.LoadLocation == d.LastEvent.Activity.Location { - return HandlingActivity{Type: Unload, Location: l.UnloadLocation, VoyageNumber: l.VoyageNumber} - } - } - case Unload: - for i, l := range d.Itinerary.Legs { - if l.UnloadLocation == d.LastEvent.Activity.Location { - if i < len(d.Itinerary.Legs)-1 { - return HandlingActivity{Type: Load, Location: d.Itinerary.Legs[i+1].LoadLocation, VoyageNumber: d.Itinerary.Legs[i+1].VoyageNumber} - } - - return HandlingActivity{Type: Claim, Location: l.UnloadLocation} - } - } - } - - return HandlingActivity{} -} - -func calculateCurrentVoyage(transportStatus TransportStatus, event HandlingEvent) voyage.Number { - if transportStatus == OnboardCarrier && event.Activity.Type != NotHandled { - return event.Activity.VoyageNumber - } - - return voyage.Number("") -} - -func calculateETA(d Delivery) time.Time { - if !d.IsOnTrack() { - return time.Time{} - } - - return d.Itinerary.FinalArrivalTime() -} diff --git a/examples/shipping/cargo/handling.go b/examples/shipping/cargo/handling.go deleted file mode 100644 index bec8509f6..000000000 --- a/examples/shipping/cargo/handling.go +++ /dev/null @@ -1,121 +0,0 @@ -package cargo - -// TODO: It would make sense to have this in its own package. Unfortunately, -// then there would be a circular dependency between the cargo and handling -// packages since cargo.Delivery would use handling.HandlingEvent and -// handling.HandlingEvent would use cargo.TrackingID. Also, -// HandlingEventFactory depends on the cargo repository. -// -// It would make sense not having the cargo package depend on handling. - -import ( - "errors" - "time" - - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -// HandlingActivity represents how and where a cargo can be handled, and can -// be used to express predictions about what is expected to happen to a cargo -// in the future. -type HandlingActivity struct { - Type HandlingEventType - Location location.UNLocode - VoyageNumber voyage.Number -} - -// HandlingEvent is used to register the event when, for instance, a cargo is -// unloaded from a carrier at a some location at a given time. -type HandlingEvent struct { - TrackingID TrackingID - Activity HandlingActivity -} - -// HandlingEventType describes type of a handling event. -type HandlingEventType int - -// Valid handling event types. -const ( - NotHandled HandlingEventType = iota - Load - Unload - Receive - Claim - Customs -) - -func (t HandlingEventType) String() string { - switch t { - case NotHandled: - return "Not Handled" - case Load: - return "Load" - case Unload: - return "Unload" - case Receive: - return "Receive" - case Claim: - return "Claim" - case Customs: - return "Customs" - } - - return "" -} - -// HandlingHistory is the handling history of a cargo. -type HandlingHistory struct { - HandlingEvents []HandlingEvent -} - -// MostRecentlyCompletedEvent returns most recently completed handling event. -func (h HandlingHistory) MostRecentlyCompletedEvent() (HandlingEvent, error) { - if len(h.HandlingEvents) == 0 { - return HandlingEvent{}, errors.New("delivery history is empty") - } - - return h.HandlingEvents[len(h.HandlingEvents)-1], nil -} - -// HandlingEventRepository provides access a handling event store. -type HandlingEventRepository interface { - Store(e HandlingEvent) - QueryHandlingHistory(TrackingID) HandlingHistory -} - -// HandlingEventFactory creates handling events. -type HandlingEventFactory struct { - CargoRepository Repository - VoyageRepository voyage.Repository - LocationRepository location.Repository -} - -// CreateHandlingEvent creates a validated handling event. -func (f *HandlingEventFactory) CreateHandlingEvent(registered time.Time, completed time.Time, id TrackingID, - voyageNumber voyage.Number, unLocode location.UNLocode, eventType HandlingEventType) (HandlingEvent, error) { - - if _, err := f.CargoRepository.Find(id); err != nil { - return HandlingEvent{}, err - } - - if _, err := f.VoyageRepository.Find(voyageNumber); err != nil { - // TODO: This is pretty ugly, but when creating a Receive event, the voyage number is not known. - if len(voyageNumber) > 0 { - return HandlingEvent{}, err - } - } - - if _, err := f.LocationRepository.Find(unLocode); err != nil { - return HandlingEvent{}, err - } - - return HandlingEvent{ - TrackingID: id, - Activity: HandlingActivity{ - Type: eventType, - Location: unLocode, - VoyageNumber: voyageNumber, - }, - }, nil -} diff --git a/examples/shipping/cargo/itinerary.go b/examples/shipping/cargo/itinerary.go deleted file mode 100644 index 6b5088ea5..000000000 --- a/examples/shipping/cargo/itinerary.go +++ /dev/null @@ -1,91 +0,0 @@ -package cargo - -import ( - "time" - - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -// Leg describes the transportation between two locations on a voyage. -type Leg struct { - VoyageNumber voyage.Number `json:"voyage_number"` - LoadLocation location.UNLocode `json:"from"` - UnloadLocation location.UNLocode `json:"to"` - LoadTime time.Time `json:"load_time"` - UnloadTime time.Time `json:"unload_time"` -} - -// NewLeg creates a new itinerary leg. -func NewLeg(voyageNumber voyage.Number, loadLocation, unloadLocation location.UNLocode, loadTime, unloadTime time.Time) Leg { - return Leg{ - VoyageNumber: voyageNumber, - LoadLocation: loadLocation, - UnloadLocation: unloadLocation, - LoadTime: loadTime, - UnloadTime: unloadTime, - } -} - -// Itinerary specifies steps required to transport a cargo from its origin to -// destination. -type Itinerary struct { - Legs []Leg `json:"legs"` -} - -// InitialDepartureLocation returns the start of the itinerary. -func (i Itinerary) InitialDepartureLocation() location.UNLocode { - if i.IsEmpty() { - return location.UNLocode("") - } - return i.Legs[0].LoadLocation -} - -// FinalArrivalLocation returns the end of the itinerary. -func (i Itinerary) FinalArrivalLocation() location.UNLocode { - if i.IsEmpty() { - return location.UNLocode("") - } - return i.Legs[len(i.Legs)-1].UnloadLocation -} - -// FinalArrivalTime returns the expected arrival time at final destination. -func (i Itinerary) FinalArrivalTime() time.Time { - return i.Legs[len(i.Legs)-1].UnloadTime -} - -// IsEmpty checks if the itinerary contains at least one leg. -func (i Itinerary) IsEmpty() bool { - return i.Legs == nil || len(i.Legs) == 0 -} - -// IsExpected checks if the given handling event is expected when executing -// this itinerary. -func (i Itinerary) IsExpected(event HandlingEvent) bool { - if i.IsEmpty() { - return true - } - - switch event.Activity.Type { - case Receive: - return i.InitialDepartureLocation() == event.Activity.Location - case Load: - for _, l := range i.Legs { - if l.LoadLocation == event.Activity.Location && l.VoyageNumber == event.Activity.VoyageNumber { - return true - } - } - return false - case Unload: - for _, l := range i.Legs { - if l.UnloadLocation == event.Activity.Location && l.VoyageNumber == event.Activity.VoyageNumber { - return true - } - } - return false - case Claim: - return i.FinalArrivalLocation() == event.Activity.Location - } - - return true -} diff --git a/examples/shipping/handling/endpoint.go b/examples/shipping/handling/endpoint.go deleted file mode 100644 index 555d08738..000000000 --- a/examples/shipping/handling/endpoint.go +++ /dev/null @@ -1,34 +0,0 @@ -package handling - -import ( - "context" - "time" - - "github.com/go-kit/kit/endpoint" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -type registerIncidentRequest struct { - ID cargo.TrackingID - Location location.UNLocode - Voyage voyage.Number - EventType cargo.HandlingEventType - CompletionTime time.Time -} - -type registerIncidentResponse struct { - Err error `json:"error,omitempty"` -} - -func (r registerIncidentResponse) error() error { return r.Err } - -func makeRegisterIncidentEndpoint(hs Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(registerIncidentRequest) - err := hs.RegisterHandlingEvent(req.CompletionTime, req.ID, req.Voyage, req.Location, req.EventType) - return registerIncidentResponse{Err: err}, nil - } -} diff --git a/examples/shipping/handling/instrumenting.go b/examples/shipping/handling/instrumenting.go deleted file mode 100644 index fecce04e1..000000000 --- a/examples/shipping/handling/instrumenting.go +++ /dev/null @@ -1,37 +0,0 @@ -package handling - -import ( - "time" - - "github.com/go-kit/kit/metrics" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -type instrumentingService struct { - requestCount metrics.Counter - requestLatency metrics.Histogram - Service -} - -// NewInstrumentingService returns an instance of an instrumenting Service. -func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service { - return &instrumentingService{ - requestCount: counter, - requestLatency: latency, - Service: s, - } -} - -func (s *instrumentingService) RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number, - loc location.UNLocode, eventType cargo.HandlingEventType) error { - - defer func(begin time.Time) { - s.requestCount.With("method", "register_incident").Add(1) - s.requestLatency.With("method", "register_incident").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.RegisterHandlingEvent(completed, id, voyageNumber, loc, eventType) -} diff --git a/examples/shipping/handling/logging.go b/examples/shipping/handling/logging.go deleted file mode 100644 index 84722fb47..000000000 --- a/examples/shipping/handling/logging.go +++ /dev/null @@ -1,38 +0,0 @@ -package handling - -import ( - "time" - - "github.com/go-kit/kit/log" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -type loggingService struct { - logger log.Logger - Service -} - -// NewLoggingService returns a new instance of a logging Service. -func NewLoggingService(logger log.Logger, s Service) Service { - return &loggingService{logger, s} -} - -func (s *loggingService) RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number, - unLocode location.UNLocode, eventType cargo.HandlingEventType) (err error) { - defer func(begin time.Time) { - s.logger.Log( - "method", "register_incident", - "tracking_id", id, - "location", unLocode, - "voyage", voyageNumber, - "event_type", eventType, - "completion_time", completed, - "took", time.Since(begin), - "err", err, - ) - }(time.Now()) - return s.Service.RegisterHandlingEvent(completed, id, voyageNumber, unLocode, eventType) -} diff --git a/examples/shipping/handling/service.go b/examples/shipping/handling/service.go deleted file mode 100644 index 83d503a2c..000000000 --- a/examples/shipping/handling/service.go +++ /dev/null @@ -1,76 +0,0 @@ -// Package handling provides the use-case for registering incidents. Used by -// views facing the people handling the cargo along its route. -package handling - -import ( - "errors" - "time" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/inspection" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -// ErrInvalidArgument is returned when one or more arguments are invalid. -var ErrInvalidArgument = errors.New("invalid argument") - -// EventHandler provides a means of subscribing to registered handling events. -type EventHandler interface { - CargoWasHandled(cargo.HandlingEvent) -} - -// Service provides handling operations. -type Service interface { - // RegisterHandlingEvent registers a handling event in the system, and - // notifies interested parties that a cargo has been handled. - RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number, - unLocode location.UNLocode, eventType cargo.HandlingEventType) error -} - -type service struct { - handlingEventRepository cargo.HandlingEventRepository - handlingEventFactory cargo.HandlingEventFactory - handlingEventHandler EventHandler -} - -func (s *service) RegisterHandlingEvent(completed time.Time, id cargo.TrackingID, voyageNumber voyage.Number, - loc location.UNLocode, eventType cargo.HandlingEventType) error { - if completed.IsZero() || id == "" || loc == "" || eventType == cargo.NotHandled { - return ErrInvalidArgument - } - - e, err := s.handlingEventFactory.CreateHandlingEvent(time.Now(), completed, id, voyageNumber, loc, eventType) - if err != nil { - return err - } - - s.handlingEventRepository.Store(e) - s.handlingEventHandler.CargoWasHandled(e) - - return nil -} - -// NewService creates a handling event service with necessary dependencies. -func NewService(r cargo.HandlingEventRepository, f cargo.HandlingEventFactory, h EventHandler) Service { - return &service{ - handlingEventRepository: r, - handlingEventFactory: f, - handlingEventHandler: h, - } -} - -type handlingEventHandler struct { - InspectionService inspection.Service -} - -func (h *handlingEventHandler) CargoWasHandled(event cargo.HandlingEvent) { - h.InspectionService.InspectCargo(event.TrackingID) -} - -// NewEventHandler returns a new instance of a EventHandler. -func NewEventHandler(s inspection.Service) EventHandler { - return &handlingEventHandler{ - InspectionService: s, - } -} diff --git a/examples/shipping/handling/transport.go b/examples/shipping/handling/transport.go deleted file mode 100644 index e8a961aee..000000000 --- a/examples/shipping/handling/transport.go +++ /dev/null @@ -1,101 +0,0 @@ -package handling - -import ( - "context" - "encoding/json" - "net/http" - "time" - - "github.com/gorilla/mux" - - kitlog "github.com/go-kit/kit/log" - "github.com/go-kit/kit/transport" - kithttp "github.com/go-kit/kit/transport/http" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -// MakeHandler returns a handler for the handling service. -func MakeHandler(hs Service, logger kitlog.Logger) http.Handler { - r := mux.NewRouter() - - opts := []kithttp.ServerOption{ - kithttp.ServerErrorHandler(transport.NewLogErrorHandler(logger)), - kithttp.ServerErrorEncoder(encodeError), - } - - registerIncidentHandler := kithttp.NewServer( - makeRegisterIncidentEndpoint(hs), - decodeRegisterIncidentRequest, - encodeResponse, - opts..., - ) - - r.Handle("/handling/v1/incidents", registerIncidentHandler).Methods("POST") - - return r -} - -func decodeRegisterIncidentRequest(_ context.Context, r *http.Request) (interface{}, error) { - var body struct { - CompletionTime time.Time `json:"completion_time"` - TrackingID string `json:"tracking_id"` - VoyageNumber string `json:"voyage"` - Location string `json:"location"` - EventType string `json:"event_type"` - } - - if err := json.NewDecoder(r.Body).Decode(&body); err != nil { - return nil, err - } - - return registerIncidentRequest{ - CompletionTime: body.CompletionTime, - ID: cargo.TrackingID(body.TrackingID), - Voyage: voyage.Number(body.VoyageNumber), - Location: location.UNLocode(body.Location), - EventType: stringToEventType(body.EventType), - }, nil -} - -func stringToEventType(s string) cargo.HandlingEventType { - types := map[string]cargo.HandlingEventType{ - cargo.Receive.String(): cargo.Receive, - cargo.Load.String(): cargo.Load, - cargo.Unload.String(): cargo.Unload, - cargo.Customs.String(): cargo.Customs, - cargo.Claim.String(): cargo.Claim, - } - return types[s] -} - -func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { - if e, ok := response.(errorer); ok && e.error() != nil { - encodeError(ctx, e.error(), w) - return nil - } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - return json.NewEncoder(w).Encode(response) -} - -type errorer interface { - error() error -} - -// encode errors from business-logic -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - switch err { - case cargo.ErrUnknown: - w.WriteHeader(http.StatusNotFound) - case ErrInvalidArgument: - w.WriteHeader(http.StatusBadRequest) - default: - w.WriteHeader(http.StatusInternalServerError) - } - json.NewEncoder(w).Encode(map[string]interface{}{ - "error": err.Error(), - }) -} diff --git a/examples/shipping/inmem/inmem.go b/examples/shipping/inmem/inmem.go deleted file mode 100644 index f941b7ebe..000000000 --- a/examples/shipping/inmem/inmem.go +++ /dev/null @@ -1,142 +0,0 @@ -// Package inmem provides in-memory implementations of all the domain repositories. -package inmem - -import ( - "sync" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -type cargoRepository struct { - mtx sync.RWMutex - cargos map[cargo.TrackingID]*cargo.Cargo -} - -func (r *cargoRepository) Store(c *cargo.Cargo) error { - r.mtx.Lock() - defer r.mtx.Unlock() - r.cargos[c.TrackingID] = c - return nil -} - -func (r *cargoRepository) Find(id cargo.TrackingID) (*cargo.Cargo, error) { - r.mtx.RLock() - defer r.mtx.RUnlock() - if val, ok := r.cargos[id]; ok { - return val, nil - } - return nil, cargo.ErrUnknown -} - -func (r *cargoRepository) FindAll() []*cargo.Cargo { - r.mtx.RLock() - defer r.mtx.RUnlock() - c := make([]*cargo.Cargo, 0, len(r.cargos)) - for _, val := range r.cargos { - c = append(c, val) - } - return c -} - -// NewCargoRepository returns a new instance of a in-memory cargo repository. -func NewCargoRepository() cargo.Repository { - return &cargoRepository{ - cargos: make(map[cargo.TrackingID]*cargo.Cargo), - } -} - -type locationRepository struct { - locations map[location.UNLocode]*location.Location -} - -func (r *locationRepository) Find(locode location.UNLocode) (*location.Location, error) { - if l, ok := r.locations[locode]; ok { - return l, nil - } - return nil, location.ErrUnknown -} - -func (r *locationRepository) FindAll() []*location.Location { - l := make([]*location.Location, 0, len(r.locations)) - for _, val := range r.locations { - l = append(l, val) - } - return l -} - -// NewLocationRepository returns a new instance of a in-memory location repository. -func NewLocationRepository() location.Repository { - r := &locationRepository{ - locations: make(map[location.UNLocode]*location.Location), - } - - r.locations[location.SESTO] = location.Stockholm - r.locations[location.AUMEL] = location.Melbourne - r.locations[location.CNHKG] = location.Hongkong - r.locations[location.JNTKO] = location.Tokyo - r.locations[location.NLRTM] = location.Rotterdam - r.locations[location.DEHAM] = location.Hamburg - - return r -} - -type voyageRepository struct { - voyages map[voyage.Number]*voyage.Voyage -} - -func (r *voyageRepository) Find(voyageNumber voyage.Number) (*voyage.Voyage, error) { - if v, ok := r.voyages[voyageNumber]; ok { - return v, nil - } - - return nil, voyage.ErrUnknown -} - -// NewVoyageRepository returns a new instance of a in-memory voyage repository. -func NewVoyageRepository() voyage.Repository { - r := &voyageRepository{ - voyages: make(map[voyage.Number]*voyage.Voyage), - } - - r.voyages[voyage.V100.Number] = voyage.V100 - r.voyages[voyage.V300.Number] = voyage.V300 - r.voyages[voyage.V400.Number] = voyage.V400 - - r.voyages[voyage.V0100S.Number] = voyage.V0100S - r.voyages[voyage.V0200T.Number] = voyage.V0200T - r.voyages[voyage.V0300A.Number] = voyage.V0300A - r.voyages[voyage.V0301S.Number] = voyage.V0301S - r.voyages[voyage.V0400S.Number] = voyage.V0400S - - return r -} - -type handlingEventRepository struct { - mtx sync.RWMutex - events map[cargo.TrackingID][]cargo.HandlingEvent -} - -func (r *handlingEventRepository) Store(e cargo.HandlingEvent) { - r.mtx.Lock() - defer r.mtx.Unlock() - // Make array if it's the first event with this tracking ID. - if _, ok := r.events[e.TrackingID]; !ok { - r.events[e.TrackingID] = make([]cargo.HandlingEvent, 0) - } - r.events[e.TrackingID] = append(r.events[e.TrackingID], e) -} - -func (r *handlingEventRepository) QueryHandlingHistory(id cargo.TrackingID) cargo.HandlingHistory { - r.mtx.RLock() - defer r.mtx.RUnlock() - return cargo.HandlingHistory{HandlingEvents: r.events[id]} -} - -// NewHandlingEventRepository returns a new instance of a in-memory handling event repository. -func NewHandlingEventRepository() cargo.HandlingEventRepository { - return &handlingEventRepository{ - events: make(map[cargo.TrackingID][]cargo.HandlingEvent), - } -} diff --git a/examples/shipping/inspection/inspection.go b/examples/shipping/inspection/inspection.go deleted file mode 100644 index 2ebf73d45..000000000 --- a/examples/shipping/inspection/inspection.go +++ /dev/null @@ -1,53 +0,0 @@ -// Package inspection provides means to inspect cargos. -package inspection - -import ( - "github.com/go-kit/kit/examples/shipping/cargo" -) - -// EventHandler provides means of subscribing to inspection events. -type EventHandler interface { - CargoWasMisdirected(*cargo.Cargo) - CargoHasArrived(*cargo.Cargo) -} - -// Service provides cargo inspection operations. -type Service interface { - // InspectCargo inspects cargo and send relevant notifications to - // interested parties, for example if a cargo has been misdirected, or - // unloaded at the final destination. - InspectCargo(id cargo.TrackingID) -} - -type service struct { - cargos cargo.Repository - events cargo.HandlingEventRepository - handler EventHandler -} - -// TODO: Should be transactional -func (s *service) InspectCargo(id cargo.TrackingID) { - c, err := s.cargos.Find(id) - if err != nil { - return - } - - h := s.events.QueryHandlingHistory(id) - - c.DeriveDeliveryProgress(h) - - if c.Delivery.IsMisdirected { - s.handler.CargoWasMisdirected(c) - } - - if c.Delivery.IsUnloadedAtDestination { - s.handler.CargoHasArrived(c) - } - - s.cargos.Store(c) -} - -// NewService creates a inspection service with necessary dependencies. -func NewService(cargos cargo.Repository, events cargo.HandlingEventRepository, handler EventHandler) Service { - return &service{cargos, events, handler} -} diff --git a/examples/shipping/location/location.go b/examples/shipping/location/location.go deleted file mode 100644 index ee2e5d45c..000000000 --- a/examples/shipping/location/location.go +++ /dev/null @@ -1,29 +0,0 @@ -// Package location provides the Location aggregate. -package location - -import ( - "errors" -) - -// UNLocode is the United Nations location code that uniquely identifies a -// particular location. -// -// http://www.unece.org/cefact/locode/ -// http://www.unece.org/cefact/locode/DocColumnDescription.htm#LOCODE -type UNLocode string - -// Location is a location is our model is stops on a journey, such as cargo -// origin or destination, or carrier movement endpoints. -type Location struct { - UNLocode UNLocode - Name string -} - -// ErrUnknown is used when a location could not be found. -var ErrUnknown = errors.New("unknown location") - -// Repository provides access a location store. -type Repository interface { - Find(locode UNLocode) (*Location, error) - FindAll() []*Location -} diff --git a/examples/shipping/location/sample_locations.go b/examples/shipping/location/sample_locations.go deleted file mode 100644 index 7fd34efa1..000000000 --- a/examples/shipping/location/sample_locations.go +++ /dev/null @@ -1,27 +0,0 @@ -package location - -// Sample UN locodes. -var ( - SESTO UNLocode = "SESTO" - AUMEL UNLocode = "AUMEL" - CNHKG UNLocode = "CNHKG" - USNYC UNLocode = "USNYC" - USCHI UNLocode = "USCHI" - JNTKO UNLocode = "JNTKO" - DEHAM UNLocode = "DEHAM" - NLRTM UNLocode = "NLRTM" - FIHEL UNLocode = "FIHEL" -) - -// Sample locations. -var ( - Stockholm = &Location{SESTO, "Stockholm"} - Melbourne = &Location{AUMEL, "Melbourne"} - Hongkong = &Location{CNHKG, "Hongkong"} - NewYork = &Location{USNYC, "New York"} - Chicago = &Location{USCHI, "Chicago"} - Tokyo = &Location{JNTKO, "Tokyo"} - Hamburg = &Location{DEHAM, "Hamburg"} - Rotterdam = &Location{NLRTM, "Rotterdam"} - Helsinki = &Location{FIHEL, "Helsinki"} -) diff --git a/examples/shipping/main.go b/examples/shipping/main.go deleted file mode 100644 index 8337d61da..000000000 --- a/examples/shipping/main.go +++ /dev/null @@ -1,200 +0,0 @@ -package main - -import ( - "context" - "flag" - "fmt" - "net/http" - "os" - "os/signal" - "syscall" - "time" - - stdprometheus "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - - "github.com/go-kit/kit/log" - kitprometheus "github.com/go-kit/kit/metrics/prometheus" - - "github.com/go-kit/kit/examples/shipping/booking" - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/handling" - "github.com/go-kit/kit/examples/shipping/inmem" - "github.com/go-kit/kit/examples/shipping/inspection" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/routing" - "github.com/go-kit/kit/examples/shipping/tracking" -) - -const ( - defaultPort = "8080" - defaultRoutingServiceURL = "http://localhost:7878" -) - -func main() { - var ( - addr = envString("PORT", defaultPort) - rsurl = envString("ROUTINGSERVICE_URL", defaultRoutingServiceURL) - - httpAddr = flag.String("http.addr", ":"+addr, "HTTP listen address") - routingServiceURL = flag.String("service.routing", rsurl, "routing service URL") - - ctx = context.Background() - ) - - flag.Parse() - - var logger log.Logger - logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr)) - logger = log.With(logger, "ts", log.DefaultTimestampUTC) - - var ( - cargos = inmem.NewCargoRepository() - locations = inmem.NewLocationRepository() - voyages = inmem.NewVoyageRepository() - handlingEvents = inmem.NewHandlingEventRepository() - ) - - // Configure some questionable dependencies. - var ( - handlingEventFactory = cargo.HandlingEventFactory{ - CargoRepository: cargos, - VoyageRepository: voyages, - LocationRepository: locations, - } - handlingEventHandler = handling.NewEventHandler( - inspection.NewService(cargos, handlingEvents, nil), - ) - ) - - // Facilitate testing by adding some cargos. - storeTestData(cargos) - - fieldKeys := []string{"method"} - - var rs routing.Service - rs = routing.NewProxyingMiddleware(ctx, *routingServiceURL)(rs) - - var bs booking.Service - bs = booking.NewService(cargos, locations, handlingEvents, rs) - bs = booking.NewLoggingService(log.With(logger, "component", "booking"), bs) - bs = booking.NewInstrumentingService( - kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "api", - Subsystem: "booking_service", - Name: "request_count", - Help: "Number of requests received.", - }, fieldKeys), - kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "api", - Subsystem: "booking_service", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, fieldKeys), - bs, - ) - - var ts tracking.Service - ts = tracking.NewService(cargos, handlingEvents) - ts = tracking.NewLoggingService(log.With(logger, "component", "tracking"), ts) - ts = tracking.NewInstrumentingService( - kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "api", - Subsystem: "tracking_service", - Name: "request_count", - Help: "Number of requests received.", - }, fieldKeys), - kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "api", - Subsystem: "tracking_service", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, fieldKeys), - ts, - ) - - var hs handling.Service - hs = handling.NewService(handlingEvents, handlingEventFactory, handlingEventHandler) - hs = handling.NewLoggingService(log.With(logger, "component", "handling"), hs) - hs = handling.NewInstrumentingService( - kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "api", - Subsystem: "handling_service", - Name: "request_count", - Help: "Number of requests received.", - }, fieldKeys), - kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "api", - Subsystem: "handling_service", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, fieldKeys), - hs, - ) - - httpLogger := log.With(logger, "component", "http") - - mux := http.NewServeMux() - - mux.Handle("/booking/v1/", booking.MakeHandler(bs, httpLogger)) - mux.Handle("/tracking/v1/", tracking.MakeHandler(ts, httpLogger)) - mux.Handle("/handling/v1/", handling.MakeHandler(hs, httpLogger)) - - http.Handle("/", accessControl(mux)) - http.Handle("/metrics", promhttp.Handler()) - - errs := make(chan error, 2) - go func() { - logger.Log("transport", "http", "address", *httpAddr, "msg", "listening") - errs <- http.ListenAndServe(*httpAddr, nil) - }() - go func() { - c := make(chan os.Signal) - signal.Notify(c, syscall.SIGINT) - errs <- fmt.Errorf("%s", <-c) - }() - - logger.Log("terminated", <-errs) -} - -func accessControl(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Access-Control-Allow-Origin", "*") - w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") - w.Header().Set("Access-Control-Allow-Headers", "Origin, Content-Type") - - if r.Method == "OPTIONS" { - return - } - - h.ServeHTTP(w, r) - }) -} - -func envString(env, fallback string) string { - e := os.Getenv(env) - if e == "" { - return fallback - } - return e -} - -func storeTestData(r cargo.Repository) { - test1 := cargo.New("FTL456", cargo.RouteSpecification{ - Origin: location.AUMEL, - Destination: location.SESTO, - ArrivalDeadline: time.Now().AddDate(0, 0, 7), - }) - if err := r.Store(test1); err != nil { - panic(err) - } - - test2 := cargo.New("ABC123", cargo.RouteSpecification{ - Origin: location.SESTO, - Destination: location.CNHKG, - ArrivalDeadline: time.Now().AddDate(0, 0, 14), - }) - if err := r.Store(test2); err != nil { - panic(err) - } -} diff --git a/examples/shipping/routing/proxying.go b/examples/shipping/routing/proxying.go deleted file mode 100644 index 0c9150b1e..000000000 --- a/examples/shipping/routing/proxying.go +++ /dev/null @@ -1,117 +0,0 @@ -package routing - -import ( - "context" - "encoding/json" - "net/http" - "net/url" - "time" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - kithttp "github.com/go-kit/kit/transport/http" - - "github.com/go-kit/kit/examples/shipping/cargo" - "github.com/go-kit/kit/examples/shipping/location" - "github.com/go-kit/kit/examples/shipping/voyage" -) - -type proxyService struct { - context.Context - FetchRoutesEndpoint endpoint.Endpoint - Service -} - -func (s proxyService) FetchRoutesForSpecification(rs cargo.RouteSpecification) []cargo.Itinerary { - response, err := s.FetchRoutesEndpoint(s.Context, fetchRoutesRequest{ - From: string(rs.Origin), - To: string(rs.Destination), - }) - if err != nil { - return []cargo.Itinerary{} - } - - resp := response.(fetchRoutesResponse) - - var itineraries []cargo.Itinerary - for _, r := range resp.Paths { - var legs []cargo.Leg - for _, e := range r.Edges { - legs = append(legs, cargo.Leg{ - VoyageNumber: voyage.Number(e.Voyage), - LoadLocation: location.UNLocode(e.Origin), - UnloadLocation: location.UNLocode(e.Destination), - LoadTime: e.Departure, - UnloadTime: e.Arrival, - }) - } - - itineraries = append(itineraries, cargo.Itinerary{Legs: legs}) - } - - return itineraries -} - -// ServiceMiddleware defines a middleware for a routing service. -type ServiceMiddleware func(Service) Service - -// NewProxyingMiddleware returns a new instance of a proxying middleware. -func NewProxyingMiddleware(ctx context.Context, proxyURL string) ServiceMiddleware { - return func(next Service) Service { - var e endpoint.Endpoint - e = makeFetchRoutesEndpoint(ctx, proxyURL) - e = circuitbreaker.Hystrix("fetch-routes")(e) - return proxyService{ctx, e, next} - } -} - -type fetchRoutesRequest struct { - From string - To string -} - -type fetchRoutesResponse struct { - Paths []struct { - Edges []struct { - Origin string `json:"origin"` - Destination string `json:"destination"` - Voyage string `json:"voyage"` - Departure time.Time `json:"departure"` - Arrival time.Time `json:"arrival"` - } `json:"edges"` - } `json:"paths"` -} - -func makeFetchRoutesEndpoint(ctx context.Context, instance string) endpoint.Endpoint { - u, err := url.Parse(instance) - if err != nil { - panic(err) - } - if u.Path == "" { - u.Path = "/paths" - } - return kithttp.NewClient( - "GET", u, - encodeFetchRoutesRequest, - decodeFetchRoutesResponse, - ).Endpoint() -} - -func decodeFetchRoutesResponse(_ context.Context, resp *http.Response) (interface{}, error) { - var response fetchRoutesResponse - if err := json.NewDecoder(resp.Body).Decode(&response); err != nil { - return nil, err - } - return response, nil -} - -func encodeFetchRoutesRequest(_ context.Context, r *http.Request, request interface{}) error { - req := request.(fetchRoutesRequest) - - vals := r.URL.Query() - vals.Add("from", req.From) - vals.Add("to", req.To) - r.URL.RawQuery = vals.Encode() - - return nil -} diff --git a/examples/shipping/routing/routing.go b/examples/shipping/routing/routing.go deleted file mode 100644 index 50496f2b8..000000000 --- a/examples/shipping/routing/routing.go +++ /dev/null @@ -1,15 +0,0 @@ -// Package routing provides the routing domain service. It does not actually -// implement the routing service but merely acts as a proxy for a separate -// bounded context. -package routing - -import ( - "github.com/go-kit/kit/examples/shipping/cargo" -) - -// Service provides access to an external routing service. -type Service interface { - // FetchRoutesForSpecification finds all possible routes that satisfy a - // given specification. - FetchRoutesForSpecification(rs cargo.RouteSpecification) []cargo.Itinerary -} diff --git a/examples/shipping/tracking/endpoint.go b/examples/shipping/tracking/endpoint.go deleted file mode 100644 index ddb13172f..000000000 --- a/examples/shipping/tracking/endpoint.go +++ /dev/null @@ -1,26 +0,0 @@ -package tracking - -import ( - "context" - - "github.com/go-kit/kit/endpoint" -) - -type trackCargoRequest struct { - ID string -} - -type trackCargoResponse struct { - Cargo *Cargo `json:"cargo,omitempty"` - Err error `json:"error,omitempty"` -} - -func (r trackCargoResponse) error() error { return r.Err } - -func makeTrackCargoEndpoint(ts Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(trackCargoRequest) - c, err := ts.Track(req.ID) - return trackCargoResponse{Cargo: &c, Err: err}, nil - } -} diff --git a/examples/shipping/tracking/instrumenting.go b/examples/shipping/tracking/instrumenting.go deleted file mode 100644 index f5dc018b0..000000000 --- a/examples/shipping/tracking/instrumenting.go +++ /dev/null @@ -1,31 +0,0 @@ -package tracking - -import ( - "time" - - "github.com/go-kit/kit/metrics" -) - -type instrumentingService struct { - requestCount metrics.Counter - requestLatency metrics.Histogram - Service -} - -// NewInstrumentingService returns an instance of an instrumenting Service. -func NewInstrumentingService(counter metrics.Counter, latency metrics.Histogram, s Service) Service { - return &instrumentingService{ - requestCount: counter, - requestLatency: latency, - Service: s, - } -} - -func (s *instrumentingService) Track(id string) (Cargo, error) { - defer func(begin time.Time) { - s.requestCount.With("method", "track").Add(1) - s.requestLatency.With("method", "track").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return s.Service.Track(id) -} diff --git a/examples/shipping/tracking/logging.go b/examples/shipping/tracking/logging.go deleted file mode 100644 index 584aeaa4b..000000000 --- a/examples/shipping/tracking/logging.go +++ /dev/null @@ -1,24 +0,0 @@ -package tracking - -import ( - "time" - - "github.com/go-kit/kit/log" -) - -type loggingService struct { - logger log.Logger - Service -} - -// NewLoggingService returns a new instance of a logging Service. -func NewLoggingService(logger log.Logger, s Service) Service { - return &loggingService{logger, s} -} - -func (s *loggingService) Track(id string) (c Cargo, err error) { - defer func(begin time.Time) { - s.logger.Log("method", "track", "tracking_id", id, "took", time.Since(begin), "err", err) - }(time.Now()) - return s.Service.Track(id) -} diff --git a/examples/shipping/tracking/service.go b/examples/shipping/tracking/service.go deleted file mode 100644 index b0e360b23..000000000 --- a/examples/shipping/tracking/service.go +++ /dev/null @@ -1,163 +0,0 @@ -// Package tracking provides the use-case of tracking a cargo. Used by views -// facing the end-user. -package tracking - -import ( - "errors" - "fmt" - "strings" - "time" - - "github.com/go-kit/kit/examples/shipping/cargo" -) - -// ErrInvalidArgument is returned when one or more arguments are invalid. -var ErrInvalidArgument = errors.New("invalid argument") - -// Service is the interface that provides the basic Track method. -type Service interface { - // Track returns a cargo matching a tracking ID. - Track(id string) (Cargo, error) -} - -type service struct { - cargos cargo.Repository - handlingEvents cargo.HandlingEventRepository -} - -func (s *service) Track(id string) (Cargo, error) { - if id == "" { - return Cargo{}, ErrInvalidArgument - } - c, err := s.cargos.Find(cargo.TrackingID(id)) - if err != nil { - return Cargo{}, err - } - return assemble(c, s.handlingEvents), nil -} - -// NewService returns a new instance of the default Service. -func NewService(cargos cargo.Repository, events cargo.HandlingEventRepository) Service { - return &service{ - cargos: cargos, - handlingEvents: events, - } -} - -// Cargo is a read model for tracking views. -type Cargo struct { - TrackingID string `json:"tracking_id"` - StatusText string `json:"status_text"` - Origin string `json:"origin"` - Destination string `json:"destination"` - ETA time.Time `json:"eta"` - NextExpectedActivity string `json:"next_expected_activity"` - ArrivalDeadline time.Time `json:"arrival_deadline"` - Events []Event `json:"events"` -} - -// Leg is a read model for booking views. -type Leg struct { - VoyageNumber string `json:"voyage_number"` - From string `json:"from"` - To string `json:"to"` - LoadTime time.Time `json:"load_time"` - UnloadTime time.Time `json:"unload_time"` -} - -// Event is a read model for tracking views. -type Event struct { - Description string `json:"description"` - Expected bool `json:"expected"` -} - -func assemble(c *cargo.Cargo, events cargo.HandlingEventRepository) Cargo { - return Cargo{ - TrackingID: string(c.TrackingID), - Origin: string(c.Origin), - Destination: string(c.RouteSpecification.Destination), - ETA: c.Delivery.ETA, - NextExpectedActivity: nextExpectedActivity(c), - ArrivalDeadline: c.RouteSpecification.ArrivalDeadline, - StatusText: assembleStatusText(c), - Events: assembleEvents(c, events), - } -} - -func assembleLegs(c cargo.Cargo) []Leg { - var legs []Leg - for _, l := range c.Itinerary.Legs { - legs = append(legs, Leg{ - VoyageNumber: string(l.VoyageNumber), - From: string(l.LoadLocation), - To: string(l.UnloadLocation), - LoadTime: l.LoadTime, - UnloadTime: l.UnloadTime, - }) - } - return legs -} - -func nextExpectedActivity(c *cargo.Cargo) string { - a := c.Delivery.NextExpectedActivity - prefix := "Next expected activity is to" - - switch a.Type { - case cargo.Load: - return fmt.Sprintf("%s %s cargo onto voyage %s in %s.", prefix, strings.ToLower(a.Type.String()), a.VoyageNumber, a.Location) - case cargo.Unload: - return fmt.Sprintf("%s %s cargo off of voyage %s in %s.", prefix, strings.ToLower(a.Type.String()), a.VoyageNumber, a.Location) - case cargo.NotHandled: - return "There are currently no expected activities for this cargo." - } - - return fmt.Sprintf("%s %s cargo in %s.", prefix, strings.ToLower(a.Type.String()), a.Location) -} - -func assembleStatusText(c *cargo.Cargo) string { - switch c.Delivery.TransportStatus { - case cargo.NotReceived: - return "Not received" - case cargo.InPort: - return fmt.Sprintf("In port %s", c.Delivery.LastKnownLocation) - case cargo.OnboardCarrier: - return fmt.Sprintf("Onboard voyage %s", c.Delivery.CurrentVoyage) - case cargo.Claimed: - return "Claimed" - default: - return "Unknown" - } -} - -func assembleEvents(c *cargo.Cargo, handlingEvents cargo.HandlingEventRepository) []Event { - h := handlingEvents.QueryHandlingHistory(c.TrackingID) - - var events []Event - for _, e := range h.HandlingEvents { - var description string - - switch e.Activity.Type { - case cargo.NotHandled: - description = "Cargo has not yet been received." - case cargo.Receive: - description = fmt.Sprintf("Received in %s, at %s", e.Activity.Location, time.Now().Format(time.RFC3339)) - case cargo.Load: - description = fmt.Sprintf("Loaded onto voyage %s in %s, at %s.", e.Activity.VoyageNumber, e.Activity.Location, time.Now().Format(time.RFC3339)) - case cargo.Unload: - description = fmt.Sprintf("Unloaded off voyage %s in %s, at %s.", e.Activity.VoyageNumber, e.Activity.Location, time.Now().Format(time.RFC3339)) - case cargo.Claim: - description = fmt.Sprintf("Claimed in %s, at %s.", e.Activity.Location, time.Now().Format(time.RFC3339)) - case cargo.Customs: - description = fmt.Sprintf("Cleared customs in %s, at %s.", e.Activity.Location, time.Now().Format(time.RFC3339)) - default: - description = "[Unknown status]" - } - - events = append(events, Event{ - Description: description, - Expected: c.Itinerary.IsExpected(e), - }) - } - - return events -} diff --git a/examples/shipping/tracking/transport.go b/examples/shipping/tracking/transport.go deleted file mode 100644 index 2ea319cf4..000000000 --- a/examples/shipping/tracking/transport.go +++ /dev/null @@ -1,75 +0,0 @@ -package tracking - -import ( - "context" - "encoding/json" - "errors" - "net/http" - - "github.com/gorilla/mux" - - kitlog "github.com/go-kit/kit/log" - kittransport "github.com/go-kit/kit/transport" - kithttp "github.com/go-kit/kit/transport/http" - - "github.com/go-kit/kit/examples/shipping/cargo" -) - -// MakeHandler returns a handler for the tracking service. -func MakeHandler(ts Service, logger kitlog.Logger) http.Handler { - r := mux.NewRouter() - - opts := []kithttp.ServerOption{ - kithttp.ServerErrorHandler(kittransport.NewLogErrorHandler(logger)), - kithttp.ServerErrorEncoder(encodeError), - } - - trackCargoHandler := kithttp.NewServer( - makeTrackCargoEndpoint(ts), - decodeTrackCargoRequest, - encodeResponse, - opts..., - ) - - r.Handle("/tracking/v1/cargos/{id}", trackCargoHandler).Methods("GET") - - return r -} - -func decodeTrackCargoRequest(_ context.Context, r *http.Request) (interface{}, error) { - vars := mux.Vars(r) - id, ok := vars["id"] - if !ok { - return nil, errors.New("bad route") - } - return trackCargoRequest{ID: id}, nil -} - -func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error { - if e, ok := response.(errorer); ok && e.error() != nil { - encodeError(ctx, e.error(), w) - return nil - } - w.Header().Set("Content-Type", "application/json; charset=utf-8") - return json.NewEncoder(w).Encode(response) -} - -type errorer interface { - error() error -} - -// encode errors from business-logic -func encodeError(_ context.Context, err error, w http.ResponseWriter) { - w.Header().Set("Content-Type", "application/json; charset=utf-8") - switch err { - case cargo.ErrUnknown: - w.WriteHeader(http.StatusNotFound) - case ErrInvalidArgument: - w.WriteHeader(http.StatusBadRequest) - default: - w.WriteHeader(http.StatusInternalServerError) - } - json.NewEncoder(w).Encode(map[string]interface{}{ - "error": err.Error(), - }) -} diff --git a/examples/shipping/voyage/sample_voyages.go b/examples/shipping/voyage/sample_voyages.go deleted file mode 100644 index 751f58852..000000000 --- a/examples/shipping/voyage/sample_voyages.go +++ /dev/null @@ -1,40 +0,0 @@ -package voyage - -import "github.com/go-kit/kit/examples/shipping/location" - -// A set of sample voyages. -var ( - V100 = New("V100", Schedule{ - []CarrierMovement{ - {DepartureLocation: location.CNHKG, ArrivalLocation: location.JNTKO}, - {DepartureLocation: location.JNTKO, ArrivalLocation: location.USNYC}, - }, - }) - - V300 = New("V300", Schedule{ - []CarrierMovement{ - {DepartureLocation: location.JNTKO, ArrivalLocation: location.NLRTM}, - {DepartureLocation: location.NLRTM, ArrivalLocation: location.DEHAM}, - {DepartureLocation: location.DEHAM, ArrivalLocation: location.AUMEL}, - {DepartureLocation: location.AUMEL, ArrivalLocation: location.JNTKO}, - }, - }) - - V400 = New("V400", Schedule{ - []CarrierMovement{ - {DepartureLocation: location.DEHAM, ArrivalLocation: location.SESTO}, - {DepartureLocation: location.SESTO, ArrivalLocation: location.FIHEL}, - {DepartureLocation: location.FIHEL, ArrivalLocation: location.DEHAM}, - }, - }) -) - -// These voyages are hard-coded into the current pathfinder. Make sure -// they exist. -var ( - V0100S = New("0100S", Schedule{[]CarrierMovement{}}) - V0200T = New("0200T", Schedule{[]CarrierMovement{}}) - V0300A = New("0300A", Schedule{[]CarrierMovement{}}) - V0301S = New("0301S", Schedule{[]CarrierMovement{}}) - V0400S = New("0400S", Schedule{[]CarrierMovement{}}) -) diff --git a/examples/shipping/voyage/voyage.go b/examples/shipping/voyage/voyage.go deleted file mode 100644 index 37366af42..000000000 --- a/examples/shipping/voyage/voyage.go +++ /dev/null @@ -1,44 +0,0 @@ -// Package voyage provides the Voyage aggregate. -package voyage - -import ( - "errors" - "time" - - "github.com/go-kit/kit/examples/shipping/location" -) - -// Number uniquely identifies a particular Voyage. -type Number string - -// Voyage is a uniquely identifiable series of carrier movements. -type Voyage struct { - Number Number - Schedule Schedule -} - -// New creates a voyage with a voyage number and a provided schedule. -func New(n Number, s Schedule) *Voyage { - return &Voyage{Number: n, Schedule: s} -} - -// Schedule describes a voyage schedule. -type Schedule struct { - CarrierMovements []CarrierMovement -} - -// CarrierMovement is a vessel voyage from one location to another. -type CarrierMovement struct { - DepartureLocation location.UNLocode - ArrivalLocation location.UNLocode - DepartureTime time.Time - ArrivalTime time.Time -} - -// ErrUnknown is used when a voyage could not be found. -var ErrUnknown = errors.New("unknown voyage") - -// Repository provides access a voyage store. -type Repository interface { - Find(Number) (*Voyage, error) -} diff --git a/examples/stringsvc1/main.go b/examples/stringsvc1/main.go deleted file mode 100644 index 8cbca37d2..000000000 --- a/examples/stringsvc1/main.go +++ /dev/null @@ -1,115 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "errors" - "log" - "net/http" - "strings" - - "github.com/go-kit/kit/endpoint" - httptransport "github.com/go-kit/kit/transport/http" -) - -// StringService provides operations on strings. -type StringService interface { - Uppercase(string) (string, error) - Count(string) int -} - -// stringService is a concrete implementation of StringService -type stringService struct{} - -func (stringService) Uppercase(s string) (string, error) { - if s == "" { - return "", ErrEmpty - } - return strings.ToUpper(s), nil -} - -func (stringService) Count(s string) int { - return len(s) -} - -// ErrEmpty is returned when an input string is empty. -var ErrEmpty = errors.New("empty string") - -// For each method, we define request and response structs -type uppercaseRequest struct { - S string `json:"s"` -} - -type uppercaseResponse struct { - V string `json:"v"` - Err string `json:"err,omitempty"` // errors don't define JSON marshaling -} - -type countRequest struct { - S string `json:"s"` -} - -type countResponse struct { - V int `json:"v"` -} - -// Endpoints are a primary abstraction in go-kit. An endpoint represents a single RPC (method in our service interface) -func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint { - return func(_ context.Context, request interface{}) (interface{}, error) { - req := request.(uppercaseRequest) - v, err := svc.Uppercase(req.S) - if err != nil { - return uppercaseResponse{v, err.Error()}, nil - } - return uppercaseResponse{v, ""}, nil - } -} - -func makeCountEndpoint(svc StringService) endpoint.Endpoint { - return func(_ context.Context, request interface{}) (interface{}, error) { - req := request.(countRequest) - v := svc.Count(req.S) - return countResponse{v}, nil - } -} - -// Transports expose the service to the network. In this first example we utilize JSON over HTTP. -func main() { - svc := stringService{} - - uppercaseHandler := httptransport.NewServer( - makeUppercaseEndpoint(svc), - decodeUppercaseRequest, - encodeResponse, - ) - - countHandler := httptransport.NewServer( - makeCountEndpoint(svc), - decodeCountRequest, - encodeResponse, - ) - - http.Handle("/uppercase", uppercaseHandler) - http.Handle("/count", countHandler) - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request uppercaseRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request countRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - return json.NewEncoder(w).Encode(response) -} diff --git a/examples/stringsvc2/instrumenting.go b/examples/stringsvc2/instrumenting.go deleted file mode 100644 index 675617d9c..000000000 --- a/examples/stringsvc2/instrumenting.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/go-kit/kit/metrics" -) - -type instrumentingMiddleware struct { - requestCount metrics.Counter - requestLatency metrics.Histogram - countResult metrics.Histogram - next StringService -} - -func (mw instrumentingMiddleware) Uppercase(s string) (output string, err error) { - defer func(begin time.Time) { - lvs := []string{"method", "uppercase", "error", fmt.Sprint(err != nil)} - mw.requestCount.With(lvs...).Add(1) - mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds()) - }(time.Now()) - - output, err = mw.next.Uppercase(s) - return -} - -func (mw instrumentingMiddleware) Count(s string) (n int) { - defer func(begin time.Time) { - lvs := []string{"method", "count", "error", "false"} - mw.requestCount.With(lvs...).Add(1) - mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds()) - mw.countResult.Observe(float64(n)) - }(time.Now()) - - n = mw.next.Count(s) - return -} diff --git a/examples/stringsvc2/logging.go b/examples/stringsvc2/logging.go deleted file mode 100644 index b958f3b6f..000000000 --- a/examples/stringsvc2/logging.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "time" - - "github.com/go-kit/kit/log" -) - -type loggingMiddleware struct { - logger log.Logger - next StringService -} - -func (mw loggingMiddleware) Uppercase(s string) (output string, err error) { - defer func(begin time.Time) { - _ = mw.logger.Log( - "method", "uppercase", - "input", s, - "output", output, - "err", err, - "took", time.Since(begin), - ) - }(time.Now()) - - output, err = mw.next.Uppercase(s) - return -} - -func (mw loggingMiddleware) Count(s string) (n int) { - defer func(begin time.Time) { - _ = mw.logger.Log( - "method", "count", - "input", s, - "n", n, - "took", time.Since(begin), - ) - }(time.Now()) - - n = mw.next.Count(s) - return -} diff --git a/examples/stringsvc2/main.go b/examples/stringsvc2/main.go deleted file mode 100644 index 60544f276..000000000 --- a/examples/stringsvc2/main.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "net/http" - "os" - - stdprometheus "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - - "github.com/go-kit/kit/log" - kitprometheus "github.com/go-kit/kit/metrics/prometheus" - httptransport "github.com/go-kit/kit/transport/http" -) - -func main() { - logger := log.NewLogfmtLogger(os.Stderr) - - fieldKeys := []string{"method", "error"} - requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "my_group", - Subsystem: "string_service", - Name: "request_count", - Help: "Number of requests received.", - }, fieldKeys) - requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "my_group", - Subsystem: "string_service", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, fieldKeys) - countResult := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "my_group", - Subsystem: "string_service", - Name: "count_result", - Help: "The result of each count method.", - }, []string{}) // no fields here - - var svc StringService - svc = stringService{} - svc = loggingMiddleware{logger, svc} - svc = instrumentingMiddleware{requestCount, requestLatency, countResult, svc} - - uppercaseHandler := httptransport.NewServer( - makeUppercaseEndpoint(svc), - decodeUppercaseRequest, - encodeResponse, - ) - - countHandler := httptransport.NewServer( - makeCountEndpoint(svc), - decodeCountRequest, - encodeResponse, - ) - - http.Handle("/uppercase", uppercaseHandler) - http.Handle("/count", countHandler) - http.Handle("/metrics", promhttp.Handler()) - logger.Log("msg", "HTTP", "addr", ":8080") - logger.Log("err", http.ListenAndServe(":8080", nil)) -} diff --git a/examples/stringsvc2/service.go b/examples/stringsvc2/service.go deleted file mode 100644 index 1da2f3ebb..000000000 --- a/examples/stringsvc2/service.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import ( - "errors" - "strings" -) - -// StringService provides operations on strings. -type StringService interface { - Uppercase(string) (string, error) - Count(string) int -} - -type stringService struct{} - -func (stringService) Uppercase(s string) (string, error) { - if s == "" { - return "", ErrEmpty - } - return strings.ToUpper(s), nil -} - -func (stringService) Count(s string) int { - return len(s) -} - -// ErrEmpty is returned when an input string is empty. -var ErrEmpty = errors.New("empty string") diff --git a/examples/stringsvc2/transport.go b/examples/stringsvc2/transport.go deleted file mode 100644 index 3e892a9c9..000000000 --- a/examples/stringsvc2/transport.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "net/http" - - "github.com/go-kit/kit/endpoint" -) - -func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint { - return func(_ context.Context, request interface{}) (interface{}, error) { - req := request.(uppercaseRequest) - v, err := svc.Uppercase(req.S) - if err != nil { - return uppercaseResponse{v, err.Error()}, nil - } - return uppercaseResponse{v, ""}, nil - } -} - -func makeCountEndpoint(svc StringService) endpoint.Endpoint { - return func(_ context.Context, request interface{}) (interface{}, error) { - req := request.(countRequest) - v := svc.Count(req.S) - return countResponse{v}, nil - } -} - -func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request uppercaseRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request countRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - return json.NewEncoder(w).Encode(response) -} - -type uppercaseRequest struct { - S string `json:"s"` -} - -type uppercaseResponse struct { - V string `json:"v"` - Err string `json:"err,omitempty"` -} - -type countRequest struct { - S string `json:"s"` -} - -type countResponse struct { - V int `json:"v"` -} diff --git a/examples/stringsvc3/instrumenting.go b/examples/stringsvc3/instrumenting.go deleted file mode 100644 index b21c016cf..000000000 --- a/examples/stringsvc3/instrumenting.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "github.com/go-kit/kit/metrics" -) - -func instrumentingMiddleware( - requestCount metrics.Counter, - requestLatency metrics.Histogram, - countResult metrics.Histogram, -) ServiceMiddleware { - return func(next StringService) StringService { - return instrmw{requestCount, requestLatency, countResult, next} - } -} - -type instrmw struct { - requestCount metrics.Counter - requestLatency metrics.Histogram - countResult metrics.Histogram - StringService -} - -func (mw instrmw) Uppercase(s string) (output string, err error) { - defer func(begin time.Time) { - lvs := []string{"method", "uppercase", "error", fmt.Sprint(err != nil)} - mw.requestCount.With(lvs...).Add(1) - mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds()) - }(time.Now()) - - output, err = mw.StringService.Uppercase(s) - return -} - -func (mw instrmw) Count(s string) (n int) { - defer func(begin time.Time) { - lvs := []string{"method", "count", "error", "false"} - mw.requestCount.With(lvs...).Add(1) - mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds()) - mw.countResult.Observe(float64(n)) - }(time.Now()) - - n = mw.StringService.Count(s) - return -} diff --git a/examples/stringsvc3/logging.go b/examples/stringsvc3/logging.go deleted file mode 100644 index 72a2709de..000000000 --- a/examples/stringsvc3/logging.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "time" - - "github.com/go-kit/kit/log" -) - -func loggingMiddleware(logger log.Logger) ServiceMiddleware { - return func(next StringService) StringService { - return logmw{logger, next} - } -} - -type logmw struct { - logger log.Logger - StringService -} - -func (mw logmw) Uppercase(s string) (output string, err error) { - defer func(begin time.Time) { - _ = mw.logger.Log( - "method", "uppercase", - "input", s, - "output", output, - "err", err, - "took", time.Since(begin), - ) - }(time.Now()) - - output, err = mw.StringService.Uppercase(s) - return -} - -func (mw logmw) Count(s string) (n int) { - defer func(begin time.Time) { - _ = mw.logger.Log( - "method", "count", - "input", s, - "n", n, - "took", time.Since(begin), - ) - }(time.Now()) - - n = mw.StringService.Count(s) - return -} diff --git a/examples/stringsvc3/main.go b/examples/stringsvc3/main.go deleted file mode 100644 index 5cdb43b1a..000000000 --- a/examples/stringsvc3/main.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "context" - "flag" - "net/http" - "os" - - stdprometheus "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - - "github.com/go-kit/kit/log" - kitprometheus "github.com/go-kit/kit/metrics/prometheus" - httptransport "github.com/go-kit/kit/transport/http" -) - -func main() { - var ( - listen = flag.String("listen", ":8080", "HTTP listen address") - proxy = flag.String("proxy", "", "Optional comma-separated list of URLs to proxy uppercase requests") - ) - flag.Parse() - - var logger log.Logger - logger = log.NewLogfmtLogger(os.Stderr) - logger = log.With(logger, "listen", *listen, "caller", log.DefaultCaller) - - fieldKeys := []string{"method", "error"} - requestCount := kitprometheus.NewCounterFrom(stdprometheus.CounterOpts{ - Namespace: "my_group", - Subsystem: "string_service", - Name: "request_count", - Help: "Number of requests received.", - }, fieldKeys) - requestLatency := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "my_group", - Subsystem: "string_service", - Name: "request_latency_microseconds", - Help: "Total duration of requests in microseconds.", - }, fieldKeys) - countResult := kitprometheus.NewSummaryFrom(stdprometheus.SummaryOpts{ - Namespace: "my_group", - Subsystem: "string_service", - Name: "count_result", - Help: "The result of each count method.", - }, []string{}) - - var svc StringService - svc = stringService{} - svc = proxyingMiddleware(context.Background(), *proxy, logger)(svc) - svc = loggingMiddleware(logger)(svc) - svc = instrumentingMiddleware(requestCount, requestLatency, countResult)(svc) - - uppercaseHandler := httptransport.NewServer( - makeUppercaseEndpoint(svc), - decodeUppercaseRequest, - encodeResponse, - ) - countHandler := httptransport.NewServer( - makeCountEndpoint(svc), - decodeCountRequest, - encodeResponse, - ) - - http.Handle("/uppercase", uppercaseHandler) - http.Handle("/count", countHandler) - http.Handle("/metrics", promhttp.Handler()) - logger.Log("msg", "HTTP", "addr", *listen) - logger.Log("err", http.ListenAndServe(*listen, nil)) -} diff --git a/examples/stringsvc3/proxying.go b/examples/stringsvc3/proxying.go deleted file mode 100644 index 0f6780776..000000000 --- a/examples/stringsvc3/proxying.go +++ /dev/null @@ -1,117 +0,0 @@ -package main - -import ( - "context" - "errors" - "fmt" - "net/url" - "strings" - "time" - - "golang.org/x/time/rate" - - "github.com/sony/gobreaker" - - "github.com/go-kit/kit/circuitbreaker" - "github.com/go-kit/kit/endpoint" - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/ratelimit" - "github.com/go-kit/kit/sd" - "github.com/go-kit/kit/sd/lb" - httptransport "github.com/go-kit/kit/transport/http" -) - -func proxyingMiddleware(ctx context.Context, instances string, logger log.Logger) ServiceMiddleware { - // If instances is empty, don't proxy. - if instances == "" { - logger.Log("proxy_to", "none") - return func(next StringService) StringService { return next } - } - - // Set some parameters for our client. - var ( - qps = 100 // beyond which we will return an error - maxAttempts = 3 // per request, before giving up - maxTime = 250 * time.Millisecond // wallclock time, before giving up - ) - - // Otherwise, construct an endpoint for each instance in the list, and add - // it to a fixed set of endpoints. In a real service, rather than doing this - // by hand, you'd probably use package sd's support for your service - // discovery system. - var ( - instanceList = split(instances) - endpointer sd.FixedEndpointer - ) - logger.Log("proxy_to", fmt.Sprint(instanceList)) - for _, instance := range instanceList { - var e endpoint.Endpoint - e = makeUppercaseProxy(ctx, instance) - e = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(e) - e = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), qps))(e) - endpointer = append(endpointer, e) - } - - // Now, build a single, retrying, load-balancing endpoint out of all of - // those individual endpoints. - balancer := lb.NewRoundRobin(endpointer) - retry := lb.Retry(maxAttempts, maxTime, balancer) - - // And finally, return the ServiceMiddleware, implemented by proxymw. - return func(next StringService) StringService { - return proxymw{ctx, next, retry} - } -} - -// proxymw implements StringService, forwarding Uppercase requests to the -// provided endpoint, and serving all other (i.e. Count) requests via the -// next StringService. -type proxymw struct { - ctx context.Context - next StringService // Serve most requests via this service... - uppercase endpoint.Endpoint // ...except Uppercase, which gets served by this endpoint -} - -func (mw proxymw) Count(s string) int { - return mw.next.Count(s) -} - -func (mw proxymw) Uppercase(s string) (string, error) { - response, err := mw.uppercase(mw.ctx, uppercaseRequest{S: s}) - if err != nil { - return "", err - } - - resp := response.(uppercaseResponse) - if resp.Err != "" { - return resp.V, errors.New(resp.Err) - } - return resp.V, nil -} - -func makeUppercaseProxy(ctx context.Context, instance string) endpoint.Endpoint { - if !strings.HasPrefix(instance, "http") { - instance = "http://" + instance - } - u, err := url.Parse(instance) - if err != nil { - panic(err) - } - if u.Path == "" { - u.Path = "/uppercase" - } - return httptransport.NewClient( - "GET", - u, - encodeRequest, - decodeUppercaseResponse, - ).Endpoint() -} - -func split(s string) []string { - a := strings.Split(s, ",") - for i := range a { - a[i] = strings.TrimSpace(a[i]) - } - return a -} diff --git a/examples/stringsvc3/service.go b/examples/stringsvc3/service.go deleted file mode 100644 index 7e1773a92..000000000 --- a/examples/stringsvc3/service.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "errors" - "strings" -) - -// StringService provides operations on strings. -type StringService interface { - Uppercase(string) (string, error) - Count(string) int -} - -type stringService struct{} - -func (stringService) Uppercase(s string) (string, error) { - if s == "" { - return "", ErrEmpty - } - return strings.ToUpper(s), nil -} - -func (stringService) Count(s string) int { - return len(s) -} - -// ErrEmpty is returned when an input string is empty. -var ErrEmpty = errors.New("empty string") - -// ServiceMiddleware is a chainable behavior modifier for StringService. -type ServiceMiddleware func(StringService) StringService diff --git a/examples/stringsvc3/transport.go b/examples/stringsvc3/transport.go deleted file mode 100644 index c17a055c7..000000000 --- a/examples/stringsvc3/transport.go +++ /dev/null @@ -1,84 +0,0 @@ -package main - -import ( - "bytes" - "context" - "encoding/json" - "io/ioutil" - "net/http" - - "github.com/go-kit/kit/endpoint" -) - -func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(uppercaseRequest) - v, err := svc.Uppercase(req.S) - if err != nil { - return uppercaseResponse{v, err.Error()}, nil - } - return uppercaseResponse{v, ""}, nil - } -} - -func makeCountEndpoint(svc StringService) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(countRequest) - v := svc.Count(req.S) - return countResponse{v}, nil - } -} - -func decodeUppercaseRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request uppercaseRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func decodeCountRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request countRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func decodeUppercaseResponse(_ context.Context, r *http.Response) (interface{}, error) { - var response uppercaseResponse - if err := json.NewDecoder(r.Body).Decode(&response); err != nil { - return nil, err - } - return response, nil -} - -func encodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error { - return json.NewEncoder(w).Encode(response) -} - -func encodeRequest(_ context.Context, r *http.Request, request interface{}) error { - var buf bytes.Buffer - if err := json.NewEncoder(&buf).Encode(request); err != nil { - return err - } - r.Body = ioutil.NopCloser(&buf) - return nil -} - -type uppercaseRequest struct { - S string `json:"s"` -} - -type uppercaseResponse struct { - V string `json:"v"` - Err string `json:"err,omitempty"` -} - -type countRequest struct { - S string `json:"s"` -} - -type countResponse struct { - V int `json:"v"` -} diff --git a/examples/stringsvc4/main.go b/examples/stringsvc4/main.go deleted file mode 100644 index fcc5a8a7a..000000000 --- a/examples/stringsvc4/main.go +++ /dev/null @@ -1,206 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "errors" - "log" - "strings" - "flag" - "net/http" - - "github.com/go-kit/kit/endpoint" - natstransport "github.com/go-kit/kit/transport/nats" - httptransport "github.com/go-kit/kit/transport/http" - - "github.com/nats-io/nats.go" -) - -// StringService provides operations on strings. -type StringService interface { - Uppercase(context.Context, string) (string, error) - Count(context.Context, string) int -} - -// stringService is a concrete implementation of StringService -type stringService struct{} - -func (stringService) Uppercase(_ context.Context, s string) (string, error) { - if s == "" { - return "", ErrEmpty - } - return strings.ToUpper(s), nil -} - -func (stringService) Count(_ context.Context, s string) int { - return len(s) -} - -// ErrEmpty is returned when an input string is empty. -var ErrEmpty = errors.New("empty string") - -// For each method, we define request and response structs -type uppercaseRequest struct { - S string `json:"s"` -} - -type uppercaseResponse struct { - V string `json:"v"` - Err string `json:"err,omitempty"` // errors don't define JSON marshaling -} - -type countRequest struct { - S string `json:"s"` -} - -type countResponse struct { - V int `json:"v"` -} - -// Endpoints are a primary abstraction in go-kit. An endpoint represents a single RPC (method in our service interface) -func makeUppercaseHTTPEndpoint(nc *nats.Conn) endpoint.Endpoint { - return natstransport.NewPublisher( - nc, - "stringsvc.uppercase", - natstransport.EncodeJSONRequest, - decodeUppercaseResponse, - ).Endpoint() -} - -func makeCountHTTPEndpoint(nc *nats.Conn) endpoint.Endpoint { - return natstransport.NewPublisher( - nc, - "stringsvc.count", - natstransport.EncodeJSONRequest, - decodeCountResponse, - ).Endpoint() -} - -func makeUppercaseEndpoint(svc StringService) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(uppercaseRequest) - v, err := svc.Uppercase(ctx, req.S) - if err != nil { - return uppercaseResponse{v, err.Error()}, nil - } - return uppercaseResponse{v, ""}, nil - } -} - -func makeCountEndpoint(svc StringService) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(countRequest) - v := svc.Count(ctx, req.S) - return countResponse{v}, nil - } -} - -// Transports expose the service to the network. In this fourth example we utilize JSON over NATS and HTTP. -func main() { - svc := stringService{} - - natsURL := flag.String("nats-url", nats.DefaultURL, "URL for connection to NATS") - flag.Parse() - - nc, err := nats.Connect(*natsURL) - if err != nil { - log.Fatal(err) - } - defer nc.Close() - - uppercaseHTTPHandler := httptransport.NewServer( - makeUppercaseHTTPEndpoint(nc), - decodeUppercaseHTTPRequest, - httptransport.EncodeJSONResponse, - ) - - countHTTPHandler := httptransport.NewServer( - makeCountHTTPEndpoint(nc), - decodeCountHTTPRequest, - httptransport.EncodeJSONResponse, - ) - - uppercaseHandler := natstransport.NewSubscriber( - makeUppercaseEndpoint(svc), - decodeUppercaseRequest, - natstransport.EncodeJSONResponse, - ) - - countHandler := natstransport.NewSubscriber( - makeCountEndpoint(svc), - decodeCountRequest, - natstransport.EncodeJSONResponse, - ) - - uSub, err := nc.QueueSubscribe("stringsvc.uppercase", "stringsvc", uppercaseHandler.ServeMsg(nc)) - if err != nil { - log.Fatal(err) - } - defer uSub.Unsubscribe() - - cSub, err := nc.QueueSubscribe("stringsvc.count", "stringsvc", countHandler.ServeMsg(nc)) - if err != nil { - log.Fatal(err) - } - defer cSub.Unsubscribe() - - http.Handle("/uppercase", uppercaseHTTPHandler) - http.Handle("/count", countHTTPHandler) - log.Fatal(http.ListenAndServe(":8080", nil)) - -} - -func decodeUppercaseHTTPRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request uppercaseRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func decodeCountHTTPRequest(_ context.Context, r *http.Request) (interface{}, error) { - var request countRequest - if err := json.NewDecoder(r.Body).Decode(&request); err != nil { - return nil, err - } - return request, nil -} - -func decodeUppercaseResponse(_ context.Context, msg *nats.Msg) (interface{}, error) { - var response uppercaseResponse - - if err := json.Unmarshal(msg.Data, &response); err != nil { - return nil, err - } - - return response, nil -} - -func decodeCountResponse(_ context.Context, msg *nats.Msg) (interface{}, error) { - var response countResponse - - if err := json.Unmarshal(msg.Data, &response); err != nil { - return nil, err - } - - return response, nil -} - -func decodeUppercaseRequest(_ context.Context, msg *nats.Msg) (interface{}, error) { - var request uppercaseRequest - - if err := json.Unmarshal(msg.Data, &request); err != nil { - return nil, err - } - return request, nil -} - -func decodeCountRequest(_ context.Context, msg *nats.Msg) (interface{}, error) { - var request countRequest - - if err := json.Unmarshal(msg.Data, &request); err != nil { - return nil, err - } - return request, nil -} - diff --git a/go.mod b/go.mod index 50ac0c4c3..628c2b4dc 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.13 require ( github.com/VividCortex/gohistogram v1.0.0 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 - github.com/apache/thrift v0.14.1 github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a github.com/aws/aws-lambda-go v1.13.3 github.com/aws/aws-sdk-go v1.27.0 @@ -23,24 +22,15 @@ require ( github.com/go-stack/stack v1.8.0 github.com/golang/protobuf v1.5.2 github.com/google/btree v1.0.0 // indirect - github.com/gorilla/mux v1.7.3 github.com/hashicorp/consul/api v1.3.0 - github.com/hashicorp/go-version v1.2.0 // indirect github.com/hashicorp/golang-lru v0.5.1 // indirect github.com/hudl/fargo v1.3.0 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d - github.com/lightstep/lightstep-tracer-go v0.22.0 github.com/nats-io/nats-server/v2 v2.2.6 github.com/nats-io/nats.go v1.11.0 - github.com/oklog/oklog v0.3.2 - github.com/oklog/run v1.0.0 // indirect github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 // indirect - github.com/opentracing/basictracer-go v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.0 - github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 github.com/openzipkin/zipkin-go v0.2.2 - github.com/pact-foundation/pact-go v1.0.4 - github.com/pborman/uuid v1.2.0 github.com/performancecopilot/speed v3.0.0+incompatible github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.11.0 @@ -61,5 +51,4 @@ require ( google.golang.org/grpc v1.38.0 gopkg.in/gcfg.v1 v1.2.3 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 ) diff --git a/go.sum b/go.sum index e6da7e4e4..b8f5b4c95 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,6 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= @@ -17,8 +15,6 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.14.1 h1:Yh8v0hpCj63p5edXOLaqTJW0IJ1p+eMW6+YSOqw1d6s= -github.com/apache/thrift v0.14.1/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -87,8 +83,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -96,7 +90,6 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -131,15 +124,13 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.3.0 h1:HXNYlRkkM/t+Y/Yhxtwcy02dlYwIaoxzvxPnS+cqy78= @@ -164,13 +155,10 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= @@ -194,7 +182,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.12 h1:famVnQVu7QwryBN4jNseQdUKES71ZAOnB6UQQJPZvqk= @@ -208,10 +195,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20200305213919-a88bf8de3718 h1:lrdADj7ifyBpqGJ+cT4vE5ztUoAF87uUf76+epwPViY= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20200305213919-a88bf8de3718/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.22.0 h1:Yy1G8UDT1Ayx010fji4IaTIsmijil5xijvwJ1OoypDk= -github.com/lightstep/lightstep-tracer-go v0.22.0/go.mod h1:RnONwHKg89zYPmF+Uig5PpHMUcYCFgml8+r4SS53y7A= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -252,10 +235,6 @@ github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/oklog/oklog v0.3.2 h1:wVfs8F+in6nTBMkA7CbRw+zZMIB7nNM825cM1wuzoTk= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -263,25 +242,12 @@ github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 h1:lM6RxxfUMrYL/f8bWEUqdXrANWtrL7Nndbm9iFN0DlU= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0 h1:YyUAhaEfjoWXclZVJ9sGoNct7j4TVk7lZWlQw5UXuoo= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5 h1:ZCnq+JUrvXcDVhX/xRolRBZifmabN1HcS1wrPSvxhrU= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2 h1:nY8Hti+WKaP0cRsSeQ026wU03QsM762XBeCXBb9NAWI= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4 h1:OYkFijGHoZAYbOIb1LWXrwKQbMMRUv1oQ89blD2Mh2Q= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkLM+sc0JPuwhXzK8OYOyt3Vg= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= @@ -320,8 +286,6 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCL github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil v2.20.1+incompatible h1:oIq9Cq4i84Hk8uQAUOG3eNdI/29hBawGrD5YRl6JRDY= -github.com/shirou/gopsutil v2.20.1+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -394,7 +358,6 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -448,7 +411,6 @@ golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -471,7 +433,6 @@ google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 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= @@ -480,8 +441,6 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -526,5 +485,3 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0 h1:ucqkfpjg9WzSUubAO62csmucvxl4/JeW3F4I4909XkM= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=