From d7372872bf6718ce1b12516ad12487f7a18cb81e Mon Sep 17 00:00:00 2001 From: thangchung Date: Fri, 28 Oct 2022 11:20:14 +0000 Subject: [PATCH] publish event and grpc-client #3 --- client.http | 2 +- cmd/barista/event/consumer.go | 7 +-- go.mod | 5 +- go.sum | 18 +++--- internal/counter/app/app.go | 26 +++++--- internal/counter/entity/order.go | 72 ++++++++++++++++++++++- internal/product/app/app.go | 32 +++++----- {internal/counter => pkg}/event/events.go | 0 8 files changed, 121 insertions(+), 41 deletions(-) rename {internal/counter => pkg}/event/events.go (100%) diff --git a/client.http b/client.http index f8a592a..3871c17 100644 --- a/client.http +++ b/client.http @@ -5,7 +5,7 @@ GET {{host}}/v1/api/item-types HTTP/1.1 content-type: application/json ### -GET {{host}}/v1/api/items-by-types/1,2,3 HTTP/1.1 +GET {{host}}/v1/api/items-by-types/COFFEE_WITH_ROOM,MUFFIN HTTP/1.1 content-type: application/json ### diff --git a/cmd/barista/event/consumer.go b/cmd/barista/event/consumer.go index d7bd323..716cc77 100644 --- a/cmd/barista/event/consumer.go +++ b/cmd/barista/event/consumer.go @@ -6,6 +6,7 @@ import ( "log" amqp "github.com/rabbitmq/amqp091-go" + events "github.com/thangchung/go-coffeeshop/pkg/event" ) const ExchangeName = "orders_topic" @@ -44,10 +45,6 @@ func (c *Consumer) setup() error { ) } -type Payload struct { - Name string `json:"name"` -} - func (c *Consumer) Listen(topics []string) error { ch, err := c.conn.Channel() if err != nil { @@ -92,7 +89,7 @@ func (c *Consumer) Listen(topics []string) error { go func() { for d := range messages { - var payload Payload + var payload events.BaristaOrdered _ = json.Unmarshal(d.Body, &payload) messageType := d.Type diff --git a/go.mod b/go.mod index f593d5b..2a6e220 100755 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0 github.com/ilyakaznacheev/cleanenv v1.3.0 github.com/rabbitmq/amqp091-go v1.5.0 + github.com/samber/lo v1.33.0 github.com/sirupsen/logrus v1.9.0 google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a google.golang.org/grpc v1.50.1 @@ -18,9 +19,9 @@ require ( github.com/BurntSushi/toml v1.1.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/joho/godotenv v1.4.0 // indirect - github.com/stretchr/testify v1.8.0 // indirect + golang.org/x/exp v0.0.0-20221026153819-32f3d567a233 // indirect golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect - golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 // indirect + golang.org/x/sys v0.1.0 // indirect golang.org/x/text v0.3.8 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect diff --git a/go.sum b/go.sum index 714a86f..4ad9605 100755 --- a/go.sum +++ b/go.sum @@ -18,28 +18,30 @@ github.com/ilyakaznacheev/cleanenv v1.3.0 h1:RapuLclPPUbmdd5Bi5UXScwMEZA6+ZNLU5O github.com/ilyakaznacheev/cleanenv v1.3.0/go.mod h1:i0owW+HDxeGKE0/JPREJOdSCPIyOnmh6C0xhWAkF/xA= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rabbitmq/amqp091-go v1.5.0 h1:VouyHPBu1CrKyJVfteGknGOGCzmOz0zcv/tONLkb7rg= github.com/rabbitmq/amqp091-go v1.5.0/go.mod h1:JsV0ofX5f1nwOGafb8L5rBItt9GyhfQfcJj+oyz0dGg= +github.com/samber/lo v1.33.0 h1:2aKucr+rQV6gHpY3bpeZu69uYoQOzVhGT3J22Op6Cjk= +github.com/samber/lo v1.33.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20221026153819-32f3d567a233 h1:9bNbSKT4RPLEzne0Xh1v3NaNecsa1DKjkOuTbY6V9rI= +golang.org/x/exp v0.0.0-20221026153819-32f3d567a233/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -56,8 +58,8 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 h1:OK7RB6t2WQX54srQQYSXMW8dF5C6/8+oA/s5QBmmto4= -golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -80,8 +82,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/counter/app/app.go b/internal/counter/app/app.go index 983baf9..5a5c440 100644 --- a/internal/counter/app/app.go +++ b/internal/counter/app/app.go @@ -4,14 +4,14 @@ import ( "context" "encoding/json" "errors" - "fmt" "net" "time" "github.com/google/uuid" amqp "github.com/rabbitmq/amqp091-go" "github.com/thangchung/go-coffeeshop/cmd/counter/config" - "github.com/thangchung/go-coffeeshop/internal/counter/event" + "github.com/thangchung/go-coffeeshop/internal/counter/entity" + events "github.com/thangchung/go-coffeeshop/pkg/event" mylogger "github.com/thangchung/go-coffeeshop/pkg/logger" gen "github.com/thangchung/go-coffeeshop/proto/gen" "google.golang.org/grpc" @@ -88,18 +88,30 @@ func (g *CounterServiceServerImpl) GetListOrderFulfillment(ctx context.Context, func (g *CounterServiceServerImpl) PlaceOrder(ctx context.Context, request *gen.PlaceOrderRequest) (*gen.PlaceOrderResponse, error) { g.logger.Info("POST: PlaceOrder") - fmt.Println(request) + g.logger.Debug("request: %s", request) + // add order + order, err := entity.CreateOrderFrom(request) + if err != nil { + return nil, err + } + + g.logger.Debug("order created: %s", *order) + + // publish order events ch, err := g.rabbitConn.Channel() if err != nil { panic(err) } defer ch.Close() - eventBytes, err := json.Marshal(event.BaristaOrdered{ - OrderID: uuid.New(), - ItemLineID: uuid.UUID, - }) + event := events.BaristaOrdered{ + OrderID: order.ID, + ItemLineID: uuid.New(), //todo + ItemType: 1, //todo + } + + eventBytes, err := json.Marshal(event) if err != nil { g.logger.LogError(err) } diff --git a/internal/counter/entity/order.go b/internal/counter/entity/order.go index 7c20eb4..d212dfb 100644 --- a/internal/counter/entity/order.go +++ b/internal/counter/entity/order.go @@ -1,8 +1,16 @@ package entity import ( + "context" + "fmt" + "strings" + "time" + "github.com/google/uuid" + "github.com/samber/lo" gen "github.com/thangchung/go-coffeeshop/proto/gen" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" ) type Order struct { @@ -24,7 +32,7 @@ func NewOrder(orderSource gen.OrderSource, loyaltyMemberID uuid.UUID, orderStatu } } -func (o *Order) From(request *gen.PlaceOrderRequest) (*Order, error) { +func CreateOrderFrom(request *gen.PlaceOrderRequest) (*Order, error) { loyaltyMemberID, err := uuid.Parse(request.LoyaltyMemberId) if err != nil { return nil, err @@ -32,12 +40,70 @@ func (o *Order) From(request *gen.PlaceOrderRequest) (*Order, error) { order := NewOrder(request.OrderSource, loyaltyMemberID, gen.Status_IN_PROGRESS, request.Location) - if len(request.BaristaItems) > 0 { + //TODO: remove hard code URL + conn, err := grpc.Dial("0.0.0.0:5001", grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, err + } + defer conn.Close() + c := gen.NewProductServiceClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + + numberOfBaristaItems := len(request.BaristaItems) > 0 + numberOfKitchenItems := len(request.KitchenItems) > 0 + + if numberOfBaristaItems { + itemTypes := lo.Reduce(request.BaristaItems, func(agg string, item *gen.CommandItem, _ int) string { + return fmt.Sprintf("%s,%s", agg, item.ItemType) + }, "") + + itemTypesRes, err := c.GetItemsByType(ctx, &gen.GetItemsByTypeRequest{ItemTypes: strings.TrimLeft(itemTypes, ",")}) + if err != nil { + return nil, err + } + lo.ForEach(request.BaristaItems, func(item *gen.CommandItem, index int) { + find, ok := lo.Find(itemTypesRes.Items, func(i *gen.ItemDto) bool { + return i.Type == int32(item.ItemType) + }) + + if ok { + lineItem := NewLineItem(item.ItemType, item.ItemType.String(), float32(find.Price), gen.Status_IN_PROGRESS, true) + + //TODO: add domain events + // ... + + order.LineItems = append(order.LineItems, *lineItem) + } + }) } - if len(request.KitchenItems) > 0 { + if numberOfKitchenItems { + itemTypes := lo.Reduce(request.KitchenItems, func(agg string, item *gen.CommandItem, _ int) string { + return fmt.Sprintf("%s,%s", agg, item.ItemType) + }, "") + + itemTypesRes, err := c.GetItemsByType(ctx, &gen.GetItemsByTypeRequest{ItemTypes: strings.TrimLeft(itemTypes, ",")}) + if err != nil { + return nil, err + } + + lo.ForEach(request.KitchenItems, func(item *gen.CommandItem, index int) { + find, ok := lo.Find(itemTypesRes.Items, func(i *gen.ItemDto) bool { + return i.Type == int32(item.ItemType) + }) + + if ok { + lineItem := NewLineItem(item.ItemType, item.ItemType.String(), float32(find.Price), gen.Status_IN_PROGRESS, false) + + //TODO: add domain events + // ... + order.LineItems = append(order.LineItems, *lineItem) + } + }) } return order, nil diff --git a/internal/product/app/app.go b/internal/product/app/app.go index 37c0c32..4d11486 100644 --- a/internal/product/app/app.go +++ b/internal/product/app/app.go @@ -3,7 +3,6 @@ package app import ( "context" "net" - "reflect" "strings" "github.com/thangchung/go-coffeeshop/cmd/product/config" @@ -25,51 +24,52 @@ type ProductServiceServerImpl struct { } var ItemTypes = map[string]gen.ItemTypeDto{ - "0": { + "CAPPUCCINO": { Name: "CAPPUCCINO", Type: 0, Price: 4.5, }, - "1": {Name: "COFFEE_BLACK", + "COFFEE_BLACK": { + Name: "COFFEE_BLACK", Type: 1, Price: 3, }, - "2": { + "COFFEE_WITH_ROOM": { Name: "COFFEE_WITH_ROOM", Type: 2, Price: 3, }, - "3": { + "ESPRESSO": { Name: "ESPRESSO", Type: 3, Price: 3.5, }, - "4": { + "ESPRESSO_DOUBLE": { Name: "ESPRESSO_DOUBLE", Type: 4, Price: 4.5, }, - "5": { + "LATTE": { Name: "LATTE", Type: 5, Price: 4.5, }, - "6": { + "CAKEPOP": { Name: "CAKEPOP", Type: 6, Price: 2.5, }, - "7": { + "CROISSANT": { Name: "CROISSANT", Type: 7, Price: 3.25, }, - "8": { + "MUFFIN": { Name: "MUFFIN", Type: 8, Price: 3, }, - "9": { + "CROISSANT_CHOCOLATE": { Name: "CROISSANT_CHOCOLATE", Type: 9, Price: 3.5, @@ -83,8 +83,9 @@ func (g *ProductServiceServerImpl) GetItemTypes(ctx context.Context, request *ge for _, v := range ItemTypes { res.ItemTypes = append(res.ItemTypes, &gen.ItemTypeDto{ - Name: v.Name, - Type: v.Type, + Name: v.Name, + Type: v.Type, + Price: v.Price, }) } @@ -92,14 +93,15 @@ func (g *ProductServiceServerImpl) GetItemTypes(ctx context.Context, request *ge } func (g *ProductServiceServerImpl) GetItemsByType(ctx context.Context, request *gen.GetItemsByTypeRequest) (*gen.GetItemsByTypeResponse, error) { - g.logger.Info("GET: GetItemsByType") + g.logger.Info("GET: GetItemsByType with %s", request.ItemTypes) res := gen.GetItemsByTypeResponse{} itemTypes := strings.Split(request.ItemTypes, ",") + for _, itemType := range itemTypes { item := ItemTypes[itemType] - if !reflect.DeepEqual(item, gen.ItemTypeDto{}) { + if item.Name != "" { res.Items = append(res.Items, &gen.ItemDto{ Price: item.Price, Type: item.Type, diff --git a/internal/counter/event/events.go b/pkg/event/events.go similarity index 100% rename from internal/counter/event/events.go rename to pkg/event/events.go