modelRT/main.go

197 lines
5.1 KiB
Go
Raw Normal View History

// entry function
package main
import (
"context"
"flag"
2025-07-31 10:31:26 +08:00
"net/http"
"os"
"os/signal"
"syscall"
"time"
"modelRT/alert"
"modelRT/config"
"modelRT/database"
"modelRT/diagram"
locker "modelRT/distributedlock"
2024-12-06 16:13:11 +08:00
_ "modelRT/docs"
"modelRT/handler"
2024-12-25 16:34:57 +08:00
"modelRT/logger"
"modelRT/middleware"
"modelRT/pool"
2025-07-31 10:31:26 +08:00
"modelRT/router"
realtimedata "modelRT/real-time-data"
"github.com/gin-gonic/gin"
"github.com/panjf2000/ants/v2"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"gorm.io/gorm"
)
var limiter *middleware.Limiter
func init() {
limiter = middleware.NewLimiter(10, 1*time.Minute) // 设置限流器允许每分钟最多请求10次
}
var (
modelRTConfigDir = flag.String("modelRT_config_dir", "./config", "config file dir of model runtime service")
modelRTConfigName = flag.String("modelRT_config_name", "config", "config file name of model runtime service")
modelRTConfigType = flag.String("modelRT_config_type", "yaml", "config file type of model runtime service")
)
var (
modelRTConfig config.ModelRTConfig
postgresDBClient *gorm.DB
alertManager *alert.EventManager
)
// TODO 使用 wire 依赖注入管理 DVIE 面板注册的 panel
func main() {
flag.Parse()
ctx := context.TODO()
// init logger
logger.InitLoggerInstance(modelRTConfig.LoggerConfig)
modelRTConfig = config.ReadAndInitConfig(*modelRTConfigDir, *modelRTConfigName, *modelRTConfigType)
// init postgresDBClient
postgresDBClient = database.InitPostgresDBInstance(ctx, modelRTConfig.PostgresDBURI)
defer func() {
sqlDB, err := postgresDBClient.DB()
if err != nil {
panic(err)
}
sqlDB.Close()
}()
// init alert manager
_ = alert.InitAlertEventManager()
2024-12-18 16:25:49 +08:00
// init model parse ants pool
parsePool, err := ants.NewPoolWithFunc(modelRTConfig.ParseConcurrentQuantity, pool.ParseFunc)
if err != nil {
logger.Error(ctx, "init concurrent parse task pool failed", "error", err)
panic(err)
}
2024-12-18 16:25:49 +08:00
defer parsePool.Release()
storageClient := diagram.InitClientInstance(modelRTConfig.StorageRedisConfig)
defer storageClient.Close()
lockerClient := locker.InitClientInstance(modelRTConfig.LockerRedisConfig)
defer lockerClient.Close()
// init anchor param ants pool
anchorRealTimePool, err := pool.AnchorPoolInit(modelRTConfig.RTDReceiveConcurrentQuantity)
2024-12-18 16:25:49 +08:00
if err != nil {
logger.Error(ctx, "init concurrent anchor param task pool failed", "error", err)
2024-12-18 16:25:49 +08:00
panic(err)
}
defer anchorRealTimePool.Release()
2024-12-18 16:25:49 +08:00
// init cancel context
2024-12-18 16:25:49 +08:00
cancelCtx, cancel := context.WithCancel(ctx)
defer cancel()
// init real time data receive channel
go realtimedata.ReceiveChan(cancelCtx)
2025-01-09 15:56:40 +08:00
postgresDBClient.Transaction(func(tx *gorm.DB) error {
// load circuit diagram from postgres
componentTypeMap, err := database.QueryCircuitDiagramComponentFromDB(cancelCtx, tx, parsePool)
2025-01-09 15:56:40 +08:00
if err != nil {
logger.Error(ctx, "load circuit diagrams from postgres failed", "error", err)
2025-01-09 15:56:40 +08:00
panic(err)
}
2025-01-09 15:56:40 +08:00
// TODO 暂时屏蔽完成 swagger 启动测试
tree, err := database.QueryTopologicFromDB(ctx, tx, componentTypeMap)
2025-01-09 15:56:40 +08:00
if err != nil {
logger.Error(ctx, "load topologic info from postgres failed", "error", err)
2025-01-09 15:56:40 +08:00
panic(err)
}
diagram.GlobalTree = tree
2025-01-09 15:56:40 +08:00
return nil
})
// TODO 完成订阅数据分析
2024-12-06 16:13:11 +08:00
// TODO 暂时屏蔽完成 swagger 启动测试
// go realtimedata.RealTimeDataComputer(ctx, nil, []string{}, "")
2025-07-31 10:31:26 +08:00
engine := gin.New()
router.RegisterRoutes(engine)
server := http.Server{
Addr: ":8080",
Handler: engine,
}
// creating a System Signal Receiver
done := make(chan os.Signal, 10)
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-done
if err := server.Shutdown(context.Background()); err != nil {
logger.Error(ctx, "ShutdownServerError", "err", err)
}
}()
2024-12-12 16:17:31 +08:00
2025-07-31 10:31:26 +08:00
logger.Info(ctx, "Starting ModelRT server...")
err = server.ListenAndServe()
if err != nil {
if err == http.ErrServerClosed {
// the service receives the shutdown signal normally and then closes
logger.Info(ctx, "Server closed under request")
} else {
// abnormal shutdown of service
logger.Error(ctx, "Server closed unexpected", "err", err)
}
}
// real time data api
engine.GET("/ws/rtdatas", handler.RealTimeDataReceivehandler)
// anchor api
engine.POST("/model/anchor_replace", handler.ComponentAnchorReplaceHandler)
// alert api
engine.GET("/alert/events/query", handler.QueryAlertEventHandler)
// real time data api
engine.GET("/rt/datas/query", handler.QueryRealTimeDataHandler)
2024-12-12 16:17:31 +08:00
// dashborad api
dashboard := engine.Group("/dashboard", limiter.Middleware)
{
dashboard.GET("/load", nil)
dashboard.GET("/query", nil)
dashboard.POST("/create", nil)
dashboard.POST("/update", nil)
dashboard.POST("/delete", nil)
}
// engine.Group()
2024-12-06 16:13:11 +08:00
// Swagger UI
engine.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
// 注册 Swagger UI 路由
// docs.SwaggerInfo.BasePath = "/model"
// v1 := engine.Group("/api/v1")
// {
// eg := v1.Group("/example")
// {
// eg.GET("/helloworld", Helloworld)
// }
// }
// start route with 8080 port
engine.Run(":8080")
// Redis hashmap 母线模型、异步电动机模型
// kv key name value busx
}