From 02ea940173715eb9e95f061bce3015f47e6f5245 Mon Sep 17 00:00:00 2001 From: Le Minh Tan Date: Fri, 30 Jul 2021 08:52:27 +0700 Subject: [PATCH] implement websocket to view the dashboard of top ten product --- go.mod | 5 +++- go.sum | 7 +++++ product/product.data.go | 28 +++++++++++++++++++ product/product.service.go | 2 ++ product/product.websocket.go | 53 ++++++++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 product/product.websocket.go diff --git a/go.mod b/go.mod index 8177617..157aebc 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/dutroctu/go-webservice go 1.16 -require github.com/go-sql-driver/mysql v1.6.0 // indirect +require ( + github.com/go-sql-driver/mysql v1.6.0 // indirect + golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect +) diff --git a/go.sum b/go.sum index 20c16d6..b6109d2 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,9 @@ github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/product/product.data.go b/product/product.data.go index 5a0a4a1..e62eda5 100644 --- a/product/product.data.go +++ b/product/product.data.go @@ -158,3 +158,31 @@ func updateProduct(product Product) error { } return nil } + +func GetTopTenProducts() ([]Product, error) { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + results, err := database.DbConn.QueryContext(ctx, `SELECT productId, + manufacturer, + sku, + upc, + pricePerUnit, + quantityOnHand, + productName + FROM products ORDER BY quantityOnHand DESC LIMIT 10`) + if err != nil { + log.Println(err.Error()) + return nil, err + } + defer results.Close() + products := make([]Product, 0) + for results.Next() { + var product Product + results.Scan(&product.ProductID, &product.Manufacturer, + &product.Sku, &product.Upc, &product.PricePerUnit, + &product.QuantityOnHand, &product.ProductName) + products = append(products, product) + } + return products, nil +} diff --git a/product/product.service.go b/product/product.service.go index 38d9715..eadd966 100644 --- a/product/product.service.go +++ b/product/product.service.go @@ -11,6 +11,7 @@ import ( "time" "github.com/dutroctu/go-webservice/cors" + "golang.org/x/net/websocket" ) const productsBasePath = "products" @@ -18,6 +19,7 @@ const productsBasePath = "products" func SetupRoutes(apiBasePath string) { handleProducts := http.HandlerFunc(productsHandler) handleProduct := http.HandlerFunc(productHandler) + http.Handle("/websocket", websocket.Handler(productSocket)) http.Handle(fmt.Sprintf("%s/%s", apiBasePath, productsBasePath), cors.Middleware(handleProducts)) http.Handle(fmt.Sprintf("%s/%s/", apiBasePath, productsBasePath), cors.Middleware(handleProduct)) } diff --git a/product/product.websocket.go b/product/product.websocket.go new file mode 100644 index 0000000..4b4b403 --- /dev/null +++ b/product/product.websocket.go @@ -0,0 +1,53 @@ +package product + +import ( + "fmt" + "log" + "time" + + "golang.org/x/net/websocket" +) + +type message struct { + Data string `json:"data"` + Type string `json:"type"` +} + +func productSocket(ws *websocket.Conn) { + done := make(chan struct{}) + fmt.Println("new websocket connection established") + go func(c *websocket.Conn) { + + for { + var msg message + if err := websocket.JSON.Receive(ws, &msg); err != nil { + log.Println(err) + break + } + fmt.Println("received message ", msg.Data) + } + close(done) + }(ws) + +loop: + for { + select { + case <-done: + fmt.Println("connection was closed, lets break out of here") + break loop + default: + products, err := GetTopTenProducts() + if err != nil { + log.Println(err) + break + } + if err := websocket.JSON.Send(ws, products); err != nil { + log.Println(err) + break + } + time.Sleep(10 * time.Second) + } + } + fmt.Println("close websocket") + defer ws.Close() +}