126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
_ "net/http/pprof"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"go.c3c.cz/cv/app/server/internal/config"
|
|
"go.c3c.cz/cv/app/server/internal/httpserver"
|
|
"go.c3c.cz/cv/app/server/internal/pprofserver"
|
|
"go.c3c.cz/cv/app/server/internal/version"
|
|
)
|
|
|
|
func main() {
|
|
defer handleExit()
|
|
|
|
notice := "Starting version "
|
|
if version.Tag != "" {
|
|
notice += version.Tag
|
|
} else {
|
|
notice += "latest"
|
|
}
|
|
if version.Commit != "" {
|
|
notice = fmt.Sprintf("%s (%s)", notice, version.Commit)
|
|
}
|
|
|
|
var logger *zap.Logger
|
|
var err error
|
|
|
|
logger, err = config.LoggerConfig.Build()
|
|
if err != nil {
|
|
fmt.Println(notice)
|
|
fmt.Println(version.CommitTime.Format("Committed at 2006/01/02 15:04:05 MST"))
|
|
|
|
panic(Exit{fmt.Errorf("logger creation failed")})
|
|
}
|
|
|
|
logger.Info(
|
|
"App initializing",
|
|
zap.String("version", version.Tag),
|
|
zap.String("commit", version.Commit),
|
|
zap.Time("commitTime", version.CommitTime),
|
|
)
|
|
|
|
defer func() {
|
|
_ = logger.Sync()
|
|
}()
|
|
|
|
httpSrv, err := httpserver.New(&httpserver.Options{
|
|
BindAddr: config.BindAddrHttp,
|
|
FrontendConfig: config.Frontend,
|
|
Logger: logger,
|
|
})
|
|
if err != nil {
|
|
logger.Error("HTTP server creation failed", zap.Error(err))
|
|
panic(Exit{err})
|
|
}
|
|
|
|
quit := struct {
|
|
os chan os.Signal
|
|
pprof chan error
|
|
http chan error
|
|
}{
|
|
os: make(chan os.Signal, 1),
|
|
pprof: make(chan error, 1),
|
|
http: make(chan error, 1),
|
|
}
|
|
|
|
pprofSrv := pprofserver.New(pprofserver.Options{
|
|
BindAddr: config.BindAddrPprof,
|
|
Logger: logger,
|
|
LogLevelHandler: config.LoggerConfig.Level,
|
|
})
|
|
|
|
// Pprof server.
|
|
go func() {
|
|
logger.Info("debug server was started", zap.String("BindAddr", config.BindAddrPprof))
|
|
quit.pprof <- pprofSrv.ListenAndServe()
|
|
}()
|
|
|
|
go func() {
|
|
logger.Info("http server was started", zap.String("BindAddr", config.BindAddrHttp))
|
|
pprofSrv.SetReady()
|
|
err := httpSrv.ListenAndServe()
|
|
if err != http.ErrServerClosed {
|
|
quit.http <- err
|
|
}
|
|
}()
|
|
|
|
logger.Info("application started")
|
|
|
|
signal.Notify(quit.os, os.Interrupt, syscall.SIGTERM)
|
|
|
|
select {
|
|
case s := <-quit.os:
|
|
sig, _ := s.(syscall.Signal)
|
|
logger.Info("Signal received\n", zap.Int("signal", int(sig)))
|
|
pprofSrv.SetNotReady()
|
|
httpSrv.ShutdownWithDelay(config.GraceTerminationDelay, config.GraceTerminationLimit)
|
|
case err := <-quit.pprof:
|
|
logger.Error("app shutdown was triggered by a pprof server error", zap.Error(err))
|
|
httpSrv.ShutdownWithDelay(config.GraceTerminationDelay, config.GraceTerminationLimit)
|
|
case err := <-quit.http:
|
|
logger.Error("app shutdown was triggered by an http server error", zap.Error(err))
|
|
}
|
|
}
|
|
|
|
type Exit struct {
|
|
err error
|
|
}
|
|
|
|
func handleExit() {
|
|
if e := recover(); e != nil {
|
|
if exit, ok := e.(Exit); ok {
|
|
fmt.Println(exit.err)
|
|
os.Exit(1)
|
|
}
|
|
panic(e)
|
|
}
|
|
}
|