This commit is contained in:
parent
00a3b5d5d5
commit
dfc621e920
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.dist
|
||||||
|
|
||||||
|
.vscode/
|
||||||
|
__debug_bin
|
@ -11,8 +11,9 @@ import (
|
|||||||
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/common"
|
baseCnf "git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
||||||
cnf "git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
|
||||||
|
cnf "git.pbiernat.dev/egommerce/basket-service/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -35,25 +36,24 @@ Usage:
|
|||||||
`
|
`
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if cnf.ErrLoadingEnvs != nil {
|
if baseCnf.ErrLoadingEnvs != nil {
|
||||||
log.Panicln("Error loading .env file", cnf.ErrLoadingEnvs)
|
log.Panicln("Error loading .env file", baseCnf.ErrLoadingEnvs)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := common.NewConfig()
|
c := cnf.NewConfig()
|
||||||
|
|
||||||
// dbURL := cnf.GetEnv("DATABASE_URL", defDbURL)
|
// dbURL := baseCnf.GetEnv("DATABASE_URL", defDbURL)
|
||||||
mTblName := cnf.GetEnv("MIGRATIONS_TABLE_NAME", defMigrationsTableName)
|
|
||||||
|
|
||||||
logHost, logPort, err := fluentd.ParseAddr(c.LoggerAddr)
|
logHost, logPort, err := fluentd.ParseAddr(c.LoggerAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error parsing logger addr: %s. Err: %v", c.LoggerAddr, err)
|
log.Fatalf("Error parsing logger addr: %s. Err: %v", c.LoggerAddr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger, err := fluentd.NewLogger(c.GetAppFullName(), logHost, logPort) // @Refactor NewLogger return (logger, error)
|
logger, err := fluentd.NewLogger(c.Base.GetAppFullName(), logHost, logPort) // @Refactor NewLogger return (logger, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error connecting to %s:%d. Err: %v", logHost, logPort, err)
|
log.Fatalf("Error connecting to %s:%d. Err: %v", logHost, logPort, err)
|
||||||
}
|
}
|
||||||
defer logger.Close()
|
// defer logger.Close()
|
||||||
|
|
||||||
flag.Usage = usage
|
flag.Usage = usage
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -65,9 +65,9 @@ func main() {
|
|||||||
Database: "egommerce",
|
Database: "egommerce",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
mTbl := baseCnf.GetEnv("MIGRATIONS_TABLE_NAME", defMigrationsTableName)
|
||||||
mig := migrations.NewCollection()
|
mig := migrations.NewCollection()
|
||||||
mig.SetTableName(mTblName)
|
mig.SetTableName(mTbl)
|
||||||
|
|
||||||
if err := mig.DiscoverSQLMigrations("./migrations"); err != nil {
|
if err := mig.DiscoverSQLMigrations("./migrations"); err != nil {
|
||||||
logger.Log("migration dicovery error: %#v", err)
|
logger.Log("migration dicovery error: %#v", err)
|
||||||
}
|
}
|
||||||
|
@ -5,31 +5,30 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
cnf "git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
baseCnf "git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/server"
|
cnf "git.pbiernat.dev/egommerce/basket-service/internal/config"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/common"
|
svr "git.pbiernat.dev/egommerce/basket-service/internal/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if cnf.ErrLoadingEnvs != nil {
|
if baseCnf.ErrLoadingEnvs != nil {
|
||||||
log.Panicln("Error loading .env file", cnf.ErrLoadingEnvs)
|
log.Panicln("Error loading .env file", baseCnf.ErrLoadingEnvs)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := common.NewConfig()
|
c := cnf.NewConfig()
|
||||||
fmt.Println("Creating new server...")
|
srv := svr.New(
|
||||||
srv := server.New(
|
|
||||||
c,
|
c,
|
||||||
server.WithCache(c),
|
svr.WithCache(c),
|
||||||
server.WithDatabase(c),
|
svr.WithDatabase(c),
|
||||||
server.WithEventbus(c),
|
svr.WithEventbus(c),
|
||||||
server.WithLogger(c),
|
svr.WithLogger(c),
|
||||||
server.WithRegistry(c),
|
svr.WithRegistry(c),
|
||||||
)
|
)
|
||||||
|
|
||||||
forever := make(chan struct{})
|
while := make(chan struct{})
|
||||||
err := srv.Base.Start(forever, srv.Shutdown())
|
err := srv.Base.Start(while, srv.Shutdown())
|
||||||
<-forever
|
<-while
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to start server. Reason: %v\n", err)
|
log.Fatalf("Failed to start server. Reason: %v\n", err)
|
||||||
@ -38,43 +37,4 @@ func main() {
|
|||||||
|
|
||||||
fmt.Println("Done.")
|
fmt.Println("Done.")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|
||||||
// c.AppDomain = cnf.GetEnv("APP_DOMAIN", defAppDomain)
|
|
||||||
// c.Port, _ = strconv.Atoi(c.NetAddr[1:])
|
|
||||||
// c.KVNamespace = cnf.GetEnv("APP_KV_NAMESPACE", defKVNmspc)
|
|
||||||
|
|
||||||
// logHost, logPort := fluentd.ParseAddr(c.LoggerAddr)
|
|
||||||
// logger := fluentd.NewLogger(c.GetAppFullName(), logHost, logPort)
|
|
||||||
// defer logger.Close()
|
|
||||||
|
|
||||||
// db conn
|
|
||||||
// dbConn, err := database.Connect(c.DbURL)
|
|
||||||
// if err != nil { // fixme: add wait-for-db...
|
|
||||||
// logger.Log("Failed to connect to Database server: %v\n", err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
// defer dbConn.Close()
|
|
||||||
|
|
||||||
// redis conn
|
|
||||||
// redis := redis.NewClient(&redis.Options{
|
|
||||||
// Addr: c.CacheAddr,
|
|
||||||
// Password: c.CachePassword,
|
|
||||||
// DB: 0,
|
|
||||||
// })
|
|
||||||
// defer redis.Close()
|
|
||||||
|
|
||||||
// eventbus conn
|
|
||||||
// ebConn, ebCh, err := amqp.Open(c.EventBusURL)
|
|
||||||
// if err != nil {
|
|
||||||
// logger.Log("Failed to connect to EventBus server: %v\n", err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
// defer ebCh.Close()
|
|
||||||
// defer amqp.Close(ebConn)
|
|
||||||
|
|
||||||
// err = amqp.NewExchange(ebCh, c.EventBusExchange)
|
|
||||||
// if err != nil {
|
|
||||||
// logger.Log("Failed to declare EventBus exchange: %v\n", err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
@ -1,217 +1,30 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
|
||||||
"github.com/go-redis/redis/v8"
|
|
||||||
"github.com/streadway/amqp"
|
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/consul"
|
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/event"
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/ui"
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/common"
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
"git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/pkg/database"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
cnf "git.pbiernat.dev/egommerce/basket-service/internal/config"
|
||||||
// defAppName = "basket-worker"
|
"git.pbiernat.dev/egommerce/basket-service/internal/worker"
|
||||||
// defLoggerAddr = "api-logger:24224"
|
|
||||||
// defRegistryAddr = "api-registry:8500"
|
|
||||||
// defDbURL = "postgres://postgres:12345678@postgres-db:5432/egommerce"
|
|
||||||
// defCacheAddr = "api-cache:6379"
|
|
||||||
// defCachePassword = "12345678"
|
|
||||||
// defMongoDbURL = "mongodb://mongodb:12345678@mongo-db:27017"
|
|
||||||
// defEventBusURL = "amqp://guest:guest@api-eventbus:5672"
|
|
||||||
// ebEventsExchange = "api-events"
|
|
||||||
// ebEventsQueue = "basket-worker"
|
|
||||||
// defKVNmspc = "dev.egommerce/service/basket-worker"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if config.ErrLoadingEnvs != nil {
|
if config.ErrLoadingEnvs != nil {
|
||||||
log.Panicln("Error loading .env file", config.ErrLoadingEnvs)
|
log.Panicln("Error loading .env file.")
|
||||||
}
|
}
|
||||||
|
|
||||||
c := common.NewConfig()
|
c := cnf.NewConfig()
|
||||||
logHost, logPort, err := fluentd.ParseAddr(c.LoggerAddr)
|
wrk := worker.New(
|
||||||
if err != nil {
|
c,
|
||||||
log.Fatalf("Error parsing logger addr: %s. Err: %v", c.LoggerAddr, err)
|
worker.WithCache(c),
|
||||||
}
|
worker.WithDatabase(c),
|
||||||
|
worker.WithEventbus(c),
|
||||||
logger, err := fluentd.NewLogger(c.GetAppFullName(), logHost, logPort) // @Refactor NewLogger return (logger, error)
|
worker.WithLogger(c),
|
||||||
if err != nil {
|
worker.WithRegistry(c),
|
||||||
log.Fatalf("Error connecting to %s:%d. Err: %v", logHost, logPort, err)
|
|
||||||
}
|
|
||||||
defer logger.Close()
|
|
||||||
|
|
||||||
// consul, err := consul.NewService(c.RegistryAddr, c.Base.AppID, c.Base.AppName, c.Base.AppID, "", "", 0)
|
|
||||||
registry, err := consul.NewService(c.RegistryAddr, c.Base.AppID, c.Base.AppName, c.Base.AppID, "", "", 0)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log("Error connecting to %s: %v", c.RegistryAddr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func(consul *consul.Service) {
|
|
||||||
ticker := time.NewTicker(time.Second * 15)
|
|
||||||
for range ticker.C {
|
|
||||||
updateKVConfig(consul, c) // FIXME: duplicated in internal/app/server/server.go
|
|
||||||
}
|
|
||||||
}(registry)
|
|
||||||
|
|
||||||
// db conn
|
|
||||||
dbConn, err := database.Connect(c.DbURL)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log("Failed to connect to Database server: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer dbConn.Close()
|
|
||||||
|
|
||||||
// redis conn
|
|
||||||
redis := redis.NewClient(&redis.Options{
|
|
||||||
Addr: c.CacheAddr,
|
|
||||||
Password: c.CachePassword,
|
|
||||||
DB: 0,
|
|
||||||
})
|
|
||||||
defer redis.Close()
|
|
||||||
|
|
||||||
// eventbus conn
|
|
||||||
ebConn, ebCh, err := rabbitmq.Open(c.EventBusURL)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log("Failed to connect to EventBus server: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer ebCh.Close()
|
|
||||||
defer rabbitmq.Close(ebConn)
|
|
||||||
|
|
||||||
err = rabbitmq.NewExchange(ebCh, c.EventBusExchange)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log("Failed to declare EventBus exchange: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// create and bind queues
|
|
||||||
_, err = ebCh.QueueDeclare(
|
|
||||||
c.EventBusQueue, // name
|
|
||||||
false, // durable
|
|
||||||
false, // delete when unused
|
|
||||||
false, // exclusive
|
|
||||||
false, // no-wait
|
|
||||||
nil, // arguments
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
|
||||||
logger.Log("Failed to declare EventBus queue: %v\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
rabbitmq.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productAddedToBasket")
|
|
||||||
rabbitmq.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productRemovedFromBasket")
|
|
||||||
rabbitmq.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.updateQuantity")
|
|
||||||
|
|
||||||
// event consume
|
|
||||||
msgs, err := ebCh.Consume(
|
|
||||||
c.EventBusQueue, // queue
|
|
||||||
"", // consumer
|
|
||||||
false, // auto-ack
|
|
||||||
false, // exclusive
|
|
||||||
false, // no-local
|
|
||||||
false, // no-wait
|
|
||||||
nil, // args
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log("Failed to register a consumer: %s", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
forever := make(chan struct{})
|
forever := make(chan struct{})
|
||||||
go func() {
|
wrk.Start()
|
||||||
sigint := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
<-sigint
|
|
||||||
|
|
||||||
logger.Log("Worker %s stopped working...\n", c.GetAppFullName())
|
|
||||||
|
|
||||||
close(forever)
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
basketSrv := service.NewBasketService(dbConn, redis, ebCh, logger)
|
|
||||||
|
|
||||||
for d := range msgs {
|
|
||||||
go func(d amqp.Delivery) {
|
|
||||||
msg, err := rabbitmq.Deserialize(d.Body)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log("deserialize error: %v\n", err)
|
|
||||||
d.Reject(false) // FIXME: or Nack? how to handle erros in queue...
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
eName := fmt.Sprintf("%s", msg["event"])
|
|
||||||
data := (msg["data"]).(map[string]interface{})
|
|
||||||
logger.Log("Message<%s>: %v\n", eName, data)
|
|
||||||
|
|
||||||
reqID := data["request_id"].(string) // FIXME Check input params!
|
|
||||||
basketID := data["basket_id"].(string) // FIXME Check input params!
|
|
||||||
|
|
||||||
switch true {
|
|
||||||
case strings.Contains(eName, event.EVENT_PRODUCT_ADDED_TO_BASKET):
|
|
||||||
productID := int(data["product_id"].(float64))
|
|
||||||
qty := int(data["quantity"].(float64))
|
|
||||||
|
|
||||||
basket, err := ui.AddProductToBasket(basketSrv, productID, qty, basketID, reqID)
|
|
||||||
if err == nil {
|
|
||||||
logger.Log("Product #%d added to basket #%s. ReqID: #%s", productID, basket.ID, reqID)
|
|
||||||
}
|
|
||||||
case strings.Contains(eName, event.EVENT_PRODUCT_REMOVED_FROM_BASKET):
|
|
||||||
productID := int(data["product_id"].(float64))
|
|
||||||
qty := int(data["quantity"].(float64))
|
|
||||||
|
|
||||||
basket, err := ui.RemoveProductFromBasket(basketSrv, productID, qty, basketID, reqID)
|
|
||||||
if err == nil {
|
|
||||||
logger.Log("Product #%d removed from basket #%s. ReqID: #%s", productID, basket.ID, reqID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
logger.Log("%s error: %s", eName, err.Error())
|
|
||||||
d.Reject(false) // FIXME: or Nack? how to handle erros in queue...
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log("ACK: %s", eName)
|
|
||||||
d.Ack(false)
|
|
||||||
}(d)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
logger.Log("Waiting for messages...")
|
|
||||||
<-forever
|
<-forever
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateKVConfig(s *consul.Service, oldCnf *common.Config) error { // FIXME: duplicated in internal/app/server/server.go
|
|
||||||
// data, _, err := s.KV().Get(oldCnf.KVNamespace, nil)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if data == nil {
|
|
||||||
// return errors.New("empty KV config data")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// buf := bytes.NewBuffer(data.Value)
|
|
||||||
// decoder := json.NewDecoder(buf)
|
|
||||||
// if err := decoder.Decode(oldCnf); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,7 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
git.pbiernat.dev/egommerce/api-entities v0.0.26
|
git.pbiernat.dev/egommerce/api-entities v0.0.26
|
||||||
git.pbiernat.dev/egommerce/go-api-pkg v0.0.150
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.151
|
||||||
github.com/georgysavva/scany/v2 v2.0.0
|
github.com/georgysavva/scany/v2 v2.0.0
|
||||||
github.com/go-pg/migrations/v8 v8.1.0
|
github.com/go-pg/migrations/v8 v8.1.0
|
||||||
github.com/go-pg/pg/v10 v10.10.7
|
github.com/go-pg/pg/v10 v10.10.7
|
||||||
|
@ -7,6 +7,8 @@ git.pbiernat.dev/egommerce/go-api-pkg v0.0.149 h1:7K4z/XUMAPrnvOPcFfkeeNCpuc5IHo
|
|||||||
git.pbiernat.dev/egommerce/go-api-pkg v0.0.149/go.mod h1:w2N79aoumjrrcrGPJLkCwxAHtrLd7G4Uj8VOxvPooa0=
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.149/go.mod h1:w2N79aoumjrrcrGPJLkCwxAHtrLd7G4Uj8VOxvPooa0=
|
||||||
git.pbiernat.dev/egommerce/go-api-pkg v0.0.150 h1:DMM3Kxb6HNw4BExA7Ss7P9ivs+TIeO9DxjfHPKeWrSg=
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.150 h1:DMM3Kxb6HNw4BExA7Ss7P9ivs+TIeO9DxjfHPKeWrSg=
|
||||||
git.pbiernat.dev/egommerce/go-api-pkg v0.0.150/go.mod h1:w2N79aoumjrrcrGPJLkCwxAHtrLd7G4Uj8VOxvPooa0=
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.150/go.mod h1:w2N79aoumjrrcrGPJLkCwxAHtrLd7G4Uj8VOxvPooa0=
|
||||||
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.151 h1:MKf+tka3Bhh4Zbn5cLqO6H39gsf7el/GUT8ittaIujM=
|
||||||
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.151/go.mod h1:w2N79aoumjrrcrGPJLkCwxAHtrLd7G4Uj8VOxvPooa0=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
cnf "git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
cnf "git.pbiernat.dev/egommerce/basket-service/pkg/config"
|
||||||
@ -27,14 +26,6 @@ const (
|
|||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Base *srv.Config
|
Base *srv.Config
|
||||||
// AppID string
|
|
||||||
// AppName string
|
|
||||||
// NetAddr string
|
|
||||||
// PathPrefix string
|
|
||||||
|
|
||||||
// IdleTimeout time.Duration `json:"idle_timeout"` // miliseconds
|
|
||||||
// ReadTimeout time.Duration `json:"read_timeout"` // miliseconds
|
|
||||||
// WriteTimeout time.Duration `json:"write_timeout"` // miliseconds
|
|
||||||
|
|
||||||
DbURL string `json:"db_url"`
|
DbURL string `json:"db_url"`
|
||||||
CacheAddr string `json:"cache_addr"`
|
CacheAddr string `json:"cache_addr"`
|
||||||
@ -46,13 +37,6 @@ type Config struct {
|
|||||||
RegistryAddr string
|
RegistryAddr string
|
||||||
|
|
||||||
// Fields with JSON mappings are available through Consul KV storage
|
// Fields with JSON mappings are available through Consul KV storage
|
||||||
|
|
||||||
// Port int
|
|
||||||
// KVNamespace string
|
|
||||||
// MongoDbUrl string `json:"mongodb_url"`
|
|
||||||
// HttpReadTimeout int `json:"http_read_timeout"`
|
|
||||||
// HttpWriteTimeout int `json:"http_write_timeout"`
|
|
||||||
// HttpIdleTimeout int `json:"http_idle_timeout"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
@ -74,11 +58,3 @@ func NewConfig() *Config {
|
|||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetAppFullName() string {
|
|
||||||
return fmt.Sprintf("%s_%s", c.Base.AppName, c.Base.AppID) // @TODO check if Base prop can be private
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) GetListenAddr() string {
|
|
||||||
return "" // @TODO: Implement me!
|
|
||||||
}
|
|
@ -5,8 +5,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/api-entities/http"
|
"git.pbiernat.dev/egommerce/api-entities/http"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
"git.pbiernat.dev/egommerce/basket-service/internal/service"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/ui"
|
"git.pbiernat.dev/egommerce/basket-service/internal/ui"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -20,13 +19,13 @@ import (
|
|||||||
db "git.pbiernat.dev/egommerce/basket-service/pkg/database"
|
db "git.pbiernat.dev/egommerce/basket-service/pkg/database"
|
||||||
srv "git.pbiernat.dev/egommerce/basket-service/pkg/server"
|
srv "git.pbiernat.dev/egommerce/basket-service/pkg/server"
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/common"
|
cnf "git.pbiernat.dev/egommerce/basket-service/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Server struct {
|
Server struct {
|
||||||
Base *srv.Server
|
Base *srv.Server
|
||||||
Config *common.Config
|
Config *cnf.Config
|
||||||
|
|
||||||
Cache *redis.Client
|
Cache *redis.Client
|
||||||
Database *pgxpool.Pool
|
Database *pgxpool.Pool
|
||||||
@ -37,10 +36,10 @@ type (
|
|||||||
kvNmspc string
|
kvNmspc string
|
||||||
}
|
}
|
||||||
|
|
||||||
OptionFn func(*Server) error
|
OptionFn func(*Server) error // FIXME: similar in worker
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(c *common.Config, opts ...OptionFn) *Server {
|
func New(c *cnf.Config, opts ...OptionFn) *Server {
|
||||||
svr := &Server{
|
svr := &Server{
|
||||||
Base: srv.New(c.Base),
|
Base: srv.New(c.Base),
|
||||||
Config: c,
|
Config: c,
|
||||||
@ -48,7 +47,7 @@ func New(c *common.Config, opts ...OptionFn) *Server {
|
|||||||
|
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
if err := opt(svr); err != nil {
|
if err := opt(svr); err != nil {
|
||||||
log.Fatalf("Failed to start HTTP Server. Err: %v\n", err)
|
log.Fatalf("Failed to attach extension to the server. Err: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ func New(c *common.Config, opts ...OptionFn) *Server {
|
|||||||
return svr
|
return svr
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithCache(c *common.Config) OptionFn {
|
func WithCache(c *cnf.Config) OptionFn {
|
||||||
redis := redis.NewClient(&redis.Options{
|
redis := redis.NewClient(&redis.Options{
|
||||||
Addr: c.CacheAddr,
|
Addr: c.CacheAddr,
|
||||||
Password: c.CachePassword,
|
Password: c.CachePassword,
|
||||||
@ -70,10 +69,9 @@ func WithCache(c *common.Config) OptionFn {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// defer redis.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithDatabase(c *common.Config) OptionFn {
|
func WithDatabase(c *cnf.Config) OptionFn {
|
||||||
dbConn, err := db.Connect(c.DbURL)
|
dbConn, err := db.Connect(c.DbURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to connect to the Database: %s. Err: %v\n", c.DbURL, err)
|
log.Fatalf("Failed to connect to the Database: %s. Err: %v\n", c.DbURL, err)
|
||||||
@ -85,10 +83,9 @@ func WithDatabase(c *common.Config) OptionFn {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// defer dbConn.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithEventbus(c *common.Config) OptionFn {
|
func WithEventbus(c *cnf.Config) OptionFn {
|
||||||
conn, err := amqp.Dial(c.EventBusURL)
|
conn, err := amqp.Dial(c.EventBusURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to connect to the Eventbus: %s. Err: %v\n", c.EventBusURL, err)
|
log.Fatalf("Failed to connect to the Eventbus: %s. Err: %v\n", c.EventBusURL, err)
|
||||||
@ -104,53 +101,49 @@ func WithEventbus(c *common.Config) OptionFn {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// defer ebCh.Close()
|
|
||||||
// defer amqp.Close(ebConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithLogger(c *common.Config) OptionFn {
|
func WithLogger(c *cnf.Config) OptionFn {
|
||||||
logHost, logPort, err := fluentd.ParseAddr(c.LoggerAddr)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to parse Fluentd address: %s. Err: %v", c.LoggerAddr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger, err := fluentd.NewLogger(c.GetAppFullName(), logHost, logPort)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to the Fluentd on %s:%d. Err: %v", logHost, logPort, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(s *Server) error {
|
return func(s *Server) error {
|
||||||
|
logHost, logPort, err := fluentd.ParseAddr(c.LoggerAddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse Fluentd address: %s. Err: %v", c.LoggerAddr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger, err := fluentd.NewLogger(c.Base.GetAppFullName(), logHost, logPort)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to connect to the Fluentd on %s:%d. Err: %v", logHost, logPort, err)
|
||||||
|
}
|
||||||
|
|
||||||
s.Logger = logger
|
s.Logger = logger
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// defer logger.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithRegistry(c *common.Config) OptionFn {
|
func WithRegistry(c *cnf.Config) OptionFn {
|
||||||
port, _ := strconv.Atoi(c.Base.NetAddr[1:]) // FIXME: can be IP:PORT which now will cause error
|
|
||||||
registry, err := consul.NewService(c.RegistryAddr, c.Base.AppID, c.Base.AppName, c.Base.AppID, c.Base.AppName, c.Base.PathPrefix, port)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to the Consul on: %s. Err: %v", c.RegistryAddr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = registry.Register()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to register in the Consul service. Err: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return func(s *Server) error {
|
return func(s *Server) error {
|
||||||
|
port, _ := strconv.Atoi(c.Base.NetAddr[1:]) // FIXME: can be IP:PORT which will cause error
|
||||||
|
registry, err := consul.NewService(c.RegistryAddr, c.Base.AppID, c.Base.AppName, c.Base.AppID, c.Base.AppName, c.Base.PathPrefix, port)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to connect to the Consul on: %s. Err: %v", c.RegistryAddr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = registry.Register()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to register in the Consul service. Err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
s.Registry = registry
|
s.Registry = registry
|
||||||
|
|
||||||
go func( /*s *Server*/ ) { // Consul KV updater
|
go func() { // Consul KV updater
|
||||||
ticker := time.NewTicker(time.Second * 15)
|
ticker := time.NewTicker(time.Second * 15)
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
s.updateKVConfig()
|
updateKVConfig(s)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func( /*s *Server*/ ) { // Server metadata cache updater
|
go func() { // Server metadata cache updater
|
||||||
ticker := time.NewTicker(time.Second * 5)
|
ticker := time.NewTicker(time.Second * 5)
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
s.cacheMetadata()
|
s.cacheMetadata()
|
||||||
@ -177,7 +170,7 @@ func (s *Server) Shutdown() srv.PurgeFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @CHECK: merge s.Config and s.Base.Config to display all config as one array/map
|
// @CHECK: merge s.Config and s.Base.Config to display all config as one array/map
|
||||||
func (s *Server) updateKVConfig() {
|
func updateKVConfig(s *Server) { // @FIXME: merge duplication in server.go and worker.go
|
||||||
config, _, err := s.Registry.KV().Get(s.kvNmspc, nil)
|
config, _, err := s.Registry.KV().Get(s.kvNmspc, nil)
|
||||||
if err != nil || config == nil {
|
if err != nil || config == nil {
|
||||||
return
|
return
|
||||||
@ -204,7 +197,6 @@ func (s *Server) cacheMetadata() {
|
|||||||
|
|
||||||
func (s *Server) clearMetadataCache() {
|
func (s *Server) clearMetadataCache() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
fmt.Printf("metadata: %v", s.Config.Base)
|
|
||||||
key, address := s.getMetadataIPsKey(), s.Config.Base.AppID
|
key, address := s.getMetadataIPsKey(), s.Config.Base.AppID
|
||||||
|
|
||||||
s.Cache.LRem(ctx, key, 0, address)
|
s.Cache.LRem(ctx, key, 0, address)
|
@ -3,15 +3,17 @@ package service
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/api-entities/model"
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/event"
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/api"
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
|
||||||
"github.com/georgysavva/scany/v2/pgxscan"
|
"github.com/georgysavva/scany/v2/pgxscan"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
"github.com/streadway/amqp"
|
"github.com/streadway/amqp"
|
||||||
|
|
||||||
|
"git.pbiernat.dev/egommerce/api-entities/model"
|
||||||
|
"git.pbiernat.dev/egommerce/go-api-pkg/api"
|
||||||
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
||||||
|
"git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
||||||
|
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/event"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
@ -3,9 +3,10 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
def "git.pbiernat.dev/egommerce/api-entities/http"
|
entity "git.pbiernat.dev/egommerce/api-entities/http"
|
||||||
"git.pbiernat.dev/egommerce/api-entities/model"
|
"git.pbiernat.dev/egommerce/api-entities/model"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AddProductToBasket(srv *service.BasketService, productID, qty int, basketID, reqID string) (*model.BasketModel, error) {
|
func AddProductToBasket(srv *service.BasketService, productID, qty int, basketID, reqID string) (*model.BasketModel, error) {
|
||||||
@ -74,15 +75,14 @@ func RemoveProductFromBasket(srv *service.BasketService, productID, qty int, bas
|
|||||||
return basket, nil
|
return basket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckoutBasket(srv *service.BasketService, basketID, reqID string) (*def.BasketCheckoutResponse, error) {
|
func CheckoutBasket(srv *service.BasketService, basketID, reqID string) (*entity.BasketCheckoutResponse, error) {
|
||||||
// ctx := context.Background()
|
res := &entity.BasketCheckoutResponse{}
|
||||||
res := &def.BasketCheckoutResponse{}
|
|
||||||
basketID, err := srv.Checkout(reqID, basketID)
|
basketID, err := srv.Checkout(reqID, basketID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res.ID = basketID
|
res.ID = basketID
|
||||||
// ctx.Done() // FIXME
|
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
272
src/internal/worker/worker.go
Normal file
272
src/internal/worker/worker.go
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
package worker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
"github.com/streadway/amqp"
|
||||||
|
|
||||||
|
"git.pbiernat.dev/egommerce/go-api-pkg/consul"
|
||||||
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
||||||
|
"git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
||||||
|
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/pkg/database"
|
||||||
|
|
||||||
|
cnf "git.pbiernat.dev/egommerce/basket-service/internal/config"
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/event"
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/service"
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/ui"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Worker struct {
|
||||||
|
Config *cnf.Config
|
||||||
|
|
||||||
|
Cache *redis.Client
|
||||||
|
Database *pgxpool.Pool
|
||||||
|
Eventbus *amqp.Channel
|
||||||
|
Logger *fluentd.Logger
|
||||||
|
Registry *consul.Service
|
||||||
|
|
||||||
|
kvNmspc string
|
||||||
|
}
|
||||||
|
OptionFn func(*Worker) error // FIXME: similar in server/server.go
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(c *cnf.Config, opts ...OptionFn) *Worker {
|
||||||
|
wrk := &Worker{
|
||||||
|
Config: c,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, opt := range opts {
|
||||||
|
if err := opt(wrk); err != nil {
|
||||||
|
log.Fatalf("Failed to attach extension to the worker. Err: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wrk
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worker) Start() error {
|
||||||
|
// event consume
|
||||||
|
msgs, err := w.Eventbus.Consume(
|
||||||
|
w.Config.EventBusQueue, // queue
|
||||||
|
"", // consumer
|
||||||
|
false, // auto-ack
|
||||||
|
false, // exclusive
|
||||||
|
false, // no-local
|
||||||
|
false, // no-wait
|
||||||
|
nil, // args
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Failed to register a consumer: %s", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
forever := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
sigint := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
<-sigint
|
||||||
|
|
||||||
|
w.Logger.Log("Shutting down %s worker...\n", w.Config.Base.GetAppFullName())
|
||||||
|
w.Shutdown()
|
||||||
|
|
||||||
|
close(forever)
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
basketSrv := service.NewBasketService(w.Database, w.Cache, w.Eventbus, w.Logger)
|
||||||
|
// basketSrv := service.NewBasketService(w)
|
||||||
|
|
||||||
|
for d := range msgs {
|
||||||
|
go func(d amqp.Delivery) {
|
||||||
|
msg, err := rabbitmq.Deserialize(d.Body)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("deserialize error: %v\n", err)
|
||||||
|
d.Reject(false) // FIXME: or Nack? how to handle erros in queue...
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
eName := fmt.Sprintf("%s", msg["event"])
|
||||||
|
data := (msg["data"]).(map[string]interface{})
|
||||||
|
w.Logger.Log("Message<%s>: %v\n", eName, data)
|
||||||
|
|
||||||
|
reqID := data["request_id"].(string) // FIXME Check input params!
|
||||||
|
basketID := data["basket_id"].(string) // FIXME Check input params!
|
||||||
|
|
||||||
|
switch true {
|
||||||
|
case strings.Contains(eName, event.EVENT_PRODUCT_ADDED_TO_BASKET):
|
||||||
|
productID := int(data["product_id"].(float64))
|
||||||
|
qty := int(data["quantity"].(float64))
|
||||||
|
|
||||||
|
basket, err := ui.AddProductToBasket(basketSrv, productID, qty, basketID, reqID)
|
||||||
|
if err == nil {
|
||||||
|
w.Logger.Log("Product #%d added to basket #%s. ReqID: #%s", productID, basket.ID, reqID)
|
||||||
|
}
|
||||||
|
case strings.Contains(eName, event.EVENT_PRODUCT_REMOVED_FROM_BASKET):
|
||||||
|
productID := int(data["product_id"].(float64))
|
||||||
|
qty := int(data["quantity"].(float64))
|
||||||
|
|
||||||
|
basket, err := ui.RemoveProductFromBasket(basketSrv, productID, qty, basketID, reqID)
|
||||||
|
if err == nil {
|
||||||
|
w.Logger.Log("Product #%d removed from basket #%s. ReqID: #%s", productID, basket.ID, reqID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("%s error: %s", eName, err.Error())
|
||||||
|
d.Reject(false) // FIXME: or Nack? how to handle erros in queue...
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Logger.Log("ACK: %s", eName)
|
||||||
|
d.Ack(false)
|
||||||
|
}(d)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
w.Logger.Log("Waiting for messages...2")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worker) Shutdown() error {
|
||||||
|
w.Logger.Log("Worker is going down...")
|
||||||
|
|
||||||
|
w.Registry.Unregister()
|
||||||
|
w.Eventbus.Close()
|
||||||
|
w.Database.Close()
|
||||||
|
w.Logger.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithCache(c *cnf.Config) OptionFn {
|
||||||
|
return func(w *Worker) error {
|
||||||
|
conn := redis.NewClient(&redis.Options{
|
||||||
|
Addr: c.CacheAddr,
|
||||||
|
Password: c.CachePassword,
|
||||||
|
DB: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
w.Cache = conn
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithDatabase(c *cnf.Config) OptionFn {
|
||||||
|
return func(w *Worker) error {
|
||||||
|
conn, err := database.Connect(c.DbURL)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Failed to connect to Database server: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Database = conn
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithEventbus(c *cnf.Config) OptionFn {
|
||||||
|
return func(w *Worker) error {
|
||||||
|
_, chn, err := rabbitmq.Open(c.EventBusURL)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Failed to connect to EventBus server: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rabbitmq.NewExchange(chn, c.EventBusExchange)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Failed to declare EventBus exchange: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = chn.QueueDeclare(
|
||||||
|
c.EventBusQueue, // name
|
||||||
|
false, // durable
|
||||||
|
false, // delete when unused
|
||||||
|
false, // exclusive
|
||||||
|
false, // no-wait
|
||||||
|
nil, // arguments
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Failed to declare EventBus queue: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// w.BindQueues()
|
||||||
|
rabbitmq.BindQueueToExchange(chn, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productAddedToBasket")
|
||||||
|
rabbitmq.BindQueueToExchange(chn, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productRemovedFromBasket")
|
||||||
|
rabbitmq.BindQueueToExchange(chn, c.EventBusQueue, c.EventBusExchange, "catalog.basket.updateQuantity")
|
||||||
|
|
||||||
|
w.Eventbus = chn
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithLogger(c *cnf.Config) OptionFn {
|
||||||
|
return func(w *Worker) error {
|
||||||
|
logHost, logPort, err := fluentd.ParseAddr(c.LoggerAddr)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Failed to parse Fluentd address: %s. Err: %v", c.LoggerAddr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger, err := fluentd.NewLogger(c.Base.GetAppFullName(), logHost, logPort)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Failed to connect to the Fluentd on %s:%d. Err: %v", logHost, logPort, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Logger = logger
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithRegistry(c *cnf.Config) OptionFn {
|
||||||
|
return func(w *Worker) error {
|
||||||
|
registry, err := consul.NewService(c.RegistryAddr, c.Base.AppID, c.Base.AppName, c.Base.AppID, "", "", 0)
|
||||||
|
if err != nil {
|
||||||
|
w.Logger.Log("Error connecting to %s: %v", c.RegistryAddr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() { // Consul KV updater
|
||||||
|
ticker := time.NewTicker(time.Second * 15)
|
||||||
|
for range ticker.C {
|
||||||
|
updateKVConfig(w)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
w.Registry = registry
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// @CHECK: merge s.Config and s.Base.Config to display all config as one array/map
|
||||||
|
func updateKVConfig(w *Worker) { // @FIXME: merge duplication in server.go and worker.go
|
||||||
|
config, _, err := w.Registry.KV().Get(w.kvNmspc, nil)
|
||||||
|
if err != nil || config == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
kvCnf := bytes.NewBuffer(config.Value)
|
||||||
|
decoder := json.NewDecoder(kvCnf)
|
||||||
|
if err := decoder.Decode(&w.Config); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
@ -14,24 +14,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
HeaderRequestID struct {
|
|
||||||
RequestID string `reqHeader:"x-request-id"`
|
|
||||||
}
|
|
||||||
Server struct {
|
Server struct {
|
||||||
*fiber.App
|
*fiber.App
|
||||||
*Config
|
*Config
|
||||||
|
|
||||||
addr string // e.g. "127.0.0.1:8080"
|
addr string // e.g. "127.0.0.1:8080"
|
||||||
|
|
||||||
// name string // e.g. "awesome-rest-api"
|
// name string // e.g. "awesome-rest-api"
|
||||||
// kvNmspc string
|
// kvNmspc string
|
||||||
// cache *redis.Client
|
|
||||||
// db *pgxpool.Pool
|
|
||||||
// discovery *discovery.Service
|
|
||||||
// ebCh *amqp.Channel
|
|
||||||
// log *fluentd.Logger
|
|
||||||
}
|
}
|
||||||
PurgeFn func(*Server) error
|
HeaderRequestID struct {
|
||||||
|
RequestID string `reqHeader:"x-request-id"`
|
||||||
|
}
|
||||||
|
OptionFn func(*Server) error
|
||||||
|
PurgeFn func(*Server) error
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(conf *Config) *Server {
|
func New(conf *Config) *Server {
|
||||||
@ -48,6 +43,30 @@ func New(conf *Config) *Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) Start(while chan struct{}, prgFn PurgeFn) error {
|
||||||
|
go func() {
|
||||||
|
sigint := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
<-sigint
|
||||||
|
|
||||||
|
fmt.Print("Shutting down... ")
|
||||||
|
if err := prgFn(s); err != nil {
|
||||||
|
log.Fatalf("Failed to shutdown server. Reason: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
close(while)
|
||||||
|
}()
|
||||||
|
|
||||||
|
err := s.Listen(s.addr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to start server. Reason: %v\n", err)
|
||||||
|
close(while)
|
||||||
|
}
|
||||||
|
<-while
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
|
func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
|
||||||
var hdr = new(HeaderRequestID)
|
var hdr = new(HeaderRequestID)
|
||||||
if err := c.ReqHeaderParser(hdr); err != nil {
|
if err := c.ReqHeaderParser(hdr); err != nil {
|
||||||
@ -60,26 +79,3 @@ func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
|
|||||||
func (s *Server) Error(c *fiber.Ctx, code int, msg string) error {
|
func (s *Server) Error(c *fiber.Ctx, code int, msg string) error {
|
||||||
return c.Status(code).JSON(http.ErrorResponse{Error: msg})
|
return c.Status(code).JSON(http.ErrorResponse{Error: msg})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Start(forever chan struct{}, prgFn PurgeFn) error {
|
|
||||||
go func() {
|
|
||||||
sigint := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
<-sigint
|
|
||||||
|
|
||||||
fmt.Println("shutting down: after term signal.")
|
|
||||||
if err := prgFn(s); err != nil {
|
|
||||||
log.Fatalf("Failed to shutdown server. Reason: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
close(forever)
|
|
||||||
}()
|
|
||||||
|
|
||||||
err := s.Listen(s.addr)
|
|
||||||
<-forever
|
|
||||||
// if err := s.Listen(s.addr); err != nil {
|
|
||||||
// s.logger.Log("Failed to start server! Reason: %v\n", err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user