Add scheduled tasks (#13470)

### What problem does this PR solve?

1. RAGFlow server will send heartbeat periodically.
2. This PR will including:
- Scheduled task
- API server message sending
- Admin server API to receive the message.

### Type of change

- [x] New Feature (non-breaking change which adds functionality)

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
Jin Hai
2026-03-09 17:48:29 +08:00
committed by GitHub
parent c732a1c8e0
commit 52bcd98d29
14 changed files with 871 additions and 36 deletions

View File

@@ -6,6 +6,7 @@ import (
"net/http"
"os"
"os/signal"
"ragflow/internal/common"
"ragflow/internal/init_data"
"ragflow/internal/server"
"ragflow/internal/utility"
@@ -30,7 +31,7 @@ import (
func main() {
// Initialize logger with default level
// logger.Init("info"); // set debug log level
if err := logger.Init("debug"); err != nil {
if err := logger.Init("info"); err != nil {
panic(fmt.Sprintf("Failed to initialize logger: %v", err))
}
@@ -45,28 +46,21 @@ func main() {
}
logger.Info("Model providers loaded", zap.Int("count", len(server.GetModelProviders())))
cfg := server.GetConfig()
config := server.GetConfig()
// Reinitialize logger with configured level if different
if cfg.Log.Level != "" && cfg.Log.Level != "info" {
if err := logger.Init(cfg.Log.Level); err != nil {
if config.Log.Level != "" && config.Log.Level != "info" {
if err := logger.Init(config.Log.Level); err != nil {
logger.Error("Failed to reinitialize logger with configured level", err)
}
}
server.SetLogger(logger.Logger)
logger.Info("Server mode", zap.String("mode", cfg.Server.Mode))
logger.Info("Server mode", zap.String("mode", config.Server.Mode))
// Print all configuration settings
server.PrintAll()
// Set Gin mode
if cfg.Server.Mode == "release" {
gin.SetMode(gin.ReleaseMode)
} else {
gin.SetMode(gin.DebugMode)
}
// Initialize database
if err := dao.InitDB(); err != nil {
logger.Fatal("Failed to initialize database", zap.Error(err))
@@ -80,13 +74,13 @@ func main() {
}
// Initialize doc engine
if err := engine.Init(&cfg.DocEngine); err != nil {
if err := engine.Init(&config.DocEngine); err != nil {
logger.Fatal("Failed to initialize doc engine", zap.Error(err))
}
defer engine.Close()
// Initialize Redis cache
if err := cache.Init(&cfg.Redis); err != nil {
if err := cache.Init(&config.Redis); err != nil {
logger.Fatal("Failed to initialize Redis", zap.Error(err))
}
defer cache.Close()
@@ -112,6 +106,20 @@ func main() {
logger.Fatal("Failed to initialize query builder", zap.Error(err))
}
startServer(config)
logger.Info("Server exited")
}
func startServer(config *server.Config) {
// Set Gin mode
if config.Server.Mode == "release" {
gin.SetMode(gin.ReleaseMode)
} else {
gin.SetMode(gin.DebugMode)
}
// Initialize service layer
userService := service.NewUserService()
documentService := service.NewDocumentService()
@@ -147,7 +155,7 @@ func main() {
ginEngine := gin.New()
// Middleware
if cfg.Server.Mode == "debug" {
if config.Server.Mode == "debug" {
ginEngine.Use(gin.Logger())
}
ginEngine.Use(gin.Recovery())
@@ -156,7 +164,7 @@ func main() {
r.Setup(ginEngine)
// Create HTTP server
addr := fmt.Sprintf(":%d", cfg.Server.Port)
addr := fmt.Sprintf(":%d", config.Server.Port)
srv := &http.Server{
Addr: addr,
Handler: ginEngine,
@@ -172,12 +180,39 @@ func main() {
" /_/ |_|/_/ |_|\\____//_/ /_/ \\____/ |__/|__/\n",
)
logger.Info(fmt.Sprintf("Version: %s", utility.GetRAGFlowVersion()))
logger.Info(fmt.Sprintf("Server starting on port: %d", cfg.Server.Port))
logger.Info(fmt.Sprintf("Server starting on port: %d", config.Server.Port))
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logger.Fatal("Failed to start server", zap.Error(err))
}
}()
// Get local IP address for heartbeat reporting
localIP := utility.GetLocalIP()
if localIP == "" {
localIP = "127.0.0.1"
}
// Initialize and start heartbeat reporter to admin server
heartbeatService := service.NewHeartbeatSender(
logger.Logger,
common.ServerTypeAPI,
fmt.Sprintf("ragflow-server-%d", config.Server.Port),
localIP,
config.Server.Port,
)
if err := heartbeatService.InitHTTPClient(); err != nil {
logger.Warn("Failed to initialize heartbeat service", zap.Error(err))
} else {
// Start heartbeat reporter with 30 seconds interval
heartbeatReporter := utility.NewScheduledTask("Heartbeat reporter", 3*time.Second, func() {
if err := heartbeatService.SendHeartbeat(); err != nil {
logger.Warn("Failed to send heartbeat", zap.Error(err))
}
})
heartbeatReporter.Start()
defer heartbeatReporter.Stop()
}
// Wait for interrupt signal to gracefully shutdown
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGUSR2)
@@ -194,6 +229,4 @@ func main() {
if err := srv.Shutdown(ctx); err != nil {
logger.Fatal("Server forced to shutdown", zap.Error(err))
}
logger.Info("Server exited")
}