diff --git a/Makefile b/Makefile index 44886f3..c4ae5fa 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,7 @@ .PHONY: proto run down proto: - protoc --go_out=. --go_opt=paths=source_relative \ - --go-grpc_out=. --go-grpc_opt=paths=source_relative \ - salesservice/proto/sales.proto + protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative salesservice/proto/sales.proto run: docker-compose up -d diff --git a/go.mod b/go.mod index 8e4e5ff..33b0f04 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/google/uuid v1.1.4 github.com/gorilla/mux v1.8.0 github.com/lib/pq v1.8.0 + github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e github.com/opentracing/opentracing-go v1.2.0 github.com/pkg/errors v0.9.1 // indirect github.com/uber/jaeger-client-go v2.25.0+incompatible diff --git a/go.sum b/go.sum index 0cef24d..ff59dd3 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,7 @@ github.com/google/uuid v1.1.4 h1:0ecGp3skIrHWPNGPJDaBIghfA6Sp7Ruo2Io8eLKzWm0= github.com/google/uuid v1.1.4/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= @@ -51,6 +52,9 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e h1:4cPxUYdgaGzZIT5/j0IfqOrrXmq6bG8AwvwisMXpdrg= +github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e/go.mod h1:DYR5Eij8rJl8h7gblRrOZ8g0kW1umSpKqYIBTgeDtLo= +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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -61,6 +65,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -92,6 +97,7 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190921015927-1a5e07d1ff72/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -135,6 +141,7 @@ google.golang.org/genproto v0.0.0-20210106152847-07624b53cd92 h1:jOTk2Z6KYaWoptU google.golang.org/genproto v0.0.0-20210106152847-07624b53cd92/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/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= google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI= diff --git a/productservice/internal/client/client.go b/productservice/internal/client/client.go index 9b3757b..a2bd33c 100644 --- a/productservice/internal/client/client.go +++ b/productservice/internal/client/client.go @@ -7,14 +7,14 @@ import ( "log" "time" + otgrpc "github.com/opentracing-contrib/go-grpc" opentracing "github.com/opentracing/opentracing-go" pb "github.com/tacheshun/golang-rest-api/salesservice/proto" "github.com/uber/jaeger-client-go/config" ) const ( - address = "localhost:50051" - defaultName = "world" + address = ":50051" ) func InitTracer(serviceName, host string) (opentracing.Tracer, error) { @@ -38,9 +38,14 @@ func InitTracer(serviceName, host string) (opentracing.Tracer, error) { } func Send() (interface{}, error) { - + tracer, err := InitTracer("product", "127.0.0.1:16686") + if err != nil { + panic("cannot start tracer") + } // Set up a connection to the server. - conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) + conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithUnaryInterceptor( + otgrpc.OpenTracingClientInterceptor(tracer)), grpc.WithStreamInterceptor( + otgrpc.OpenTracingStreamClientInterceptor(tracer)), grpc.WithBlock()) if err != nil { log.Fatalf("did not connect: %v", err) } @@ -49,15 +54,40 @@ func Send() (interface{}, error) { // Contact the server and print out its response. var productId uint32 - productId = 1 + productId = 2 ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() r, err := c.GetProductWithHighestSales(ctx, &pb.ProductIdRequest{ProductId: productId}) if err != nil { log.Fatalf("could not fetch: %v", err) } - fmt.Println(r) - log.Printf("Product wth the highest sales is: %v, %v", r.Product, r.TotalSales) return r, nil } + +func GetSalesForProductRPC(productId uint32) (map[string]interface{}, error) { + tracer, err := InitTracer("product", "127.0.0.1:16686") + if err != nil { + panic("cannot start tracer") + } + // Set up a connection to the server. + conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithUnaryInterceptor( + otgrpc.OpenTracingClientInterceptor(tracer)), grpc.WithStreamInterceptor( + otgrpc.OpenTracingStreamClientInterceptor(tracer)), grpc.WithBlock()) + if err != nil { + log.Fatalf("did not connect: %v", err) + } + defer conn.Close() + c := pb.NewSalesClient(conn) + + // Contact the server and print out its response. + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + res, err := c.GetSalesForProduct(ctx, &pb.ProductIdRequest{ProductId: productId}) + if err != nil { + log.Fatalf("could not fetch: %v", err) + } + + return map[string]interface{}{"productId":res.ProductId, "quantity":res.Quantity}, nil +} diff --git a/productservice/internal/handlers/handlers.go b/productservice/internal/handlers/handlers.go index bd47845..d77fc4f 100644 --- a/productservice/internal/handlers/handlers.go +++ b/productservice/internal/handlers/handlers.go @@ -50,6 +50,11 @@ func (a *App) GetProduct(w http.ResponseWriter, r *http.Request) { } p := models.Product{ID: id} + if err != nil { + respondWithError(w, http.StatusBadRequest, "RPC request failed") + return + } + if err := p.GetProduct(a.DB); err != nil { switch err { case sql.ErrNoRows: @@ -59,6 +64,8 @@ func (a *App) GetProduct(w http.ResponseWriter, r *http.Request) { } return } + productTotalSales, err := client.GetSalesForProductRPC(uint32(id)) + p.Sale = float64(productTotalSales["quantity"].(uint32)) respondWithJSON(w, http.StatusOK, p) } diff --git a/productservice/internal/models/models.go b/productservice/internal/models/models.go index e42c2ee..4326824 100644 --- a/productservice/internal/models/models.go +++ b/productservice/internal/models/models.go @@ -9,6 +9,7 @@ type Product struct { ID int `json:"id"` Name string `json:"name"` Price float64 `json:"price"` + Sale float64 `json:"total_sales,omitempty"` Created time.Time `json:"-"` Modified time.Time `json:"-"` } diff --git a/salesservice/cmd/sales/main.go b/salesservice/cmd/sales/main.go index 368b027..5a447e1 100644 --- a/salesservice/cmd/sales/main.go +++ b/salesservice/cmd/sales/main.go @@ -4,12 +4,18 @@ import ( "context" "database/sql" "encoding/json" + "fmt" _ "github.com/lib/pq" + otgrpc "github.com/opentracing-contrib/go-grpc" + "github.com/opentracing/opentracing-go" + "github.com/opentracing/opentracing-go/ext" pb "github.com/tacheshun/golang-rest-api/salesservice/proto" + "github.com/uber/jaeger-client-go/config" "google.golang.org/grpc" "log" "net" "net/http" + "time" ) const ( @@ -24,9 +30,14 @@ func main() { if err != nil { log.Fatalf("failed to listen: %v", err) } - grpcServer := grpc.NewServer() + tracer, err := InitTracer("Sales", "127.0.0.1:16686") + grpcServer := grpc.NewServer(grpc.UnaryInterceptor( + otgrpc.OpenTracingServerInterceptor(tracer)), + grpc.StreamInterceptor( + otgrpc.OpenTracingStreamServerInterceptor(tracer))) pb.RegisterSalesServer(grpcServer, &server{ - repo: &app, + repo: &app, + tracer: tracer, }) if err := grpcServer.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) @@ -38,9 +49,10 @@ type SalesApp struct { } type Sale struct { - SalesID int `json:"sale_id"` - ProductID int `json:"product_id"` - Quantity int `json:"quantity"` + SalesID int `json:"sale_id"` + ProductID int `json:"product_id"` + Quantity int `json:"quantity"` + Created time.Time `json:"created"` } type ProductSales struct { @@ -58,10 +70,18 @@ func (s *SalesApp) Initialize() { type server struct { pb.UnimplementedSalesServer - repo *SalesApp + repo *SalesApp + tracer opentracing.Tracer } func (srv *server) GetProductWithHighestSales(ctx context.Context, in *pb.ProductIdRequest) (*pb.ProductWithSales, error) { + if span := opentracing.SpanFromContext(ctx); span != nil { + span := srv.tracer.StartSpan("GetProductWithHighestSales", opentracing.ChildOf(span.Context())) + span.SetTag("param.location", in.ProductId) + ext.SpanKindRPCClient.Set(span) + defer span.Finish() + ctx = opentracing.ContextWithSpan(ctx, span) + } result, err := srv.repo.GetProductPlusHighestSales(in.GetProductId()) if err != nil { return nil, err @@ -74,6 +94,19 @@ func (srv *server) GetProductWithHighestSales(ctx context.Context, in *pb.Produc return out, nil } +func (srv *server) GetSalesForProduct(ctx context.Context, in *pb.ProductIdRequest) (*pb.Sale, error) { + result, err := srv.repo.GetSalesForProductID(in.GetProductId()) + if err != nil { + return nil, err + } + + out := &pb.Sale{} + // + out.ProductId = uint32(result.ProductID) + out.Quantity = uint32(result.Quantity) + return out, nil +} + func (s *SalesApp) GetProductPlusHighestSales(_ uint32) (*ProductSales, error) { var productSales ProductSales _ = s.DB.QueryRow( @@ -82,6 +115,14 @@ func (s *SalesApp) GetProductPlusHighestSales(_ uint32) (*ProductSales, error) { return &productSales, nil } +func (s *SalesApp) GetSalesForProductID(productId uint32) (*Sale, error) { + var sale Sale + _ = s.DB.QueryRow( + "SELECT product_id, sum(quantity) as total_sales from sales WHERE product_id=$1 group by product_id", productId).Scan(&sale.ProductID, &sale.Quantity) + + return &sale, nil +} + func respondWithError(w http.ResponseWriter, code int, message string) { respondWithJSON(w, code, map[string]string{"error": message}) } @@ -93,3 +134,23 @@ func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { w.WriteHeader(code) _, _ = w.Write(response) } + +func InitTracer(serviceName, host string) (opentracing.Tracer, error) { + cfg := config.Configuration{ + Sampler: &config.SamplerConfig{ + Type: "const", + Param: 1, + }, + Reporter: &config.ReporterConfig{ + LogSpans: false, + BufferFlushInterval: 1 * time.Second, + LocalAgentHostPort: host, + }, + } + + tracer, _, err := cfg.New(serviceName) + if err != nil { + return nil, fmt.Errorf("new tracer error: %v", err) + } + return tracer, nil +} diff --git a/salesservice/proto/sales.pb.go b/salesservice/proto/sales.pb.go index fc01565..dbe1d1d 100644 --- a/salesservice/proto/sales.pb.go +++ b/salesservice/proto/sales.pb.go @@ -353,16 +353,20 @@ var file_salesservice_proto_sales_proto_rawDesc = []byte{ 0x63, 0x74, 0x49, 0x64, 0x22, 0x38, 0x0a, 0x0c, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x28, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x53, 0x41, 0x4c, 0x45, 0x53, 0x2e, 0x50, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x32, 0x59, - 0x0a, 0x05, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x74, 0x57, 0x69, 0x74, 0x68, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, 0x74, - 0x53, 0x61, 0x6c, 0x65, 0x73, 0x12, 0x17, 0x2e, 0x53, 0x41, 0x4c, 0x45, 0x53, 0x2e, 0x50, 0x72, - 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x53, 0x41, 0x4c, 0x45, 0x53, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x57, 0x69, - 0x74, 0x68, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x22, 0x00, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x61, 0x63, 0x68, 0x65, 0x73, 0x68, 0x75, - 0x6e, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x72, 0x65, 0x73, 0x74, 0x2d, 0x61, 0x70, - 0x69, 0x3b, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x32, 0x97, + 0x01, 0x0a, 0x05, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x57, 0x69, 0x74, 0x68, 0x48, 0x69, 0x67, 0x68, 0x65, 0x73, + 0x74, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x12, 0x17, 0x2e, 0x53, 0x41, 0x4c, 0x45, 0x53, 0x2e, 0x50, + 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x17, 0x2e, 0x53, 0x41, 0x4c, 0x45, 0x53, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x57, + 0x69, 0x74, 0x68, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x12, 0x47, 0x65, + 0x74, 0x53, 0x61, 0x6c, 0x65, 0x73, 0x46, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x12, 0x17, 0x2e, 0x53, 0x41, 0x4c, 0x45, 0x53, 0x2e, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, + 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x53, 0x41, 0x4c, 0x45, + 0x53, 0x2e, 0x53, 0x61, 0x6c, 0x65, 0x22, 0x00, 0x42, 0x2a, 0x5a, 0x28, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x61, 0x63, 0x68, 0x65, 0x73, 0x68, 0x75, 0x6e, + 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2d, 0x72, 0x65, 0x73, 0x74, 0x2d, 0x61, 0x70, 0x69, + 0x3b, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -391,9 +395,11 @@ var file_salesservice_proto_sales_proto_depIdxs = []int32{ 5, // 1: SALES.Sale.created:type_name -> google.protobuf.Timestamp 0, // 2: SALES.ProductReply.product:type_name -> SALES.Product 3, // 3: SALES.Sales.GetProductWithHighestSales:input_type -> SALES.ProductIdRequest - 2, // 4: SALES.Sales.GetProductWithHighestSales:output_type -> SALES.ProductWithSales - 4, // [4:5] is the sub-list for method output_type - 3, // [3:4] is the sub-list for method input_type + 3, // 4: SALES.Sales.GetSalesForProduct:input_type -> SALES.ProductIdRequest + 2, // 5: SALES.Sales.GetProductWithHighestSales:output_type -> SALES.ProductWithSales + 1, // 6: SALES.Sales.GetSalesForProduct:output_type -> SALES.Sale + 5, // [5:7] is the sub-list for method output_type + 3, // [3:5] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name 3, // [3:3] is the sub-list for extension extendee 0, // [0:3] is the sub-list for field type_name diff --git a/salesservice/proto/sales.proto b/salesservice/proto/sales.proto index 7be2dc9..0012bc5 100644 --- a/salesservice/proto/sales.proto +++ b/salesservice/proto/sales.proto @@ -35,4 +35,5 @@ message ProductReply { service Sales { rpc GetProductWithHighestSales(ProductIdRequest) returns (ProductWithSales) {} -} \ No newline at end of file + rpc GetSalesForProduct(ProductIdRequest) returns (Sale) {} +} diff --git a/salesservice/proto/sales_grpc.pb.go b/salesservice/proto/sales_grpc.pb.go index 57320f4..4cc6bf6 100644 --- a/salesservice/proto/sales_grpc.pb.go +++ b/salesservice/proto/sales_grpc.pb.go @@ -19,6 +19,7 @@ const _ = grpc.SupportPackageIsVersion7 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type SalesClient interface { GetProductWithHighestSales(ctx context.Context, in *ProductIdRequest, opts ...grpc.CallOption) (*ProductWithSales, error) + GetSalesForProduct(ctx context.Context, in *ProductIdRequest, opts ...grpc.CallOption) (*Sale, error) } type salesClient struct { @@ -38,11 +39,21 @@ func (c *salesClient) GetProductWithHighestSales(ctx context.Context, in *Produc return out, nil } +func (c *salesClient) GetSalesForProduct(ctx context.Context, in *ProductIdRequest, opts ...grpc.CallOption) (*Sale, error) { + out := new(Sale) + err := c.cc.Invoke(ctx, "/SALES.Sales/GetSalesForProduct", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // SalesServer is the server API for Sales service. // All implementations must embed UnimplementedSalesServer // for forward compatibility type SalesServer interface { GetProductWithHighestSales(context.Context, *ProductIdRequest) (*ProductWithSales, error) + GetSalesForProduct(context.Context, *ProductIdRequest) (*Sale, error) mustEmbedUnimplementedSalesServer() } @@ -53,6 +64,9 @@ type UnimplementedSalesServer struct { func (UnimplementedSalesServer) GetProductWithHighestSales(context.Context, *ProductIdRequest) (*ProductWithSales, error) { return nil, status.Errorf(codes.Unimplemented, "method GetProductWithHighestSales not implemented") } +func (UnimplementedSalesServer) GetSalesForProduct(context.Context, *ProductIdRequest) (*Sale, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSalesForProduct not implemented") +} func (UnimplementedSalesServer) mustEmbedUnimplementedSalesServer() {} // UnsafeSalesServer may be embedded to opt out of forward compatibility for this service. @@ -84,6 +98,24 @@ func _Sales_GetProductWithHighestSales_Handler(srv interface{}, ctx context.Cont return interceptor(ctx, in, info, handler) } +func _Sales_GetSalesForProduct_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ProductIdRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SalesServer).GetSalesForProduct(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/SALES.Sales/GetSalesForProduct", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SalesServer).GetSalesForProduct(ctx, req.(*ProductIdRequest)) + } + return interceptor(ctx, in, info, handler) +} + // Sales_ServiceDesc is the grpc.ServiceDesc for Sales service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -95,6 +127,10 @@ var Sales_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetProductWithHighestSales", Handler: _Sales_GetProductWithHighestSales_Handler, }, + { + MethodName: "GetSalesForProduct", + Handler: _Sales_GetSalesForProduct_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "salesservice/proto/sales.proto",