Files
ragflow/cmd/ingestion_server.go
qinling0210 c960dc2a4c Refine handling of POST /api/v1/datasets/search in GO (#15583)
### What problem does this PR solve?

Refine handling of POST /api/v1/datasets/search in GO

### Type of change

- [x] Refactoring
2026-06-08 11:49:37 +08:00

191 lines
6.6 KiB
Go

//
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package main
import (
"context"
"flag"
"fmt"
"os"
"os/signal"
"ragflow/internal/ingestion"
"ragflow/internal/service/nlp"
"ragflow/internal/tokenizer"
"ragflow/internal/utility"
"syscall"
"time"
"ragflow/internal/cache"
"ragflow/internal/common"
"ragflow/internal/dao"
"ragflow/internal/engine"
"ragflow/internal/server"
"ragflow/internal/storage"
"go.uber.org/zap"
)
func printIngestionServerHelp() {
fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS]\n\n", os.Args[0])
fmt.Fprintf(os.Stderr, "RAGFlow Ingestion Worker - Document ingestion processing\n\n")
fmt.Fprintf(os.Stderr, "Options:\n")
fmt.Fprintf(os.Stderr, " -f string\t\tPath to config file (default: auto-detect)\n")
fmt.Fprintf(os.Stderr, " --name string\t\tIngestion server name (default: \"default_ingestion\")\n")
fmt.Fprintf(os.Stderr, " --admin-host string\tAdmin server host (overrides config file)\n")
fmt.Fprintf(os.Stderr, " --admin-port int\tAdmin server port (overrides config file)\n")
fmt.Fprintf(os.Stderr, " -h, --help\t\tShow this help message and exit\n")
fmt.Fprintf(os.Stderr, "\nExamples:\n")
fmt.Fprintf(os.Stderr, " %s # Start with default config\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s -f /path/to/config.yaml # Start with custom config file\n", os.Args[0])
fmt.Fprintf(os.Stderr, " %s --admin-host 10.0.0.1 --admin-port 9383\n", os.Args[0])
}
func main() {
// Parse command line flags
var configPath string
var name string
var adminHost string
var adminPort int
flag.StringVar(&configPath, "f", "", "Path to config file (overrides auto-detect)")
flag.StringVar(&name, "name", "default_ingestion", "Ingestion server name")
flag.StringVar(&adminHost, "admin-host", "", "Admin server host (overrides config file)")
flag.IntVar(&adminPort, "admin-port", 0, "Admin server port (overrides config file)")
// Custom help message
flag.Usage = printIngestionServerHelp
flag.Parse()
// Initialize logger with default level
if err := common.Init("info", "ingestion_server.log"); err != nil {
panic(fmt.Sprintf("Failed to initialize logger: %v", err))
}
// Initialize configuration
if err := server.Init(configPath); err != nil {
common.Fatal("Failed to initialize config", zap.Error(err))
}
config := server.GetConfig()
// Override admin server host with command line argument if provided
if adminHost != "" {
config.Admin.Host = adminHost
common.Info("Admin host overridden by command line argument", zap.String("admin_host", adminHost))
}
// Override admin server port with command line argument if provided
if adminPort > 0 {
config.Admin.Port = adminPort
common.Info("Admin port overridden by command line argument", zap.Int("admin_port", adminPort))
}
// Reinitialize logger with configured level if different
level := config.Log.Level
if level == "" {
level = "info"
}
if err := common.Init(level, "ingestion_server.log"); err != nil {
common.Error("Failed to reinitialize logger", err)
}
server.SetLogger(common.Logger)
common.Info("Starting RAGFlow Ingestion Worker")
// Initialize database
if err := dao.InitDB(); err != nil {
common.Fatal("Failed to initialize database", zap.Error(err))
}
// Initialize doc engine
if err := engine.Init(&config.DocEngine); err != nil {
common.Fatal("Failed to initialize doc engine", zap.Error(err))
}
defer engine.Close()
// Initialize Redis cache
if err := cache.Init(&config.Redis); err != nil {
common.Fatal("Failed to initialize Redis", zap.Error(err))
}
defer cache.Close()
// Initialize storage factory
if err := storage.InitStorageFactory(); err != nil {
common.Fatal("Failed to initialize storage factory", zap.Error(err))
}
// Initialize server variables (runtime variables from Redis)
if err := server.InitVariables(cache.Get()); err != nil {
common.Warn("Failed to initialize server variables from Redis, using defaults", zap.String("error", err.Error()))
}
// Initialize tokenizer (rag_analyzer)
tokenizerCfg := &tokenizer.PoolConfig{
DictPath: "/usr/share/infinity/resource",
}
if err := tokenizer.Init(tokenizerCfg); err != nil {
common.Fatal("Failed to initialize tokenizer", zap.Error(err))
}
defer tokenizer.Close()
// Initialize global QueryBuilder using tokenizer's DictPath
if err := nlp.InitQueryBuilderFromTokenizer(tokenizerCfg.DictPath); err != nil {
common.Fatal("Failed to initialize query builder", zap.Error(err))
}
ingestor := ingestion.NewIngestor(name, 2, []string{"pdf", "docx", "txt"})
// Connect to the admin server
serverAddress := fmt.Sprintf("%s:%d", config.Admin.Host, config.Admin.IngestionManagerPort)
if err := ingestor.Connect(serverAddress); err != nil {
common.Fatal(fmt.Sprintf("Error: %s", err.Error()))
}
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGUSR2)
// Print all configuration settings
server.PrintAll()
common.Info("\n ____ __ _\n" +
" / _/___ ____ ____ _____/ /_(_)___ ____ ________ ______ _____ _____\n" +
" / // __ \\/ __ `/ _ \\/ ___/ __/ / __ \\/ __ \\ / ___/ _ \\/ ___/ | / / _ \\/ ___/\n" +
" _/ // / / / /_/ / __(__ ) /_/ / /_/ / / / / (__ ) __/ / | |/ / __/ /\n" +
"/___/_/ /_/\\__, /\\___/____/\\__/_/\\____/_/ /_/ /____/\\___/_/ |___/\\___/_/\n" +
" /____/\n")
// Print RAGFlow version
common.Info(fmt.Sprintf("RAGFlow admin version: %s", utility.GetRAGFlowVersion()))
// Wait for either an OS signal or a shutdown command from the admin
select {
case sig := <-quit:
common.Info("Received signal", zap.String("signal", sig.String()))
common.Info(fmt.Sprintf("Shutting down RAGFlow ingestor %s ...", name))
case <-ingestor.ShutdownCh:
common.Info(fmt.Sprintf("Received shutdown command from admin, stopping ingestor %s ...", name))
}
// Create context with timeout for graceful shutdown
_, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
ingestor.Stop()
common.Info(fmt.Sprintf("Ingestor %s shutdown complete", name))
}