eventRT/main.go

115 lines
3.2 KiB
Go

// entry function
package main
import (
"context"
"errors"
"flag"
"fmt"
"log"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"eventRT/config"
"eventRT/constants"
"eventRT/database"
"eventRT/logger"
"eventRT/mq"
"eventRT/util"
"github.com/gin-gonic/gin"
)
var (
eventRTConfigDir = flag.String("eventRT_config_dir", "./configs", "config file dir")
eventRTConfigName = flag.String("eventRT_config_name", "config", "config file name")
eventRTConfigType = flag.String("eventRT_config_type", "yaml", "config file type")
)
func main() {
flag.Parse()
configPath := filepath.Join(*eventRTConfigDir, *eventRTConfigName+"."+*eventRTConfigType)
if _, err := os.Stat(configPath); os.IsNotExist(err) {
log.Println("configuration file not found,checking for example file")
exampleConfigPath := filepath.Join(*eventRTConfigDir, *eventRTConfigName+".example."+*eventRTConfigType)
configDir := filepath.Dir(configPath)
if err := os.MkdirAll(configDir, 0o755); err != nil {
panic(fmt.Errorf("failed to create config directory %s:%w", configDir, err))
}
if _, err := os.Stat(exampleConfigPath); err == nil {
if err := util.CopyFile(exampleConfigPath, configPath); err != nil {
panic(fmt.Errorf("failed to copy example config file:%w", err))
}
} else {
panic(errors.New("no config file and no config example file found"))
}
}
eventRTConfig := config.ReadAndInitConfig(*eventRTConfigDir, *eventRTConfigName, *eventRTConfigType)
// init logger instance
logger.InitLoggerInstance(eventRTConfig.LoggerConfig)
// init MongoDB client
notifyCtx, stop := signal.NotifyContext(context.TODO(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
defer stop()
client := database.InitMongoInstance(notifyCtx, eventRTConfig)
defer func() {
disconnectCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := client.Disconnect(disconnectCtx); err != nil {
logger.Error(notifyCtx, "mongodb disconnect failed", "err", err)
} else {
logger.Info(notifyCtx, "mongodb connection closed gracefully")
}
}()
// init RabbitMQ connection
mq.InitRabbitProxy(notifyCtx, eventRTConfig.RabbitMQConfig)
defer mq.GetConn().Close()
// use release mode in production
if eventRTConfig.DeployEnv == constants.ProductionDeployMode {
gin.SetMode(gin.ReleaseMode)
}
engine := gin.New()
engine.Use(gin.Logger(), gin.Recovery())
// TODO k8s liveness & readiness probe endpoints
// engine.GET("/ping", func(c *gin.Context) {
// c.JSON(200, gin.H{"status": "ok"})
// })
server := http.Server{
Addr: eventRTConfig.ServiceAddr,
Handler: engine,
}
go func() {
<-notifyCtx.Done()
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(shutdownCtx); err != nil {
logger.Error(shutdownCtx, "server shutdown failed", "err", err)
}
}()
logger.Info(notifyCtx, "starting EventRT server")
err := server.ListenAndServe()
if err != nil {
if err == http.ErrServerClosed {
// the service receives the shutdown signal normally and then closes
logger.Info(notifyCtx, "server closed under request")
} else {
// abnormal shutdown of service
logger.Error(notifyCtx, "server closed unexpected", "err", err)
}
}
}