basket-service/src/internal/app/server/server.go
Piotr Biernat f66662111e
Some checks failed
continuous-integration/drone/push Build is failing
update
2023-03-20 17:33:14 +01:00

181 lines
4.0 KiB
Go

package server
import (
"bytes"
"context"
"encoding/json"
"os"
"os/signal"
"syscall"
"time"
"github.com/go-redis/redis/v8"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
"github.com/streadway/amqp"
def "git.pbiernat.dev/egommerce/api-entities/http"
discovery "git.pbiernat.dev/egommerce/go-api-pkg/consul"
"git.pbiernat.dev/egommerce/go-api-pkg/fluentd"
)
type Server struct {
*fiber.App
conf *Config
log *fluentd.Logger
db *pgxpool.Pool
cache *redis.Client
ebCh *amqp.Channel
discovery *discovery.Service
name string
addr string
kvNmspc string
}
type Headers struct {
RequestID string `reqHeader:"x-request-id"`
}
func NewServer(conf *Config, logger *fluentd.Logger, db *pgxpool.Pool, cache *redis.Client, ebCh *amqp.Channel) *Server {
consul, err := discovery.NewService(conf.RegistryAddr, conf.AppID, conf.AppName, conf.AppID, conf.AppDomain, conf.PathPrefix, conf.Port)
if err != nil {
logger.Log("Error connecting to %s: %v", conf.RegistryAddr, err)
}
logger.Log("Registering service with name: %s, address: %s", consul.Name, consul.Address)
err = consul.Register()
if err != nil {
logger.Log("register error: %v", err)
}
cnf := fiber.Config{
AppName: conf.AppName,
ServerHeader: conf.AppName,
ReadTimeout: time.Millisecond * 50,
WriteTimeout: time.Millisecond * 50,
IdleTimeout: time.Millisecond * 50,
}
s := &Server{
fiber.New(cnf),
conf,
logger,
db,
cache,
ebCh,
consul,
conf.AppName,
conf.NetAddr,
conf.KVNamespace,
}
go func(s *Server) { // Consul KV updater
interval := time.Second * 15
ticker := time.NewTicker(interval)
for range ticker.C {
s.updateKVConfig()
}
}(s)
go func(s *Server) { // Server metadata cache updater
ticker := time.NewTicker(time.Second * 5)
for range ticker.C {
s.cacheMetadata()
}
}(s)
SetupMiddlewares(s)
SetupRoutes(s)
return s
}
// func (s *Server) Start() {
// err := s.Listen(s.addr)
// s.log.Log("Starting error: %v", err)
// }
func (s *Server) StartWithGracefulShutdown(forever chan struct{}) {
go func() {
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
<-sigint
if err := s.gracefulShutdown(); err != nil {
s.log.Log("Server is not shutting down! Reason: %v", err)
}
close(forever)
}()
if err := s.Listen(s.addr); err != nil {
s.log.Log("Server is not running! Reason: %v", err)
}
<-forever
}
func (s *Server) GetRequestID(c *fiber.Ctx) (string, error) {
var hdr = new(Headers)
if err := c.ReqHeaderParser(hdr); err != nil {
return "", err
}
return hdr.RequestID, nil
}
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)
if err != nil || config == nil {
return
}
kvCnf := bytes.NewBuffer(config.Value)
decoder := json.NewDecoder(kvCnf)
if err := decoder.Decode(&s.conf); err != nil {
return
}
}
func (s *Server) cacheMetadata() {
ctx := context.Background()
key, address := s.getMetadataIPsKey(), s.conf.AppID
pos := s.cache.LPos(ctx, key, address, redis.LPosArgs{}).Val()
if pos >= 0 {
s.cache.LRem(ctx, key, 0, address)
}
s.cache.LPush(ctx, key, address).Err()
}
func (s *Server) clearMetadataCache() {
ctx := context.Background()
key, address := s.getMetadataIPsKey(), s.conf.AppID
s.cache.LRem(ctx, key, 0, address)
}
func (s *Server) getMetadataIPsKey() string {
return "internal__" + s.conf.AppName + "__ips"
}
func (s *Server) gracefulShutdown() error {
s.log.Log("Server is going down... Unregistering service: %s", s.discovery.GetID())
s.discovery.Unregister()
s.clearMetadataCache()
s.ebCh.Close()
s.db.Close()
s.log.Close()
return s.Shutdown()
}