Huge refactoring
This commit is contained in:
parent
b276fa9e81
commit
0151c19e8f
@ -1,13 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
cnf "git.pbiernat.io/egommerce/go-api-pkg/config"
|
cnf "git.pbiernat.io/egommerce/go-api-pkg/config"
|
||||||
|
|
||||||
"git.pbiernat.io/egommerce/catalog-service/internal/app"
|
"git.pbiernat.io/egommerce/catalog-service/internal/app"
|
||||||
"git.pbiernat.io/egommerce/catalog-service/internal/config"
|
|
||||||
"git.pbiernat.io/egommerce/catalog-service/internal/server"
|
"git.pbiernat.io/egommerce/catalog-service/internal/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,24 +16,26 @@ func main() {
|
|||||||
log.Panicln("Error loading .env file", cnf.ErrLoadingEnvs)
|
log.Panicln("Error loading .env file", cnf.ErrLoadingEnvs)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := config.NewServerConfig("catalog")
|
c := server.NewConfig("catalog")
|
||||||
srv := server.New(c)
|
cArr := c.GetArray()
|
||||||
app := app.NewApp(c, srv)
|
|
||||||
|
|
||||||
app.RegisterHelper("cache", app.WithCache())
|
doer := server.New(c)
|
||||||
app.RegisterHelper("database", app.WithDatabase())
|
a := app.NewApp(doer)
|
||||||
app.RegisterHelper("eventbus", app.WithEventbus())
|
a.RegisterPlugin(app.LoggerPlugin(cArr))
|
||||||
app.RegisterHelper("logger", app.WithLogger())
|
a.RegisterPlugin(app.CachePlugin(cArr))
|
||||||
app.RegisterHelper("registry", app.WithRegistry())
|
a.RegisterPlugin(app.DatabasePlugin(cArr))
|
||||||
|
a.RegisterPlugin(app.EventbusPlugin(cArr))
|
||||||
|
a.RegisterPlugin(app.RegistryPlugin(cArr))
|
||||||
|
|
||||||
while := make(chan struct{})
|
while := make(chan struct{})
|
||||||
err := app.Start(while)
|
err := a.Start(while)
|
||||||
<-while
|
<-while
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to start application. Reason: %v\n", err)
|
log.Fatalf("Failed to start server. Reason: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Gone")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,33 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
// "git.pbiernat.io/egommerce/go-api-pkg/config"
|
cnf "git.pbiernat.io/egommerce/go-api-pkg/config"
|
||||||
|
|
||||||
|
"git.pbiernat.io/egommerce/catalog-service/internal/app"
|
||||||
"git.pbiernat.io/egommerce/catalog-service/internal/worker"
|
"git.pbiernat.io/egommerce/catalog-service/internal/worker"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// if config.ErrLoadingEnvs != nil {
|
if cnf.ErrLoadingEnvs != nil {
|
||||||
// log.Fatalln("Error loading .env file.")
|
log.Fatalln("Error loading .env file.")
|
||||||
// }
|
}
|
||||||
|
|
||||||
c := cnf.NewConfig("catalog-worker")
|
c := worker.NewConfig("catalog-worker")
|
||||||
wrk := worker.New(
|
cArr := c.GetArray()
|
||||||
c,
|
|
||||||
worker.WithCache(c),
|
doer := worker.New(c)
|
||||||
worker.WithDatabase(c),
|
a := app.NewApp(doer)
|
||||||
worker.WithEventbus(c),
|
a.RegisterPlugin(app.LoggerPlugin(cArr))
|
||||||
worker.WithLogger(c),
|
a.RegisterPlugin(app.CachePlugin(cArr))
|
||||||
)
|
a.RegisterPlugin(app.DatabasePlugin(cArr))
|
||||||
|
a.RegisterPlugin(app.EventbusPlugin(cArr))
|
||||||
|
|
||||||
while := make(chan struct{})
|
while := make(chan struct{})
|
||||||
err := wrk.Start(while)
|
err := a.Start(while)
|
||||||
<-while
|
<-while
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -31,5 +35,6 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Gone")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ go 1.18
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
git.pbiernat.io/egommerce/api-entities v0.2.3
|
git.pbiernat.io/egommerce/api-entities v0.2.3
|
||||||
git.pbiernat.io/egommerce/go-api-pkg v0.2.72
|
git.pbiernat.io/egommerce/go-api-pkg v0.2.88
|
||||||
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.11.1
|
github.com/go-pg/pg/v10 v10.11.1
|
||||||
|
@ -37,8 +37,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
|||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.pbiernat.io/egommerce/api-entities v0.2.3 h1:mR6EYfZkAzh4teydb7KXDBWoxwVW3qasnmmH5J3mnas=
|
git.pbiernat.io/egommerce/api-entities v0.2.3 h1:mR6EYfZkAzh4teydb7KXDBWoxwVW3qasnmmH5J3mnas=
|
||||||
git.pbiernat.io/egommerce/api-entities v0.2.3/go.mod h1:INXAG5x4+i+vNwg1NpfPHiDW8nY1kn1K7pgLOtX+/I0=
|
git.pbiernat.io/egommerce/api-entities v0.2.3/go.mod h1:INXAG5x4+i+vNwg1NpfPHiDW8nY1kn1K7pgLOtX+/I0=
|
||||||
git.pbiernat.io/egommerce/go-api-pkg v0.2.72 h1:289HdYxa5ZzKEirxZfat1i6B7jThvZwtvO3SZykFTcg=
|
git.pbiernat.io/egommerce/go-api-pkg v0.2.88 h1:xya/39BnFeha3Oc76ad/ppoQd6AstTGQd87Qszamr1A=
|
||||||
git.pbiernat.io/egommerce/go-api-pkg v0.2.72/go.mod h1:XIy2mmvRNIzQmYIUAcDZafhRPxTQFS2HDmsK7ZQ6980=
|
git.pbiernat.io/egommerce/go-api-pkg v0.2.88/go.mod h1:XIy2mmvRNIzQmYIUAcDZafhRPxTQFS2HDmsK7ZQ6980=
|
||||||
github.com/Azure/azure-sdk-for-go v44.0.0+incompatible h1:e82Yv2HNpS0kuyeCrV29OPKvEiqfs2/uJHic3/3iKdg=
|
github.com/Azure/azure-sdk-for-go v44.0.0+incompatible h1:e82Yv2HNpS0kuyeCrV29OPKvEiqfs2/uJHic3/3iKdg=
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
|
||||||
github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
|
github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
|
||||||
|
@ -6,64 +6,29 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
redis "github.com/go-redis/redis/v8"
|
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
|
||||||
amqp "github.com/rabbitmq/amqp091-go"
|
|
||||||
|
|
||||||
"git.pbiernat.io/egommerce/go-api-pkg/consul"
|
|
||||||
"git.pbiernat.io/egommerce/go-api-pkg/fluentd"
|
|
||||||
|
|
||||||
cnf "git.pbiernat.io/egommerce/catalog-service/internal/config"
|
|
||||||
srv "git.pbiernat.io/egommerce/catalog-service/internal/server"
|
|
||||||
db "git.pbiernat.io/egommerce/catalog-service/pkg/database"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Doer interface {
|
Doer interface {
|
||||||
Start(while chan struct{}) error
|
Start() error
|
||||||
OnShutdown(*App)
|
RegisterHandler(string, func() any)
|
||||||
|
OnShutdown()
|
||||||
}
|
}
|
||||||
Application interface {
|
Application interface {
|
||||||
Start(while chan struct{})
|
Start(while chan struct{})
|
||||||
RegisterHelper(OptionFn) error
|
RegisterPlugin(PluginFn) error
|
||||||
Shutdown()
|
Shutdown()
|
||||||
}
|
}
|
||||||
OptionFn func(*App) error
|
|
||||||
|
|
||||||
App struct {
|
App struct {
|
||||||
cnf *srv.ServerConfig
|
|
||||||
|
|
||||||
doer Doer
|
doer Doer
|
||||||
|
|
||||||
// helpers
|
|
||||||
Cache *redis.Client
|
|
||||||
Database *pgxpool.Pool
|
|
||||||
Eventbus *amqp.Channel
|
|
||||||
Logger *fluentd.Logger
|
|
||||||
Registry *consul.Service
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewApp(c *cnf.ServerConfig, d Doer) *App {
|
func NewApp(d Doer) *App {
|
||||||
app := &App{
|
return &App{
|
||||||
cnf: c,
|
|
||||||
doer: d,
|
doer: d,
|
||||||
}
|
}
|
||||||
|
|
||||||
// while := make(chan struct{})
|
|
||||||
// // err := srv.Base.Start(while)
|
|
||||||
// err := app.Doer.Start(while)
|
|
||||||
// <-while
|
|
||||||
|
|
||||||
// if err != nil {
|
|
||||||
// log.Fatalf("Failed to start application. Reason: %v\n", err)
|
|
||||||
// os.Exit(1)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// os.Exit(0)
|
|
||||||
|
|
||||||
return app
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) Start(while chan struct{}) error {
|
func (a *App) Start(while chan struct{}) error {
|
||||||
@ -72,7 +37,6 @@ func (a *App) Start(while chan struct{}) error {
|
|||||||
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
<-sigint
|
<-sigint
|
||||||
|
|
||||||
a.doer.OnShutdown(a)
|
|
||||||
a.Shutdown()
|
a.Shutdown()
|
||||||
|
|
||||||
close(while)
|
close(while)
|
||||||
@ -81,17 +45,24 @@ func (a *App) Start(while chan struct{}) error {
|
|||||||
run := a.createRunFile("./app.run") // FIXME path...
|
run := a.createRunFile("./app.run") // FIXME path...
|
||||||
defer a.removeRunFile(run)
|
defer a.removeRunFile(run)
|
||||||
|
|
||||||
a.doer.Start(while)
|
err := a.doer.Start()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to start app. Reason: %v\n", err)
|
||||||
|
close(while)
|
||||||
|
}
|
||||||
|
<-while
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) RegisterHelper(name string, opt OptionFn) error {
|
func (a *App) RegisterPlugin(p Plugin) error {
|
||||||
if err := opt(a); err != nil {
|
a.doer.RegisterHandler(p.name, p.fn)
|
||||||
log.Fatalf("Failed to attach extension to the server. Err: %v\n", err)
|
|
||||||
}
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) Shutdown() {
|
func (a *App) Shutdown() {
|
||||||
// ...
|
a.doer.OnShutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) createRunFile(path string) *os.File {
|
func (a *App) createRunFile(path string) *os.File {
|
||||||
@ -108,108 +79,3 @@ func (a *App) createRunFile(path string) *os.File {
|
|||||||
func (a *App) removeRunFile(f *os.File) error {
|
func (a *App) removeRunFile(f *os.File) error {
|
||||||
return f.Close()
|
return f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func WithCache() OptionFn {
|
|
||||||
return func(a *App) error {
|
|
||||||
a.Cache = redis.NewClient(&redis.Options{
|
|
||||||
Addr: a.cnf.CacheAddr,
|
|
||||||
Password: a.cnf.CachePassword,
|
|
||||||
DB: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithDatabase() OptionFn {
|
|
||||||
return func(a *App) error {
|
|
||||||
dbConn, err := db.Connect(a.cnf.DbURL)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to the Database: %s. Err: %v\n", a.cnf.DbURL, err)
|
|
||||||
os.Exit(1) // TODO: retry in background... for now treat as integraded service...
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Database = dbConn
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithEventbus() OptionFn {
|
|
||||||
return func(a *App) error {
|
|
||||||
conn, err := amqp.Dial(a.cnf.EventBusURL)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to the Eventbus: %s. Err: %v\n", a.cnf.EventBusURL, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
chn, err := conn.Channel()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to open new Eventbus channel. Err: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Eventbus = chn
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithLogger() OptionFn {
|
|
||||||
return func(a *App) error {
|
|
||||||
logHost, logPort, err := fluentd.ParseAddr(a.cnf.LoggerAddr)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to parse Fluentd address: %s. Err: %v", a.cnf.LoggerAddr, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
logger, err := fluentd.NewLogger(a.cnf.Base.GetAppFullName(), logHost, logPort)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to connect to the Fluentd on %s:%d. Err: %v", logHost, logPort, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
a.Logger = logger
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func WithRegistry() OptionFn {
|
|
||||||
return func(a *App) error {
|
|
||||||
port, _ := strconv.Atoi(a.cnf.Base.NetAddr[1:]) // FIXME: can be IP:PORT or :PORT
|
|
||||||
// log.Printf("Consul retrieved port: %v", port)
|
|
||||||
registry, err := consul.NewService(a.cnf.RegistryAddr, a.cnf.Base.AppID, a.cnf.Base.AppName, a.cnf.Base.RegistryDomainOverIP, a.cnf.Base.GetIP(), a.cnf.Base.AppDomain, a.cnf.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)
|
|
||||||
}
|
|
||||||
|
|
||||||
registry.RegisterHealthChecks()
|
|
||||||
// a.registerKVUpdater() // FIXME run as goroutine
|
|
||||||
|
|
||||||
a.Registry = registry
|
|
||||||
|
|
||||||
// svc, _ := registry.Connect()
|
|
||||||
// tlsCnf := svc.ServerTLSConfig()
|
|
||||||
// s.Base.App.Server().TLSConfig = tlsCnf
|
|
||||||
// fmt.Println("Podmiana configa TLS")
|
|
||||||
// defer svc.Close()
|
|
||||||
|
|
||||||
// go func() { // Consul KV updater
|
|
||||||
// ticker := time.NewTicker(time.Second * 15)
|
|
||||||
// for range ticker.C {
|
|
||||||
// fetchKVConfig(s) // FIXME: duplicated in worker
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
|
|
||||||
// go func() { // Server metadata cache updater
|
|
||||||
// ticker := time.NewTicker(time.Second * 5)
|
|
||||||
// for range ticker.C {
|
|
||||||
// s.cacheMetadata()
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
139
src/internal/app/plugins.go
Normal file
139
src/internal/app/plugins.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
redis "github.com/go-redis/redis/v8"
|
||||||
|
amqp "github.com/rabbitmq/amqp091-go"
|
||||||
|
|
||||||
|
"git.pbiernat.io/egommerce/go-api-pkg/consul"
|
||||||
|
"git.pbiernat.io/egommerce/go-api-pkg/fluentd"
|
||||||
|
|
||||||
|
db "git.pbiernat.io/egommerce/catalog-service/pkg/database"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Plugin struct {
|
||||||
|
name string
|
||||||
|
fn PluginFn
|
||||||
|
}
|
||||||
|
PluginFn func() any
|
||||||
|
)
|
||||||
|
|
||||||
|
func CachePlugin(cArr map[string]string) Plugin {
|
||||||
|
return Plugin{
|
||||||
|
name: "cache",
|
||||||
|
fn: func() any {
|
||||||
|
return redis.NewClient(&redis.Options{
|
||||||
|
Addr: cArr["cacheAddr"],
|
||||||
|
Password: cArr["cachePassword"],
|
||||||
|
DB: 0,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DatabasePlugin(cArr map[string]string) Plugin {
|
||||||
|
return Plugin{
|
||||||
|
name: "database",
|
||||||
|
fn: func() any {
|
||||||
|
dbConn, err := db.Connect(cArr["dbURL"])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to connect to the Database: %s. Err: %v\n", cArr["dbURL"], err)
|
||||||
|
os.Exit(1) // TODO: retry in background...
|
||||||
|
}
|
||||||
|
|
||||||
|
return dbConn
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func EventbusPlugin(cArr map[string]string) Plugin {
|
||||||
|
return Plugin{
|
||||||
|
name: "eventbus",
|
||||||
|
fn: func() any {
|
||||||
|
conn, err := amqp.Dial(cArr["eventBusURL"])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to connect to the EventBus: %s. Err: %v\n", cArr["eventBusURL"], err)
|
||||||
|
os.Exit(1) // TODO: retry in background...
|
||||||
|
}
|
||||||
|
|
||||||
|
chn, err := conn.Channel()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to open new EventBus channel. Err: %v\n", err)
|
||||||
|
os.Exit(1) // TODO: retry in background...
|
||||||
|
}
|
||||||
|
|
||||||
|
return chn
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoggerPlugin(cArr map[string]string) Plugin {
|
||||||
|
return Plugin{
|
||||||
|
name: "logger",
|
||||||
|
fn: func() any {
|
||||||
|
logHost, logPort, err := fluentd.ParseAddr(cArr["loggerAddr"])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to parse FluentD address: %s. Err: %v", cArr["loggerAddr"], err)
|
||||||
|
os.Exit(1) // TODO: retry in background...
|
||||||
|
}
|
||||||
|
|
||||||
|
logger, err := fluentd.NewLogger(cArr["appFullname"], logHost, logPort)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to connect to the FluentD on %s:%d. Err: %v", logHost, logPort, err)
|
||||||
|
os.Exit(1) // TODO: retry in background...
|
||||||
|
}
|
||||||
|
|
||||||
|
return logger
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegistryPlugin(cArr map[string]string) Plugin {
|
||||||
|
return Plugin{
|
||||||
|
name: "registry",
|
||||||
|
fn: func() any {
|
||||||
|
port, _ := strconv.Atoi(cArr["netAddr"][1:]) // FIXME: can be IP:PORT or :PORT
|
||||||
|
// log.Printf("Consul retrieved port: %v", port)
|
||||||
|
registry, err := consul.NewService(cArr["registryAddr"], cArr["id"], cArr["name"], cArr["registryDomainOverIP"], cArr["ip"], cArr["domain"], cArr["pathPrefix"], port)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to connect to the Consul on: %s. Err: %v", cArr["registryAddr"], err)
|
||||||
|
os.Exit(1) // TODO: retry in background...
|
||||||
|
}
|
||||||
|
|
||||||
|
err = registry.Register()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to register in the Consul service. Err: %v", err)
|
||||||
|
os.Exit(1) // TODO: retry in background...
|
||||||
|
}
|
||||||
|
|
||||||
|
registry.RegisterHealthChecks()
|
||||||
|
// a.registerKVUpdater() // FIXME run as goroutine
|
||||||
|
|
||||||
|
return registry
|
||||||
|
|
||||||
|
// svc, _ := registry.Connect()
|
||||||
|
// tlsCnf := svc.ServerTLSConfig()
|
||||||
|
// s.Base.App.Server().TLSConfig = tlsCnf
|
||||||
|
// fmt.Println("Podmiana configa TLS")
|
||||||
|
// defer svc.Close()
|
||||||
|
|
||||||
|
// go func() { // Consul KV updater
|
||||||
|
// ticker := time.NewTicker(time.Second * 15)
|
||||||
|
// for range ticker.C {
|
||||||
|
// fetchKVConfig(s) // FIXME: duplicated in worker
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
|
|
||||||
|
// go func() { // Server metadata cache updater
|
||||||
|
// ticker := time.NewTicker(time.Second * 5)
|
||||||
|
// for range ticker.C {
|
||||||
|
// s.cacheMetadata()
|
||||||
|
// }
|
||||||
|
// }()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -13,9 +13,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) GetProductListHandler(c *fiber.Ctx) error {
|
func (s *Server) GetProductListHandler(c *fiber.Ctx) error {
|
||||||
reqID, _ := s.Base.GetRequestID(c)
|
reqID, _ := s.GetRequestID(c)
|
||||||
req := new(def.GetProductListRequest)
|
req := new(def.GetProductListRequest)
|
||||||
catalogSrv := service.NewCatalogService(s.Database, s.Eventbus, s.Logger)
|
catalogSrv := service.NewCatalogService(s.GetDatabase(), s.GetEventBus(), s.GetLogger())
|
||||||
res, err := ui.GetProductList(catalogSrv, req.CategoryID, reqID)
|
res, err := ui.GetProductList(catalogSrv, req.CategoryID, reqID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -25,10 +25,10 @@ func (s *Server) GetProductListHandler(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) AddProductToBasketHandler(c *fiber.Ctx) error {
|
func (s *Server) AddProductToBasketHandler(c *fiber.Ctx) error {
|
||||||
reqID, _ := s.Base.GetRequestID(c)
|
reqID, _ := s.GetRequestID(c)
|
||||||
req := new(def.AddProductToBasketRequest)
|
req := new(def.AddProductToBasketRequest)
|
||||||
if err := c.BodyParser(req); err != nil {
|
if err := c.BodyParser(req); err != nil {
|
||||||
return s.Base.Error(c, 400, err.Error())
|
return s.Error(c, 400, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
basketID := prepareBasket(c)
|
basketID := prepareBasket(c)
|
||||||
@ -37,24 +37,24 @@ func (s *Server) AddProductToBasketHandler(c *fiber.Ctx) error {
|
|||||||
qty = req.Quantity
|
qty = req.Quantity
|
||||||
}
|
}
|
||||||
|
|
||||||
catalogSrv := service.NewCatalogService(s.Database, s.Eventbus, s.Logger)
|
catalogSrv := service.NewCatalogService(s.GetDatabase(), s.GetEventBus(), s.GetLogger())
|
||||||
res, err := ui.AddProductToBasket(catalogSrv, req.ProductID, qty, basketID, reqID)
|
res, err := ui.AddProductToBasket(catalogSrv, req.ProductID, qty, basketID, reqID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Logger.Log("AddProductToBasketHandler error: ", err)
|
s.GetLogger().Log("AddProductToBasketHandler error: ", err)
|
||||||
if res.ProductID == 0 {
|
if res.ProductID == 0 {
|
||||||
return s.Base.Error(c, 404, fmt.Sprintf("Product #%d not exists", req.ProductID))
|
return s.Error(c, 404, fmt.Sprintf("Product #%d not exists", req.ProductID))
|
||||||
}
|
}
|
||||||
return s.Base.Error(c, 400, "Failed to add product to basket")
|
return s.Error(c, 400, "Failed to add product to basket")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(res)
|
return c.JSON(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) RemoveProductFromBasketHandler(c *fiber.Ctx) error {
|
func (s *Server) RemoveProductFromBasketHandler(c *fiber.Ctx) error {
|
||||||
reqID, _ := s.Base.GetRequestID(c)
|
reqID, _ := s.GetRequestID(c)
|
||||||
req := new(def.RemoveProductFromBasketRequest)
|
req := new(def.RemoveProductFromBasketRequest)
|
||||||
if err := c.BodyParser(req); err != nil {
|
if err := c.BodyParser(req); err != nil {
|
||||||
return s.Base.Error(c, 400, err.Error())
|
return s.Error(c, 400, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
basketID := prepareBasket(c)
|
basketID := prepareBasket(c)
|
||||||
@ -63,11 +63,11 @@ func (s *Server) RemoveProductFromBasketHandler(c *fiber.Ctx) error {
|
|||||||
qty = req.Quantity
|
qty = req.Quantity
|
||||||
}
|
}
|
||||||
|
|
||||||
catalogSrv := service.NewCatalogService(s.Database, s.Eventbus, s.Logger)
|
catalogSrv := service.NewCatalogService(s.GetDatabase(), s.GetEventBus(), s.GetLogger())
|
||||||
res, err := ui.RemoveProductFromBasket(catalogSrv, req.ProductID, qty, basketID, reqID)
|
res, err := ui.RemoveProductFromBasket(catalogSrv, req.ProductID, qty, basketID, reqID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Logger.Log("RemoveProductFromBasketHandler error: ", err)
|
s.GetLogger().Log("RemoveProductFromBasketHandler error: ", err)
|
||||||
return s.Base.Error(c, 400, "Failed to remove product from basket")
|
return s.Error(c, 400, "Failed to remove product from basket")
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.JSON(res)
|
return c.JSON(res)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package config
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -26,7 +26,7 @@ const (
|
|||||||
defEbEventsQueue = "catalog-svc"
|
defEbEventsQueue = "catalog-svc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServerConfig struct {
|
type Config struct {
|
||||||
ID string
|
ID string
|
||||||
Name string
|
Name string
|
||||||
Domain string
|
Domain string
|
||||||
@ -52,8 +52,8 @@ type ServerConfig struct {
|
|||||||
// Fields with JSON mappings are available through Consul KV storage
|
// Fields with JSON mappings are available through Consul KV storage
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerConfig(name string) *ServerConfig {
|
func NewConfig(name string) *Config {
|
||||||
c := new(ServerConfig)
|
c := new(Config)
|
||||||
|
|
||||||
c.ID, _ = os.Hostname()
|
c.ID, _ = os.Hostname()
|
||||||
c.Name = name
|
c.Name = name
|
||||||
@ -74,15 +74,11 @@ func NewServerConfig(name string) *ServerConfig {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ServerConfig) GetAppFullName() string {
|
func (c *Config) GetAppFullName() string {
|
||||||
return fmt.Sprintf("%s_%s", c.Name, c.ID)
|
return fmt.Sprintf("%s_%s", c.Name, c.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (c *ServerConfig) GetAddressForRegistry() string {
|
func (c *Config) GetIP() string {
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (c *ServerConfig) GetIP() string {
|
|
||||||
host, _ := os.Hostname()
|
host, _ := os.Hostname()
|
||||||
ips, _ := net.LookupIP(host)
|
ips, _ := net.LookupIP(host)
|
||||||
// for _, ip := range ips {
|
// for _, ip := range ips {
|
||||||
@ -91,3 +87,25 @@ func (c *ServerConfig) GetIP() string {
|
|||||||
|
|
||||||
return ips[0].String()
|
return ips[0].String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetArray() map[string]string { // FIXME fix types etc
|
||||||
|
arr := make(map[string]string)
|
||||||
|
arr["id"] = c.ID
|
||||||
|
arr["name"] = c.Name
|
||||||
|
arr["appFullname"] = c.GetAppFullName()
|
||||||
|
arr["domain"] = c.Domain
|
||||||
|
arr["ip"] = c.GetIP()
|
||||||
|
arr["netAddr"] = c.NetAddr
|
||||||
|
arr["registryDomainOverIP"] = c.RegistryDomainOverIP
|
||||||
|
arr["pathPrefix"] = c.PathPrefix
|
||||||
|
arr["cacheAddr"] = c.CacheAddr
|
||||||
|
arr["cachePassword"] = c.CachePassword
|
||||||
|
arr["dbURL"] = c.DbURL
|
||||||
|
arr["eventBusExchange"] = c.EventBusExchange
|
||||||
|
arr["eventBusURL"] = c.EventBusURL
|
||||||
|
arr["kvNamespace"] = c.KVNamespace
|
||||||
|
arr["loggerAddr"] = c.LoggerAddr
|
||||||
|
arr["registryAddr"] = c.RegistryAddr
|
||||||
|
|
||||||
|
return arr
|
||||||
|
}
|
@ -12,7 +12,7 @@ import (
|
|||||||
// "github.com/gofiber/fiber/v2/middleware/cors"
|
// "github.com/gofiber/fiber/v2/middleware/cors"
|
||||||
|
|
||||||
func SetupMiddleware(s *Server) {
|
func SetupMiddleware(s *Server) {
|
||||||
s.Base.Use(LoggingMiddleware(s.Logger))
|
s.Use(LoggingMiddleware(s.GetLogger()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoggingMiddleware(log *fluentd.Logger) func(c *fiber.Ctx) error {
|
func LoggingMiddleware(log *fluentd.Logger) func(c *fiber.Ctx) error {
|
||||||
|
@ -1,78 +1,74 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
amqp "github.com/rabbitmq/amqp091-go"
|
||||||
|
|
||||||
"git.pbiernat.io/egommerce/api-entities/http"
|
"git.pbiernat.io/egommerce/api-entities/http"
|
||||||
"git.pbiernat.io/egommerce/catalog-service/app"
|
"git.pbiernat.io/egommerce/go-api-pkg/consul"
|
||||||
cnf "git.pbiernat.io/egommerce/catalog-service/config"
|
"git.pbiernat.io/egommerce/go-api-pkg/fluentd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Server struct {
|
Server struct {
|
||||||
*fiber.App
|
*fiber.App
|
||||||
cnf *cnf.ServerConfig
|
|
||||||
|
|
||||||
|
ID string
|
||||||
addr string // e.g. "127.0.0.1:80"
|
addr string // e.g. "127.0.0.1:80"
|
||||||
|
handlers map[string]any
|
||||||
ShutdownFn
|
|
||||||
}
|
}
|
||||||
HeaderRequestID struct {
|
HeaderRequestID struct {
|
||||||
RequestID string `reqHeader:"x-request-id"`
|
RequestID string `reqHeader:"x-request-id"`
|
||||||
}
|
}
|
||||||
ShutdownFn func() error
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(conf *cnf.Config) *Server {
|
func New(c *Config) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
|
ID: c.ID,
|
||||||
App: fiber.New(fiber.Config{
|
App: fiber.New(fiber.Config{
|
||||||
AppName: conf.ID,
|
AppName: c.ID,
|
||||||
ServerHeader: conf.Name + ":" + conf.ID,
|
ServerHeader: c.Name + ":" + c.ID,
|
||||||
ReadTimeout: conf.ReadTimeout * time.Millisecond,
|
ReadTimeout: c.ReadTimeout * time.Millisecond,
|
||||||
WriteTimeout: conf.WriteTimeout * time.Millisecond,
|
WriteTimeout: c.WriteTimeout * time.Millisecond,
|
||||||
IdleTimeout: conf.IdleTimeout * time.Millisecond,
|
IdleTimeout: c.IdleTimeout * time.Millisecond,
|
||||||
}),
|
}),
|
||||||
cnf: conf,
|
addr: c.NetAddr,
|
||||||
addr: conf.NetAddr,
|
handlers: make(map[string]any),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Init() {
|
func (s *Server) Start() error {
|
||||||
// svr.Base.ShutdownFn = svr.Shutdown()
|
|
||||||
|
|
||||||
SetupMiddleware(s)
|
SetupMiddleware(s)
|
||||||
SetupRouter(s)
|
SetupRouter(s)
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) Start(while chan struct{}) {
|
// fmt.Printf("Starting server at: %s...\n", s.addr)
|
||||||
// fmt.Println("[DOER] Started server at: " + s.addr)
|
|
||||||
ln, _ := net.Listen("tcp", s.addr)
|
ln, _ := net.Listen("tcp", s.addr)
|
||||||
// ln = tls.NewListener(ln, s.App.Server().TLSConfig)
|
// ln = tls.NewListener(ln, s.App.Server().TLSConfig)
|
||||||
err := s.Listener(ln)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to start server: %s. Reason: %v\n", s.cnf.ID, err)
|
|
||||||
close(while)
|
|
||||||
}
|
|
||||||
<-while
|
|
||||||
|
|
||||||
// return err
|
return s.Listener(ln)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) OnShutdown(a *app.App) {
|
func (s *Server) RegisterHandler(name string, fn func() any) {
|
||||||
a.Logger.Log("Server %s is going down...", a.cnf.ID)
|
// fmt.Printf("Registering plugin( with handler): %s... OK\n", name)
|
||||||
|
s.handlers[name] = fn()
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("Unregistering...")
|
func (s *Server) OnShutdown() {
|
||||||
a.Registry.Unregister()
|
// s.GetLogger().Log("Server %s is going down...", s.ID)
|
||||||
|
|
||||||
|
s.GetRegistry().Unregister()
|
||||||
// a.clearMetadataCache()
|
// a.clearMetadataCache()
|
||||||
a.Eventbus.Close()
|
s.GetEventBus().Close()
|
||||||
a.Database.Close()
|
s.GetDatabase().Close()
|
||||||
a.Logger.Log("Gone.")
|
s.GetLogger().Log("Gone.")
|
||||||
a.Logger.Close()
|
s.GetLogger().Close()
|
||||||
|
|
||||||
|
s.Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
|
func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
|
||||||
@ -88,6 +84,27 @@ 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})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Plugin helper funcitons
|
||||||
|
func (s *Server) GetCache() *redis.Client {
|
||||||
|
return (s.handlers["cache"]).(*redis.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetDatabase() *pgxpool.Pool { // FIXME hardcoded index issue
|
||||||
|
return (s.handlers["database"]).(*pgxpool.Pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetEventBus() *amqp.Channel {
|
||||||
|
return (s.handlers["eventbus"]).(*amqp.Channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetLogger() *fluentd.Logger {
|
||||||
|
return (s.handlers["logger"]).(*fluentd.Logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetRegistry() *consul.Service {
|
||||||
|
return (s.handlers["registry"]).(*consul.Service)
|
||||||
|
}
|
||||||
|
|
||||||
// @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) registerKVUpdater() { // @FIXME: merge duplication in server.go and worker.go
|
// func (s *Server) registerKVUpdater() { // @FIXME: merge duplication in server.go and worker.go
|
||||||
// go func() {
|
// go func() {
|
||||||
|
@ -5,8 +5,10 @@ import (
|
|||||||
|
|
||||||
"git.pbiernat.io/egommerce/api-entities/model"
|
"git.pbiernat.io/egommerce/api-entities/model"
|
||||||
"git.pbiernat.io/egommerce/catalog-service/internal/event"
|
"git.pbiernat.io/egommerce/catalog-service/internal/event"
|
||||||
|
|
||||||
"git.pbiernat.io/egommerce/go-api-pkg/fluentd"
|
"git.pbiernat.io/egommerce/go-api-pkg/fluentd"
|
||||||
"git.pbiernat.io/egommerce/go-api-pkg/rabbitmq"
|
"git.pbiernat.io/egommerce/go-api-pkg/rabbitmq"
|
||||||
|
|
||||||
"github.com/georgysavva/scany/v2/pgxscan"
|
"github.com/georgysavva/scany/v2/pgxscan"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
amqp "github.com/rabbitmq/amqp091-go"
|
amqp "github.com/rabbitmq/amqp091-go"
|
||||||
|
85
src/internal/worker/config.go
Normal file
85
src/internal/worker/config.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package worker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
cnf "git.pbiernat.io/egommerce/go-api-pkg/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defName = "catalog-worker"
|
||||||
|
defDomain = "catalog-worker"
|
||||||
|
defCacheAddr = "egommerce.local:6379"
|
||||||
|
defCachePassword = "12345678"
|
||||||
|
defDbURL = "postgres://postgres:12345678@db-postgres:5432/egommerce"
|
||||||
|
defEventBusURL = "amqp://guest:guest@api-eventbus:5672"
|
||||||
|
defKVNmspc = "dev.egommerce/service/catalog-worker"
|
||||||
|
defLoggerAddr = "api-logger:24224"
|
||||||
|
defMongoDbURL = "mongodb://mongodb:12345678@mongo-db:27017"
|
||||||
|
defEbEventsExchange = "api-events"
|
||||||
|
defEbEventsQueue = "catalog-svc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
|
||||||
|
LoggerAddr string `json:"logger_addr"`
|
||||||
|
DbURL string `json:"db_url"`
|
||||||
|
CacheAddr string `json:"cache_addr"`
|
||||||
|
CachePassword string `json:"cache_password"`
|
||||||
|
MongoDbUrl string `json:"mongodb_url"`
|
||||||
|
EventBusURL string `json:"eventbus_url"`
|
||||||
|
EventBusExchange string `json:"eventbus_exchange"`
|
||||||
|
EventBusQueue string `json:"eventbus_queue"`
|
||||||
|
KVNamespace string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfig(name string) *Config {
|
||||||
|
c := new(Config)
|
||||||
|
|
||||||
|
c.ID, _ = os.Hostname()
|
||||||
|
c.Name = name
|
||||||
|
|
||||||
|
c.CacheAddr = cnf.GetEnv("CACHE_ADDR", defCacheAddr)
|
||||||
|
c.CachePassword = cnf.GetEnv("CACHE_PASSWORD", defCachePassword)
|
||||||
|
c.DbURL = cnf.GetEnv("DATABASE_URL", defDbURL)
|
||||||
|
c.EventBusExchange = defEbEventsExchange
|
||||||
|
c.EventBusURL = cnf.GetEnv("EVENTBUS_URL", defEventBusURL)
|
||||||
|
c.KVNamespace = cnf.GetEnv("APP_KV_NAMESPACE", defKVNmspc)
|
||||||
|
c.LoggerAddr = cnf.GetEnv("LOGGER_ADDR", defLoggerAddr)
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetAppFullName() string {
|
||||||
|
return fmt.Sprintf("%s_%s", c.Name, c.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetIP() string {
|
||||||
|
host, _ := os.Hostname()
|
||||||
|
ips, _ := net.LookupIP(host)
|
||||||
|
// for _, ip := range ips {
|
||||||
|
// return ip.String()
|
||||||
|
// }
|
||||||
|
|
||||||
|
return ips[0].String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetArray() map[string]string { // FIXME fix types etc
|
||||||
|
arr := make(map[string]string)
|
||||||
|
arr["id"] = c.ID
|
||||||
|
arr["name"] = c.Name
|
||||||
|
arr["appFullname"] = c.GetAppFullName()
|
||||||
|
arr["cacheAddr"] = c.CacheAddr
|
||||||
|
arr["cachePassword"] = c.CachePassword
|
||||||
|
arr["dbURL"] = c.DbURL
|
||||||
|
arr["eventBusExchange"] = c.EventBusExchange
|
||||||
|
arr["eventBusURL"] = c.EventBusURL
|
||||||
|
arr["kvNamespace"] = c.KVNamespace
|
||||||
|
arr["loggerAddr"] = c.LoggerAddr
|
||||||
|
|
||||||
|
return arr
|
||||||
|
}
|
@ -4,104 +4,131 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
amqp "github.com/rabbitmq/amqp091-go"
|
amqp "github.com/rabbitmq/amqp091-go"
|
||||||
|
|
||||||
"git.pbiernat.io/egommerce/go-api-pkg/consul"
|
|
||||||
"git.pbiernat.io/egommerce/go-api-pkg/fluentd"
|
"git.pbiernat.io/egommerce/go-api-pkg/fluentd"
|
||||||
"git.pbiernat.io/egommerce/go-api-pkg/rabbitmq"
|
"git.pbiernat.io/egommerce/go-api-pkg/rabbitmq"
|
||||||
|
|
||||||
"git.pbiernat.io/egommerce/catalog-service/internal/event"
|
"git.pbiernat.io/egommerce/catalog-service/internal/event"
|
||||||
cnf "git.pbiernat.io/egommerce/catalog-service/internal/server"
|
|
||||||
"git.pbiernat.io/egommerce/catalog-service/internal/service"
|
"git.pbiernat.io/egommerce/catalog-service/internal/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
Worker struct {
|
Worker struct {
|
||||||
Config *cnf.Config
|
ID string
|
||||||
Cache *redis.Client
|
cnf *Config
|
||||||
Database *pgxpool.Pool
|
handlers map[string]any
|
||||||
Eventbus *amqp.Channel
|
services map[string]any
|
||||||
Logger *fluentd.Logger
|
doWrkUntil chan struct{}
|
||||||
Registry *consul.Service
|
|
||||||
}
|
}
|
||||||
OptionFn func(*Worker) error // FIXME: similar in server/server.go
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func New(c *cnf.Config, opts ...OptionFn) *Worker {
|
func New(c *Config) *Worker {
|
||||||
w := &Worker{
|
return &Worker{
|
||||||
Config: c,
|
ID: c.ID,
|
||||||
}
|
cnf: c,
|
||||||
|
handlers: make(map[string]any),
|
||||||
for _, opt := range opts {
|
services: make(map[string]any),
|
||||||
if err := opt(w); err != nil {
|
doWrkUntil: make(chan struct{}),
|
||||||
log.Fatalf("Failed to attach extension to the worker. Err: %v\n", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return w
|
func (w *Worker) Start() error {
|
||||||
}
|
// Init
|
||||||
|
err := rabbitmq.NewExchange(w.GetEventBus(), w.cnf.EventBusExchange)
|
||||||
func (w *Worker) Start(while chan struct{}) error {
|
|
||||||
go func() {
|
|
||||||
sigint := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
<-sigint
|
|
||||||
|
|
||||||
w.Shutdown()
|
|
||||||
close(while)
|
|
||||||
}()
|
|
||||||
|
|
||||||
run := w.createRunFile("./app.run") // TODO move to common library (shared between server and worker)
|
|
||||||
defer w.removeRunFile(run)
|
|
||||||
|
|
||||||
err := w.doWork()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to start worker: %s. Reason: %v\n", w.Config.Base.AppID, err)
|
w.GetLogger().Log("Failed to declare EventBus exchange: %v\n", err)
|
||||||
close(while)
|
fmt.Printf("Failed to declare EventBus exchange: %v\n", err)
|
||||||
}
|
|
||||||
|
|
||||||
w.Logger.Log("Waiting for messages...")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Worker) Shutdown() error {
|
|
||||||
w.Logger.Log("Worker %s is going down...", w.Config.Base.AppID)
|
|
||||||
|
|
||||||
w.Registry.Unregister()
|
|
||||||
w.Eventbus.Close()
|
|
||||||
w.Database.Close()
|
|
||||||
w.Logger.Log("Gone.")
|
|
||||||
w.Logger.Close()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *Worker) createRunFile(path string) *os.File {
|
|
||||||
run, err := os.Create(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to create run file. Reason: %v\n", err)
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
run.WriteString(strconv.Itoa(os.Getpid()))
|
|
||||||
|
|
||||||
return run
|
_, err = w.GetEventBus().QueueDeclare(
|
||||||
|
w.cnf.EventBusQueue, // name
|
||||||
|
false, // durable
|
||||||
|
false, // delete when unused
|
||||||
|
false, // exclusive
|
||||||
|
false, // no-wait
|
||||||
|
nil, // arguments
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
w.GetLogger().Log("Failed to declare EventBus queue: %v\n", err)
|
||||||
|
fmt.Printf("Failed to declare EventBus queue: %v\n", err)
|
||||||
|
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) removeRunFile(f *os.File) error {
|
err = w.doWork(w.doWrkUntil)
|
||||||
return f.Close()
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to start worker: %s. Reason: %v\n", w.ID, err)
|
||||||
|
close(w.doWrkUntil)
|
||||||
|
}
|
||||||
|
<-w.doWrkUntil
|
||||||
|
|
||||||
|
return err
|
||||||
|
|
||||||
|
// go func() {
|
||||||
|
// sigint := make(chan os.Signal, 1)
|
||||||
|
// signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
// <-sigint
|
||||||
|
|
||||||
|
// w.Shutdown()
|
||||||
|
// close(while)
|
||||||
|
// }()
|
||||||
|
|
||||||
|
// run := w.createRunFile("./app.run") // TODO move to common library (shared between server and worker)
|
||||||
|
// defer w.removeRunFile(run)
|
||||||
|
|
||||||
|
// w.Logger.Log("Waiting for messages...")
|
||||||
|
|
||||||
|
// return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) doWork() error {
|
func (w *Worker) RegisterHandler(name string, fn func() any) {
|
||||||
msgs, err := w.Eventbus.Consume(
|
// fmt.Printf("Registering plugin( with handler): %s... OK\n", name)
|
||||||
w.Config.EventBusQueue, // queue
|
w.handlers[name] = fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worker) OnShutdown() {
|
||||||
|
w.GetLogger().Log("Worker %s is going down...", w.ID)
|
||||||
|
// fmt.Printf("Worker %s is going down...\n", w.ID)
|
||||||
|
w.GetEventBus().Close()
|
||||||
|
w.GetDatabase().Close()
|
||||||
|
w.GetLogger().Log("Gone.")
|
||||||
|
w.GetLogger().Close()
|
||||||
|
|
||||||
|
close(w.doWrkUntil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin helper funcitons
|
||||||
|
func (w *Worker) GetCache() *redis.Client {
|
||||||
|
return (w.handlers["cache"]).(*redis.Client)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worker) GetDatabase() *pgxpool.Pool { // FIXME hardcoded index issue
|
||||||
|
return (w.handlers["database"]).(*pgxpool.Pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worker) GetEventBus() *amqp.Channel {
|
||||||
|
return (w.handlers["eventbus"]).(*amqp.Channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worker) GetLogger() *fluentd.Logger {
|
||||||
|
return (w.handlers["logger"]).(*fluentd.Logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Worker) doWork(while chan struct{}) error {
|
||||||
|
w.services["catalog"] =
|
||||||
|
service.NewCatalogService(w.GetDatabase(), w.GetEventBus(), w.GetLogger())
|
||||||
|
|
||||||
|
cSrv := (w.services["catalog"]).(*service.CatalogService) // FIXME simplify maybe...?
|
||||||
|
|
||||||
|
msgs, err := w.GetEventBus().Consume(
|
||||||
|
w.cnf.EventBusQueue, // queue
|
||||||
"", // consumer
|
"", // consumer
|
||||||
false, // auto-ack
|
false, // auto-ack
|
||||||
false, // exclusive
|
false, // exclusive
|
||||||
@ -110,27 +137,28 @@ func (w *Worker) doWork() error {
|
|||||||
nil, // args
|
nil, // args
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Logger.Log("Failed to register a consumer: %s", err)
|
w.GetLogger().Log("Failed to register a consumer: %s", err)
|
||||||
|
fmt.Printf("Failed to register a consumer: %s", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
// close(while)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
catalogSrvc := service.NewCatalogService(w.Database, w.Eventbus, w.Logger)
|
|
||||||
|
|
||||||
for d := range msgs {
|
for d := range msgs {
|
||||||
go func(d amqp.Delivery) {
|
// go func(d amqp.Delivery) {
|
||||||
w.processMsg(catalogSrvc, d)
|
w.processMsg(cSrv, d)
|
||||||
}(d)
|
// }(d)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
<-while
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) processMsg(srvc *service.CatalogService, d amqp.Delivery) {
|
func (w *Worker) processMsg(cSrv *service.CatalogService, d amqp.Delivery) {
|
||||||
msg, err := rabbitmq.Deserialize(d.Body)
|
msg, err := rabbitmq.Deserialize(d.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.Logger.Log("Deserialization error: %v\n", err)
|
w.GetLogger().Log("Deserialization error: %v\n", err)
|
||||||
d.Reject(false)
|
d.Reject(false)
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -140,22 +168,22 @@ func (w *Worker) processMsg(srvc *service.CatalogService, d amqp.Delivery) {
|
|||||||
data := (msg["data"]).(map[string]interface{})
|
data := (msg["data"]).(map[string]interface{})
|
||||||
// reqID := (data["request_id"]).(string) // FIXME Check input params!
|
// reqID := (data["request_id"]).(string) // FIXME Check input params!
|
||||||
|
|
||||||
w.Logger.Log("Processing message \"%s\" with data: %v\n", name, data)
|
w.GetLogger().Log("Processing message \"%s\" with data: %v\n", name, data)
|
||||||
|
|
||||||
var ok = false
|
var ok = false
|
||||||
switch true { // Refactor -> use case for polymorphism
|
switch true { // Refactor -> use case for polymorphism
|
||||||
case strings.Contains(name, event.EVENT_WAREHOUSE_STOCK_UPDATED):
|
case strings.Contains(name, event.EVENT_WAREHOUSE_STOCK_UPDATED):
|
||||||
w.Logger.Log("Event: %s", event.EVENT_WAREHOUSE_STOCK_UPDATED)
|
w.GetLogger().Log("Event: %s", event.EVENT_WAREHOUSE_STOCK_UPDATED)
|
||||||
}
|
}
|
||||||
|
|
||||||
rnr := NewCommandRunner(data, srvc)
|
rnr := NewCommandRunner(data, cSrv)
|
||||||
ok, _ = rnr.run(data)
|
ok, _ = rnr.run(data)
|
||||||
if ok {
|
if ok {
|
||||||
w.Logger.Log("Successful executed message \"%s\"\n", name)
|
w.GetLogger().Log("Successful executed message \"%s\"\n", name)
|
||||||
d.Ack(false)
|
d.Ack(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Logger.Log("Error processing \"%s\": %s (%v)", name, err.Error(), err)
|
w.GetLogger().Log("Error processing \"%s\": %s (%v)", name, err.Error(), err)
|
||||||
d.Reject(false) // FIXME: or Nack(repeat until success - maybe message shoud know...?
|
d.Reject(false) // FIXME: or Nack(repeat until success - maybe message shoud know...?
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user