This commit is contained in:
parent
dca3a531fe
commit
9c74b911c3
@ -6,10 +6,10 @@ FROM ${BUILDER_IMAGE} AS builder
|
|||||||
# FROM gcr.io/distroless/base-debian10
|
# FROM gcr.io/distroless/base-debian10
|
||||||
FROM alpine:3.17
|
FROM alpine:3.17
|
||||||
|
|
||||||
ARG BUILD_TIME
|
|
||||||
ARG BIN_OUTPUT
|
|
||||||
ARG SVC_NAME
|
ARG SVC_NAME
|
||||||
ARG SVC_VER
|
ARG SVC_VER
|
||||||
|
ARG BIN_OUTPUT
|
||||||
|
ARG BUILD_TIME
|
||||||
|
|
||||||
LABEL dev.egommerce.image.author="Piotr Biernat"
|
LABEL dev.egommerce.image.author="Piotr Biernat"
|
||||||
LABEL dev.egommerce.image.vendor="Egommerce"
|
LABEL dev.egommerce.image.vendor="Egommerce"
|
||||||
@ -26,5 +26,5 @@ RUN chmod 755 /bin/entrypoint.sh /bin/migrate.sh
|
|||||||
|
|
||||||
EXPOSE 80
|
EXPOSE 80
|
||||||
|
|
||||||
CMD ["/app"]
|
CMD ["sh", "-c", "/app"]
|
||||||
ENTRYPOINT ["entrypoint.sh"]
|
ENTRYPOINT ["entrypoint.sh"]
|
||||||
|
@ -18,6 +18,7 @@ waitForService "postgres-db:5432"
|
|||||||
waitForService "api-eventbus:5672"
|
waitForService "api-eventbus:5672"
|
||||||
waitForService "api-logger:24224"
|
waitForService "api-logger:24224"
|
||||||
waitForService "api-registry:8500"
|
waitForService "api-registry:8500"
|
||||||
|
waitForService "pricing-svc:80"
|
||||||
|
|
||||||
# run migrations
|
# run migrations
|
||||||
migrate.sh
|
migrate.sh
|
||||||
|
@ -58,17 +58,18 @@ func main() {
|
|||||||
mig.SetTableName(mTblName)
|
mig.SetTableName(mTblName)
|
||||||
err := mig.DiscoverSQLMigrations("./migrations")
|
err := mig.DiscoverSQLMigrations("./migrations")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
logger.Log("migration dicovery error: %#v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
oldVersion, newVersion, err := mig.Run(db, flag.Args()...)
|
oldVersion, newVersion, err := mig.Run(db, flag.Args()...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exitf(err.Error())
|
logger.Log("migration runner error: %#v", err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if newVersion != oldVersion {
|
if newVersion != oldVersion {
|
||||||
fmt.Printf("migrated from version %d to %d\n", oldVersion, newVersion)
|
logger.Log("migrated from version %d to %d\n", oldVersion, newVersion)
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("version is %d\n", oldVersion)
|
logger.Log("version is %d\n", oldVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,12 +78,3 @@ func usage() {
|
|||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorf(s string, args ...interface{}) {
|
|
||||||
fmt.Fprintf(os.Stderr, s+"\n", args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func exitf(s string, args ...interface{}) {
|
|
||||||
errorf(s, args...)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
@ -10,15 +10,19 @@ import (
|
|||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/server"
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/server"
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
||||||
amqp "git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
amqp "git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defAppName = "basket-svc"
|
defAppName = "basket-svc"
|
||||||
defAppDomain = "basket-svc"
|
defAppDomain = "basket-svc"
|
||||||
|
defPathPrefix = "/basket"
|
||||||
defNetAddr = ":80"
|
defNetAddr = ":80"
|
||||||
defLoggerAddr = "api-logger:24224"
|
defLoggerAddr = "api-logger:24224"
|
||||||
defRegistryAddr = "api-registry:8500"
|
defRegistryAddr = "api-registry:8500"
|
||||||
defDbURL = "postgres://postgres:12345678@postgres-db:5432/egommerce"
|
defDbURL = "postgres://postgres:12345678@postgres-db:5432/egommerce"
|
||||||
|
defCacheAddr = "api-cache:6379"
|
||||||
|
defCachePassword = "12345678"
|
||||||
defMongoDbURL = "mongodb://mongodb:12345678@mongo-db:27017"
|
defMongoDbURL = "mongodb://mongodb:12345678@mongo-db:27017"
|
||||||
defEventBusURL = "amqp://guest:guest@api-eventbus:5672"
|
defEventBusURL = "amqp://guest:guest@api-eventbus:5672"
|
||||||
ebEventsExchange = "api-events"
|
ebEventsExchange = "api-events"
|
||||||
@ -35,11 +39,14 @@ func main() {
|
|||||||
c.AppID, _ = os.Hostname()
|
c.AppID, _ = os.Hostname()
|
||||||
c.AppName = config.GetEnv("APP_NAME", defAppName)
|
c.AppName = config.GetEnv("APP_NAME", defAppName)
|
||||||
c.AppDomain = config.GetEnv("APP_DOMAIN", defAppDomain)
|
c.AppDomain = config.GetEnv("APP_DOMAIN", defAppDomain)
|
||||||
|
c.PathPrefix = config.GetEnv("APP_PATH_PREFIX", defPathPrefix)
|
||||||
c.NetAddr = config.GetEnv("SERVER_ADDR", defNetAddr)
|
c.NetAddr = config.GetEnv("SERVER_ADDR", defNetAddr)
|
||||||
c.Port, _ = strconv.Atoi(c.NetAddr[1:])
|
c.Port, _ = strconv.Atoi(c.NetAddr[1:])
|
||||||
c.LoggerAddr = config.GetEnv("LOGGER_ADDR", defLoggerAddr)
|
c.LoggerAddr = config.GetEnv("LOGGER_ADDR", defLoggerAddr)
|
||||||
c.RegistryAddr = config.GetEnv("REGISTRY_ADDR", defRegistryAddr)
|
c.RegistryAddr = config.GetEnv("REGISTRY_ADDR", defRegistryAddr)
|
||||||
c.DbURL = config.GetEnv("DATABASE_URL", defDbURL)
|
c.DbURL = config.GetEnv("DATABASE_URL", defDbURL)
|
||||||
|
c.CacheAddr = config.GetEnv("CACHE_ADDR", defCacheAddr)
|
||||||
|
c.CachePassword = config.GetEnv("CACHE_PASSWORD", defCachePassword)
|
||||||
c.EventBusURL = config.GetEnv("EVENTBUS_URL", defEventBusURL)
|
c.EventBusURL = config.GetEnv("EVENTBUS_URL", defEventBusURL)
|
||||||
c.EventBusExchange = ebEventsExchange
|
c.EventBusExchange = ebEventsExchange
|
||||||
c.KVNamespace = config.GetEnv("APP_KV_NAMESPACE", defKVNmspc)
|
c.KVNamespace = config.GetEnv("APP_KV_NAMESPACE", defKVNmspc)
|
||||||
@ -56,6 +63,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer dbConn.Close()
|
defer dbConn.Close()
|
||||||
|
|
||||||
|
// redis conn
|
||||||
|
redis := redis.NewClient(&redis.Options{
|
||||||
|
Addr: c.CacheAddr,
|
||||||
|
Password: c.CachePassword,
|
||||||
|
DB: 0,
|
||||||
|
})
|
||||||
|
defer redis.Close()
|
||||||
|
|
||||||
// eventbus conn
|
// eventbus conn
|
||||||
ebConn, ebCh, err := amqp.Open(c.EventBusURL)
|
ebConn, ebCh, err := amqp.Open(c.EventBusURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -72,7 +87,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start server
|
// start server
|
||||||
srv := server.NewServer(c, logger, dbConn, ebCh)
|
srv := server.NewServer(c, logger, dbConn, redis, ebCh)
|
||||||
|
|
||||||
forever := make(chan struct{})
|
forever := make(chan struct{})
|
||||||
srv.StartWithGracefulShutdown(forever)
|
srv.StartWithGracefulShutdown(forever)
|
||||||
|
@ -14,13 +14,15 @@ import (
|
|||||||
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/config"
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/config"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/database"
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/database"
|
||||||
def "git.pbiernat.dev/egommerce/basket-service/internal/app/definition"
|
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/event"
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/event"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/server"
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/server"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/ui"
|
||||||
discovery "git.pbiernat.dev/egommerce/go-api-pkg/consul"
|
discovery "git.pbiernat.dev/egommerce/go-api-pkg/consul"
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
||||||
amqp "git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
"git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
"github.com/streadway/amqp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -28,6 +30,8 @@ const (
|
|||||||
defLoggerAddr = "api-logger:24224"
|
defLoggerAddr = "api-logger:24224"
|
||||||
defRegistryAddr = "api-registry:8500"
|
defRegistryAddr = "api-registry:8500"
|
||||||
defDbURL = "postgres://postgres:12345678@postgres-db:5432/egommerce"
|
defDbURL = "postgres://postgres:12345678@postgres-db:5432/egommerce"
|
||||||
|
defCacheAddr = "api-cache:6379"
|
||||||
|
defCachePassword = "12345678"
|
||||||
defMongoDbURL = "mongodb://mongodb:12345678@mongo-db:27017"
|
defMongoDbURL = "mongodb://mongodb:12345678@mongo-db:27017"
|
||||||
defEventBusURL = "amqp://guest:guest@api-eventbus:5672"
|
defEventBusURL = "amqp://guest:guest@api-eventbus:5672"
|
||||||
ebEventsExchange = "api-events"
|
ebEventsExchange = "api-events"
|
||||||
@ -46,6 +50,8 @@ func main() {
|
|||||||
c.LoggerAddr = config.GetEnv("LOGGER_ADDR", defLoggerAddr)
|
c.LoggerAddr = config.GetEnv("LOGGER_ADDR", defLoggerAddr)
|
||||||
c.RegistryAddr = config.GetEnv("REGISTRY_ADDR", defRegistryAddr)
|
c.RegistryAddr = config.GetEnv("REGISTRY_ADDR", defRegistryAddr)
|
||||||
c.DbURL = config.GetEnv("DATABASE_URL", defDbURL)
|
c.DbURL = config.GetEnv("DATABASE_URL", defDbURL)
|
||||||
|
c.CacheAddr = config.GetEnv("CACHE_ADDR", defCacheAddr)
|
||||||
|
c.CachePassword = config.GetEnv("CACHE_PASSWORD", defCachePassword)
|
||||||
c.EventBusURL = config.GetEnv("EVENTBUS_URL", defEventBusURL)
|
c.EventBusURL = config.GetEnv("EVENTBUS_URL", defEventBusURL)
|
||||||
c.EventBusExchange = ebEventsExchange
|
c.EventBusExchange = ebEventsExchange
|
||||||
c.EventBusQueue = ebEventsQueue
|
c.EventBusQueue = ebEventsQueue
|
||||||
@ -55,7 +61,7 @@ func main() {
|
|||||||
logger := fluentd.NewLogger(c.GetAppFullName(), logHost, logPort)
|
logger := fluentd.NewLogger(c.GetAppFullName(), logHost, logPort)
|
||||||
defer logger.Close()
|
defer logger.Close()
|
||||||
|
|
||||||
consul, err := discovery.NewService(c.RegistryAddr, c.AppID, c.AppName, c.AppID, "", 0)
|
consul, err := discovery.NewService(c.RegistryAddr, c.AppID, c.AppName, c.AppID, "", "", 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log("Error connecting to %s: %v", c.RegistryAddr, err)
|
logger.Log("Error connecting to %s: %v", c.RegistryAddr, err)
|
||||||
}
|
}
|
||||||
@ -76,16 +82,24 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer dbConn.Close()
|
defer dbConn.Close()
|
||||||
|
|
||||||
|
// redis conn
|
||||||
|
redis := redis.NewClient(&redis.Options{
|
||||||
|
Addr: c.CacheAddr,
|
||||||
|
Password: c.CachePassword,
|
||||||
|
DB: 0,
|
||||||
|
})
|
||||||
|
defer redis.Close()
|
||||||
|
|
||||||
// eventbus conn
|
// eventbus conn
|
||||||
ebConn, ebCh, err := amqp.Open(c.EventBusURL)
|
ebConn, ebCh, err := rabbitmq.Open(c.EventBusURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log("Failed to connect to EventBus server: %v\n", err)
|
logger.Log("Failed to connect to EventBus server: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer ebCh.Close()
|
defer ebCh.Close()
|
||||||
defer amqp.Close(ebConn)
|
defer rabbitmq.Close(ebConn)
|
||||||
|
|
||||||
err = amqp.NewExchange(ebCh, c.EventBusExchange)
|
err = rabbitmq.NewExchange(ebCh, c.EventBusExchange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log("Failed to declare EventBus exchange: %v\n", err)
|
logger.Log("Failed to declare EventBus exchange: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -105,14 +119,9 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
amqp.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productAddedToBasket")
|
rabbitmq.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productAddedToBasket")
|
||||||
amqp.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productRemovedFromBasket")
|
rabbitmq.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.productRemovedFromBasket")
|
||||||
amqp.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.updateQuantity")
|
rabbitmq.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog.basket.updateQuantity")
|
||||||
// err = amqp.BindQueueToExchange(ebCh, c.EventBusQueue, c.EventBusExchange, "catalog-svc.product.addedToBasket")
|
|
||||||
// if err != nil {
|
|
||||||
// logger.Log("Failed to prepare EventBus queue: %v\n", err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// event consume
|
// event consume
|
||||||
msgs, err := ebCh.Consume(
|
msgs, err := ebCh.Consume(
|
||||||
@ -141,51 +150,55 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
bSrvc := service.NewBasketService(dbConn, ebCh, logger)
|
basketSrv := service.NewBasketService(dbConn, redis, ebCh, logger)
|
||||||
|
|
||||||
for d := range msgs {
|
for d := range msgs {
|
||||||
msg, err := amqp.Deserialize(d.Body)
|
go func(d amqp.Delivery) {
|
||||||
if err != nil {
|
msg, err := rabbitmq.Deserialize(d.Body)
|
||||||
logger.Log("json error: %v\n", err)
|
|
||||||
d.Reject(false) // FIXME: how to handle erros in queue...????
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
eName := fmt.Sprintf("%s", msg["event"])
|
|
||||||
data := (msg["data"]).(map[string]interface{})
|
|
||||||
logger.Log("Message<%s>: %s\n", eName, data)
|
|
||||||
|
|
||||||
basketID := data["basket_id"].(string) // FIXME Check input params!
|
|
||||||
productID := data["product_id"].(string) // FIXME Check input params!
|
|
||||||
|
|
||||||
switch true {
|
|
||||||
case strings.Contains(eName, event.EVENT_PRODUCT_ADDED_TO_BASKET):
|
|
||||||
var basket *def.BasketModel
|
|
||||||
basket, err := bSrvc.FetchFromDB(basketID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log("Basket#:%s not found. Creating...", basketID)
|
logger.Log("deserialize error: %v\n", err)
|
||||||
basket, err = bSrvc.Create(basketID)
|
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 {
|
if err != nil {
|
||||||
logger.Log("Creating basket error: %v", err)
|
fmt.Println("worker error: ", err)
|
||||||
d.Reject(false)
|
logger.Log("%s error: %s", event.EVENT_PRODUCT_ADDED_TO_BASKET, err.Error())
|
||||||
continue
|
d.Reject(false) // FIXME: or Nack? how to handle erros in queue...
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Log("Product #%s 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("%s error: %s", event.EVENT_PRODUCT_ADDED_TO_BASKET, err.Error())
|
||||||
|
d.Reject(false) // FIXME: or Nack? how to handle erros in queue...
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Log("Product #%s removed from basket #%s. ReqID: #%s", productID, basket.ID, reqID)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bSrvc.AddProduct(productID, basketID, 1) // FIXME: change to Update quantity - which add or delete product to/from basket depends on new quantity
|
logger.Log("ACK: %s", eName)
|
||||||
if err != nil {
|
d.Ack(false)
|
||||||
logger.Log("Error adding product to basket: %v", err)
|
}(d)
|
||||||
d.Reject(false)
|
|
||||||
}
|
|
||||||
logger.Log("Fetched basket: %v", basket)
|
|
||||||
|
|
||||||
case strings.Contains(eName, event.EVENT_PRODUCT_REMOVED_FROM_BASKET):
|
|
||||||
// remove product from basket
|
|
||||||
logger.Log("Event: %s", event.EVENT_PRODUCT_REMOVED_FROM_BASKET)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Log("ACK: %s", eName)
|
|
||||||
d.Ack(false)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -3,12 +3,13 @@ module git.pbiernat.dev/egommerce/basket-service
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.pbiernat.dev/egommerce/go-api-pkg v0.0.113
|
git.pbiernat.dev/egommerce/api-entities v0.0.26
|
||||||
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.136
|
||||||
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
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5
|
||||||
github.com/gofiber/fiber/v2 v2.40.1
|
github.com/gofiber/fiber/v2 v2.40.1
|
||||||
github.com/jackc/pgtype v1.12.0
|
|
||||||
github.com/jackc/pgx/v5 v5.1.1
|
github.com/jackc/pgx/v5 v5.1.1
|
||||||
github.com/joho/godotenv v1.4.0
|
github.com/joho/godotenv v1.4.0
|
||||||
github.com/streadway/amqp v1.0.0
|
github.com/streadway/amqp v1.0.0
|
||||||
@ -17,6 +18,8 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||||
github.com/armon/go-metrics v0.4.1 // indirect
|
github.com/armon/go-metrics v0.4.1 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
github.com/fatih/color v1.13.0 // indirect
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
github.com/fluent/fluent-logger-golang v1.9.0 // indirect
|
github.com/fluent/fluent-logger-golang v1.9.0 // indirect
|
||||||
github.com/go-pg/zerochecker v0.2.0 // indirect
|
github.com/go-pg/zerochecker v0.2.0 // indirect
|
||||||
@ -30,6 +33,7 @@ require (
|
|||||||
github.com/jackc/pgio v1.0.0 // indirect
|
github.com/jackc/pgio v1.0.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
||||||
|
github.com/jackc/pgtype v1.13.0 // indirect
|
||||||
github.com/jackc/puddle/v2 v2.1.2 // indirect
|
github.com/jackc/puddle/v2 v2.1.2 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/klauspost/compress v1.15.9 // indirect
|
github.com/klauspost/compress v1.15.9 // indirect
|
||||||
|
26
src/go.sum
26
src/go.sum
@ -1,6 +1,10 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
git.pbiernat.dev/egommerce/go-api-pkg v0.0.113 h1:kf7HesezhXIAMNYgLCm8x6YVqyLqJRqaPKIFEXf4xSs=
|
git.pbiernat.dev/egommerce/api-entities v0.0.26 h1:Avz02GINwuYWOjw1fmZIJ3QgGEIz3a5vRQZNaxxUQIk=
|
||||||
git.pbiernat.dev/egommerce/go-api-pkg v0.0.113/go.mod h1:nAwcw2MZtn/54YKq8VQK6RJAsiuoLUtPuazXg8JcqK8=
|
git.pbiernat.dev/egommerce/api-entities v0.0.26/go.mod h1:+BXvUcr6Cr6QNpJsW8BUfe1vVILdWDADNE0e3u0lNvU=
|
||||||
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.135 h1:qOa6MB6d2/lr0t9c3WWP84rf/T57PNYgizTmuNCDws8=
|
||||||
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.135/go.mod h1:w2N79aoumjrrcrGPJLkCwxAHtrLd7G4Uj8VOxvPooa0=
|
||||||
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.136 h1:SzJRAkqJKdng/3d0V7o/R0yGh7QaZynPBn/P++on9RA=
|
||||||
|
git.pbiernat.dev/egommerce/go-api-pkg v0.0.136/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=
|
||||||
@ -23,6 +27,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
|
|||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
@ -35,6 +41,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
@ -61,6 +69,8 @@ github.com/go-pg/pg/v10 v10.10.7 h1:Q7Bs45kP9MIg03v/ejwdqsPd1T0cecgeDoTJVg/UJuQ=
|
|||||||
github.com/go-pg/pg/v10 v10.10.7/go.mod h1:GLmFXufrElQHf5uzM3BQlcfwV3nsgnHue5uzjQ6Nqxg=
|
github.com/go-pg/pg/v10 v10.10.7/go.mod h1:GLmFXufrElQHf5uzM3BQlcfwV3nsgnHue5uzjQ6Nqxg=
|
||||||
github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
|
github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
|
||||||
github.com/go-pg/zerochecker v0.2.0/go.mod h1:NJZ4wKL0NmTtz0GKCoJ8kym6Xn/EQzXRl2OnAe7MmDo=
|
github.com/go-pg/zerochecker v0.2.0/go.mod h1:NJZ4wKL0NmTtz0GKCoJ8kym6Xn/EQzXRl2OnAe7MmDo=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
|
||||||
|
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gofiber/fiber/v2 v2.40.1 h1:pc7n9VVpGIqNsvg9IPLQhyFEMJL8gCs1kneH5D1pIl4=
|
github.com/gofiber/fiber/v2 v2.40.1 h1:pc7n9VVpGIqNsvg9IPLQhyFEMJL8gCs1kneH5D1pIl4=
|
||||||
github.com/gofiber/fiber/v2 v2.40.1/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk=
|
github.com/gofiber/fiber/v2 v2.40.1/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk=
|
||||||
@ -172,8 +182,8 @@ github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01C
|
|||||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
|
||||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
|
||||||
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
|
||||||
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
|
github.com/jackc/pgtype v1.13.0 h1:XkIc7A+1BmZD19bB2NxrtjJweHxQ9agqvM+9URc68Cg=
|
||||||
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
github.com/jackc/pgtype v1.13.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
|
||||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||||
@ -252,16 +262,16 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
|
|||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
|
|
||||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||||
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.14.2 h1:8mVmC9kjFFmA8H4pKMUhcblgifdkOIXPvbhN1T36q1M=
|
|
||||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
|
|
||||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||||
|
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
@ -523,8 +533,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
package definition
|
|
||||||
|
|
||||||
type BasketCheckoutRequest struct {
|
|
||||||
BasketID string `json:"basket_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type BasketCheckoutResponse struct {
|
|
||||||
ID string `json:"order_id"`
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
package definition
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jackc/pgtype"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BasketModel struct {
|
|
||||||
ID string `db:"id"`
|
|
||||||
CreatedAt time.Time `db:"created_at"`
|
|
||||||
UpdatedAt pgtype.Timestamp `db:"updated_at"`
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package definition
|
|
||||||
|
|
||||||
type ErrorResponse struct {
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func Error(err string) *ErrorResponse {
|
|
||||||
return &ErrorResponse{err}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package definition
|
|
||||||
|
|
||||||
type HealthResponse struct {
|
|
||||||
Status string `json:"status,omitempty"`
|
|
||||||
}
|
|
@ -1,24 +1,82 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
def "git.pbiernat.dev/egommerce/basket-service/internal/app/definition"
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
def "git.pbiernat.dev/egommerce/api-entities/http"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/ui"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) CheckoutHandler(c *fiber.Ctx) error {
|
func (s *Server) GetBasketHandler(c *fiber.Ctx) error {
|
||||||
reqID, _ := s.GetRequestID(c)
|
req := new(def.GetBasketRequest)
|
||||||
data := new(def.BasketCheckoutRequest)
|
if err := c.BodyParser(req); err != nil {
|
||||||
if err := c.BodyParser(data); err != nil {
|
return s.Error400(c, err.Error())
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
basketID := data.BasketID
|
basketID := req.BasketID
|
||||||
// vlaidate, pre check... etc
|
basketSrv := service.NewBasketService(s.db, s.cache, s.ebCh, s.log)
|
||||||
basket := service.NewBasketService(s.db, s.ebCh, s.log)
|
ctx := context.Background()
|
||||||
basket.Checkout(reqID, basketID)
|
basket, err := basketSrv.FetchFromDB(ctx, basketID)
|
||||||
|
if err != nil {
|
||||||
|
return s.Error400(c, "Failed to retrieve basket")
|
||||||
|
}
|
||||||
|
|
||||||
return c.JSON(&def.BasketCheckoutResponse{
|
res := &def.GetBasketResponse{
|
||||||
ID: data.BasketID,
|
ID: basket.ID,
|
||||||
})
|
State: basket.State,
|
||||||
|
CreatedAt: time.Duration(basket.CreatedAt.Time.Unix()),
|
||||||
|
}
|
||||||
|
if basket.UpdatedAt.Time.Unix() > 0 {
|
||||||
|
res.UpdatedAt = time.Duration(basket.UpdatedAt.Time.Unix())
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetBasketItemsHandler(c *fiber.Ctx) error {
|
||||||
|
basketID := c.Params("basketId", "")
|
||||||
|
basketSrv := service.NewBasketService(s.db, s.cache, s.ebCh, s.log)
|
||||||
|
ctx := context.Background()
|
||||||
|
items, err := basketSrv.FetchItems(ctx, basketID)
|
||||||
|
if err != nil {
|
||||||
|
return s.Error400(c, "Failed to retrieve basket items")
|
||||||
|
}
|
||||||
|
|
||||||
|
var res []*def.GetBasketItemsResponse // FIXME
|
||||||
|
for _, item := range items {
|
||||||
|
resItem := &def.GetBasketItemsResponse{
|
||||||
|
ID: item.ID,
|
||||||
|
BasketID: item.BasketID,
|
||||||
|
ProductID: item.ProductID,
|
||||||
|
Quantity: item.Quantity,
|
||||||
|
Price: item.Price,
|
||||||
|
CreatedAt: time.Duration(item.CreatedAt.Time.Unix()),
|
||||||
|
}
|
||||||
|
if item.UpdatedAt.Time.Unix() > 0 {
|
||||||
|
resItem.UpdatedAt = time.Duration(item.UpdatedAt.Time.Unix())
|
||||||
|
}
|
||||||
|
res = append(res, resItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) CheckoutHandler(c *fiber.Ctx) error {
|
||||||
|
reqID, _ := s.GetRequestID(c)
|
||||||
|
req := new(def.BasketCheckoutRequest)
|
||||||
|
if err := c.BodyParser(req); err != nil {
|
||||||
|
return s.Error400(c, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
basketID := req.BasketID
|
||||||
|
basketSrv := service.NewBasketService(s.db, s.cache, s.ebCh, s.log)
|
||||||
|
res, err := ui.CheckoutBasket(basketSrv, basketID, reqID)
|
||||||
|
if err != nil {
|
||||||
|
return s.Error400(c, "Failed to create order")
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.JSON(res)
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ type Config struct {
|
|||||||
AppID string
|
AppID string
|
||||||
AppName string
|
AppName string
|
||||||
AppDomain string
|
AppDomain string
|
||||||
|
PathPrefix string
|
||||||
NetAddr string
|
NetAddr string
|
||||||
Port int
|
Port int
|
||||||
RegistryAddr string
|
RegistryAddr string
|
||||||
@ -13,6 +14,8 @@ type Config struct {
|
|||||||
|
|
||||||
LoggerAddr string `json:"logger_addr"`
|
LoggerAddr string `json:"logger_addr"`
|
||||||
DbURL string `json:"db_url"`
|
DbURL string `json:"db_url"`
|
||||||
|
CacheAddr string `json:"cache_addr"`
|
||||||
|
CachePassword string `json:"cache_password"`
|
||||||
MongoDbUrl string `json:"mongodb_url"`
|
MongoDbUrl string `json:"mongodb_url"`
|
||||||
EventBusURL string `json:"eventbus_url"`
|
EventBusURL string `json:"eventbus_url"`
|
||||||
EventBusExchange string `json:"eventbus_exchange"`
|
EventBusExchange string `json:"eventbus_exchange"`
|
||||||
|
@ -3,7 +3,7 @@ package server
|
|||||||
import (
|
import (
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
def "git.pbiernat.dev/egommerce/basket-service/internal/app/definition"
|
def "git.pbiernat.dev/egommerce/api-entities/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) HealthHandler(c *fiber.Ctx) error {
|
func (s *Server) HealthHandler(c *fiber.Ctx) error {
|
||||||
|
@ -1,25 +1,50 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultCORS = cors.New(cors.Config{
|
||||||
|
AllowOrigins: "*",
|
||||||
|
AllowCredentials: true,
|
||||||
|
AllowMethods: "GET, POST, PATCH, PUT, DELETE, OPTIONS",
|
||||||
|
AllowHeaders: "Accept, Authorization, Content-Type, Vary, X-Request-Id",
|
||||||
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
func SetupRoutes(s *Server) {
|
func SetupRoutes(s *Server) {
|
||||||
|
s.App.Options("*", defaultCORS)
|
||||||
|
|
||||||
s.App.Get("/health", s.HealthHandler)
|
s.App.Get("/health", s.HealthHandler)
|
||||||
s.App.Get("/config", s.ConfigHandler)
|
s.App.Get("/config", s.ConfigHandler)
|
||||||
|
|
||||||
api := s.App.Group("/api")
|
api := s.App.Group("/api")
|
||||||
v1 := api.Group("/v1")
|
v1 := api.Group("/v1")
|
||||||
|
v1.Get("/basket", s.GetBasketHandler)
|
||||||
|
v1.Get("/basket/:basketId/items", s.GetBasketItemsHandler)
|
||||||
v1.Post("/checkout", s.CheckoutHandler)
|
v1.Post("/checkout", s.CheckoutHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupMiddlewares(s *Server) {
|
func SetupMiddlewares(s *Server) {
|
||||||
|
s.App.Use(defaultCORS)
|
||||||
s.App.Use(LoggingMiddleware(s.log))
|
s.App.Use(LoggingMiddleware(s.log))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CORSPreflightMiddleware(c *fiber.Ctx) error {
|
||||||
|
if string(c.Request().Header.Method()) == http.MethodOptions {
|
||||||
|
c.Response().SetStatusCode(http.StatusOK)
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
// Middlewares
|
// Middlewares
|
||||||
func LoggingMiddleware(log *fluentd.Logger) func(c *fiber.Ctx) error {
|
func LoggingMiddleware(log *fluentd.Logger) func(c *fiber.Ctx) error {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
|
@ -2,18 +2,19 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
"github.com/streadway/amqp"
|
"github.com/streadway/amqp"
|
||||||
|
|
||||||
|
def "git.pbiernat.dev/egommerce/api-entities/http"
|
||||||
discovery "git.pbiernat.dev/egommerce/go-api-pkg/consul"
|
discovery "git.pbiernat.dev/egommerce/go-api-pkg/consul"
|
||||||
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
|
||||||
)
|
)
|
||||||
@ -23,6 +24,7 @@ type Server struct {
|
|||||||
conf *Config
|
conf *Config
|
||||||
log *fluentd.Logger
|
log *fluentd.Logger
|
||||||
db *pgxpool.Pool
|
db *pgxpool.Pool
|
||||||
|
cache *redis.Client
|
||||||
ebCh *amqp.Channel
|
ebCh *amqp.Channel
|
||||||
discovery *discovery.Service
|
discovery *discovery.Service
|
||||||
name string
|
name string
|
||||||
@ -34,9 +36,8 @@ type Headers struct {
|
|||||||
RequestID string `reqHeader:"x-request-id"`
|
RequestID string `reqHeader:"x-request-id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer(conf *Config, logger *fluentd.Logger, db *pgxpool.Pool, ebCh *amqp.Channel) *Server {
|
func NewServer(conf *Config, logger *fluentd.Logger, db *pgxpool.Pool, cache *redis.Client, ebCh *amqp.Channel) *Server {
|
||||||
logger.Log("API_ID: %s", conf.AppID)
|
consul, err := discovery.NewService(conf.RegistryAddr, conf.AppID, conf.AppName, conf.AppID, conf.AppDomain, conf.PathPrefix, conf.Port)
|
||||||
consul, err := discovery.NewService(conf.RegistryAddr, conf.AppID, conf.AppName, conf.AppID, conf.AppDomain, conf.Port)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log("Error connecting to %s: %v", conf.RegistryAddr, err)
|
logger.Log("Error connecting to %s: %v", conf.RegistryAddr, err)
|
||||||
}
|
}
|
||||||
@ -59,6 +60,7 @@ func NewServer(conf *Config, logger *fluentd.Logger, db *pgxpool.Pool, ebCh *amq
|
|||||||
conf,
|
conf,
|
||||||
logger,
|
logger,
|
||||||
db,
|
db,
|
||||||
|
cache,
|
||||||
ebCh,
|
ebCh,
|
||||||
consul,
|
consul,
|
||||||
conf.AppName,
|
conf.AppName,
|
||||||
@ -66,14 +68,22 @@ func NewServer(conf *Config, logger *fluentd.Logger, db *pgxpool.Pool, ebCh *amq
|
|||||||
conf.KVNamespace,
|
conf.KVNamespace,
|
||||||
}
|
}
|
||||||
|
|
||||||
go func(s *Server) { // Consul KV config updater
|
go func(s *Server) { // Consul KV updater
|
||||||
interval := time.Second * 30
|
interval := time.Second * 15
|
||||||
ticker := time.NewTicker(interval)
|
ticker := time.NewTicker(interval)
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
s.updateKVConfig()
|
s.updateKVConfig()
|
||||||
}
|
}
|
||||||
}(s)
|
}(s)
|
||||||
|
|
||||||
|
go func(s *Server) { // Server metadata cache updater
|
||||||
|
interval := time.Second * 5
|
||||||
|
ticker := time.NewTicker(interval)
|
||||||
|
for range ticker.C {
|
||||||
|
s.cacheMetadata()
|
||||||
|
}
|
||||||
|
}(s)
|
||||||
|
|
||||||
SetupMiddlewares(s)
|
SetupMiddlewares(s)
|
||||||
SetupRoutes(s)
|
SetupRoutes(s)
|
||||||
|
|
||||||
@ -114,31 +124,51 @@ func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
|
|||||||
return hdr.RequestID, nil
|
return hdr.RequestID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) updateKVConfig() error { // FIXME: duplicated in cmd/worker/main.go
|
func (s *Server) Error400(c *fiber.Ctx, msg string) error {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(&def.ErrorResponse{Error: msg})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Error404(c *fiber.Ctx, msg string) error {
|
||||||
|
return c.Status(fiber.StatusNotFound).JSON(&def.ErrorResponse{Error: msg})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) updateKVConfig() { // FIXME: duplicated in cmd/worker/main.go
|
||||||
config, _, err := s.discovery.KV().Get(s.kvNmspc, nil)
|
config, _, err := s.discovery.KV().Get(s.kvNmspc, nil)
|
||||||
if err != nil {
|
if err != nil || config == nil {
|
||||||
fmt.Println(err)
|
return
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if config == nil {
|
|
||||||
return errors.New("empty KV config data")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kvCnf := bytes.NewBuffer(config.Value)
|
kvCnf := bytes.NewBuffer(config.Value)
|
||||||
decoder := json.NewDecoder(kvCnf)
|
decoder := json.NewDecoder(kvCnf)
|
||||||
if err := decoder.Decode(&s.conf); err != nil {
|
if err := decoder.Decode(&s.conf); err != nil {
|
||||||
return err
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) cacheMetadata() {
|
||||||
|
ctx := context.Background()
|
||||||
|
key, address := "internal__"+s.conf.AppName+"__ips", s.conf.AppID // FIXME: key name
|
||||||
|
|
||||||
|
pos := s.cache.LPos(ctx, key, address, redis.LPosArgs{}).Val()
|
||||||
|
if pos >= 0 {
|
||||||
|
s.cache.LRem(ctx, key, 0, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
s.cache.LPush(ctx, key, address).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) clearMetadataCache() {
|
||||||
|
ctx := context.Background()
|
||||||
|
key, address := "internal__"+s.conf.AppName+"__ips", s.conf.AppID // FIXME: key name
|
||||||
|
|
||||||
|
s.cache.LRem(ctx, key, 0, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) gracefulShutdown() error {
|
func (s *Server) gracefulShutdown() error {
|
||||||
s.log.Log("Server is going down...")
|
s.log.Log("Server is going down...")
|
||||||
s.log.Log("Unregistering service: %s", s.discovery.GetID())
|
s.log.Log("Unregistering service: %s", s.discovery.GetID())
|
||||||
s.discovery.Unregister()
|
s.discovery.Unregister()
|
||||||
|
s.clearMetadataCache()
|
||||||
|
|
||||||
s.ebCh.Close()
|
s.ebCh.Close()
|
||||||
s.db.Close()
|
s.db.Close()
|
||||||
|
@ -3,41 +3,48 @@ package service
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
def "git.pbiernat.dev/egommerce/basket-service/internal/app/definition"
|
"git.pbiernat.dev/egommerce/api-entities/model"
|
||||||
"git.pbiernat.dev/egommerce/basket-service/internal/app/event"
|
"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/fluentd"
|
||||||
amqp "git.pbiernat.dev/egommerce/go-api-pkg/rabbitmq"
|
"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/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
base "github.com/streadway/amqp"
|
"github.com/streadway/amqp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SERVICE_USER_AGENT = "basket-httpclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BasketService struct {
|
type BasketService struct {
|
||||||
dbConn *pgxpool.Pool
|
dbConn *pgxpool.Pool
|
||||||
ebCh *base.Channel
|
redis *redis.Client
|
||||||
|
ebCh *amqp.Channel
|
||||||
log *fluentd.Logger
|
log *fluentd.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBasketService(dbConn *pgxpool.Pool, chn *base.Channel, log *fluentd.Logger) *BasketService {
|
func NewBasketService(dbConn *pgxpool.Pool, redis *redis.Client, chn *amqp.Channel, log *fluentd.Logger) *BasketService {
|
||||||
return &BasketService{dbConn, chn, log}
|
return &BasketService{dbConn, redis, chn, log}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BasketService) Create(basketID string) (*def.BasketModel, error) {
|
func (s *BasketService) Log(format string, val ...any) {
|
||||||
ctx := context.Background()
|
s.log.Log(format, val...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BasketService) CreateBasket(ctx context.Context, basketID string) (*model.BasketModel, error) {
|
||||||
sql := `INSERT INTO basket.basket(id) VALUES($1)`
|
sql := `INSERT INTO basket.basket(id) VALUES($1)`
|
||||||
if _, err := s.dbConn.Exec(ctx, sql, basketID); err != nil {
|
if _, err := s.dbConn.Exec(ctx, sql, basketID); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &def.BasketModel{ID: basketID}, nil // FIXME - WTF is that xD??
|
return &model.BasketModel{ID: basketID}, nil // FIXME
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BasketService) FetchFromDB(basketID string) (*def.BasketModel, error) {
|
func (s *BasketService) FetchFromDB(ctx context.Context, basketID string) (*model.BasketModel, error) {
|
||||||
ctx := context.Background()
|
basket := new(model.BasketModel)
|
||||||
|
err := pgxscan.Get(ctx, s.dbConn, basket, `SELECT id,state,created_at,updated_at FROM basket.basket WHERE id=$1 LIMIT 1`, basketID)
|
||||||
basket := new(def.BasketModel)
|
|
||||||
err := pgxscan.Get(ctx, s.dbConn, basket, `SELECT id, created_at, updated_at FROM basket.basket WHERE id=$1`, basketID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -45,12 +52,71 @@ func (s *BasketService) FetchFromDB(basketID string) (*def.BasketModel, error) {
|
|||||||
return basket, nil
|
return basket, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *BasketService) AddProduct(productId, basketID string, qty int) error {
|
func (s *BasketService) FetchItems(ctx context.Context, basketID string) ([]*model.BasketItemModel, error) {
|
||||||
ctx := context.Background()
|
items := []*model.BasketItemModel{}
|
||||||
s.log.Log("Adding product#:%s into Basket#:%s", productId, basketID)
|
sql := `SELECT id,basket_id,product_id,quantity,price,created_at FROM basket.basket_item WHERE basket_id=$1`
|
||||||
|
rows, err := s.dbConn.Query(ctx, sql, basketID)
|
||||||
|
if err != nil {
|
||||||
|
// s.Log("Fetch basket items error: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
sql := `INSERT INTO basket.basket_item(basket_id, product_id) VALUES($1,$2)`
|
if err := pgxscan.ScanAll(&items, rows); err != nil {
|
||||||
if _, err := s.dbConn.Exec(ctx, sql, basketID, productId); err != nil {
|
// s.Log("Fetch basket items error: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BasketService) FetchItem(ctx context.Context, basketID string, productID int) (*model.BasketItemModel, error) {
|
||||||
|
item := new(model.BasketItemModel)
|
||||||
|
sql := `SELECT id,basket_id,product_id,quantity,price,created_at FROM basket.basket_item WHERE basket_id=$1 AND product_id=$2 LIMIT 1`
|
||||||
|
err := pgxscan.Get(ctx, s.dbConn, item, sql, basketID, productID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return item, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BasketService) AddItem(ctx context.Context, itemID int, basketID string, qty int) error {
|
||||||
|
var price float64 = 0
|
||||||
|
pricingAPI := api.NewPricingAPI(SERVICE_USER_AGENT, s.redis)
|
||||||
|
|
||||||
|
productPrice, err := pricingAPI.GetProductPrice(itemID)
|
||||||
|
if err == nil {
|
||||||
|
price = productPrice.Price
|
||||||
|
}
|
||||||
|
|
||||||
|
sql := `INSERT INTO basket.basket_item(basket_id,product_id,price,quantity) VALUES($1,$2,$3,$4)`
|
||||||
|
if _, err := s.dbConn.Exec(ctx, sql, basketID, itemID, price, qty); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BasketService) RemoveItem(ctx context.Context, itemID int, basketID string) error {
|
||||||
|
sql := `DELETE FROM basket.basket_item WHERE basket_id=$1 AND product_id=$2`
|
||||||
|
if _, err := s.dbConn.Exec(ctx, sql, basketID, itemID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BasketService) UpdateItem(ctx context.Context, item *model.BasketItemModel, qty int) error {
|
||||||
|
var price float64 = 0
|
||||||
|
pricingAPI := api.NewPricingAPI(SERVICE_USER_AGENT, s.redis)
|
||||||
|
|
||||||
|
productPrice, err := pricingAPI.GetProductPrice(item.ProductID)
|
||||||
|
if err == nil {
|
||||||
|
price = productPrice.Price
|
||||||
|
}
|
||||||
|
|
||||||
|
sql := `UPDATE basket.basket_item SET quantity=$1, price=$2 WHERE basket_id=$3 AND product_id=$4`
|
||||||
|
if _, err := s.dbConn.Exec(ctx, sql, qty, price, item.BasketID, item.ProductID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +126,8 @@ func (s *BasketService) AddProduct(productId, basketID string, qty int) error {
|
|||||||
func (s *BasketService) Checkout(reqID, basketID string) (string, error) {
|
func (s *BasketService) Checkout(reqID, basketID string) (string, error) {
|
||||||
s.log.Log("Creating initial order from basket#:%s", basketID)
|
s.log.Log("Creating initial order from basket#:%s", basketID)
|
||||||
|
|
||||||
msg := &event.BasketCheckoutEvent{Event: event.NewEvent(reqID), BasketID: basketID}
|
msg := &event.BasketCheckoutEvent{Event: event.NewEvent(reqID), BasketID: basketID} // FIXME: send more info...
|
||||||
amqp.Publish(s.ebCh, "api-events", "basket.order.basketCheckout", msg)
|
rabbitmq.Publish(s.ebCh, "api-events", "basket.order.basketCheckout", msg)
|
||||||
|
|
||||||
return basketID, nil
|
return basketID, nil
|
||||||
}
|
}
|
||||||
|
88
src/internal/app/ui/basket.go
Normal file
88
src/internal/app/ui/basket.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
def "git.pbiernat.dev/egommerce/api-entities/http"
|
||||||
|
"git.pbiernat.dev/egommerce/api-entities/model"
|
||||||
|
"git.pbiernat.dev/egommerce/basket-service/internal/app/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AddProductToBasket(srv *service.BasketService, productID, qty int, basketID, reqID string) (*model.BasketModel, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
basket, err := srv.FetchFromDB(ctx, basketID)
|
||||||
|
if err != nil {
|
||||||
|
srv.Log("Basket#:%s not found. Creating new one...", basketID)
|
||||||
|
basket, err = srv.CreateBasket(ctx, basketID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Done() // FIXME
|
||||||
|
srv.Log("Creating basket error: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
item, err := srv.FetchItem(ctx, basket.ID, productID)
|
||||||
|
if err != nil {
|
||||||
|
err := srv.AddItem(ctx, productID, basket.ID, qty)
|
||||||
|
ctx.Done() // FIXME
|
||||||
|
if err != nil {
|
||||||
|
srv.Log("Error adding product to basket: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return basket, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
qty = item.Quantity + qty
|
||||||
|
err = srv.UpdateItem(ctx, item, qty)
|
||||||
|
if err != nil {
|
||||||
|
srv.Log("UpdateItem error: %v", err)
|
||||||
|
}
|
||||||
|
ctx.Done() // FIXME
|
||||||
|
|
||||||
|
return basket, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveProductFromBasket(srv *service.BasketService, productID, qty int, basketID, reqID string) (*model.BasketModel, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
basket, err := srv.FetchFromDB(ctx, basketID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Done() // FIXME
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
item, err := srv.FetchItem(ctx, basket.ID, productID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Done() // FIXME
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.Quantity <= qty {
|
||||||
|
err = srv.RemoveItem(ctx, item.ProductID, item.BasketID)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Done() // FIXME
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qty = item.Quantity - qty
|
||||||
|
err = srv.UpdateItem(ctx, item, qty)
|
||||||
|
if err != nil {
|
||||||
|
srv.Log("UpdateItem error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.Done() // FIXME
|
||||||
|
|
||||||
|
return basket, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckoutBasket(srv *service.BasketService, basketID, reqID string) (*def.BasketCheckoutResponse, error) {
|
||||||
|
// ctx := context.Background()
|
||||||
|
res := &def.BasketCheckoutResponse{}
|
||||||
|
basketID, err := srv.Checkout(reqID, basketID)
|
||||||
|
if err != nil {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
res.ID = basketID
|
||||||
|
// ctx.Done() // FIXME
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user