From 74866371effd386809aa2e113c1739565fe87440 Mon Sep 17 00:00:00 2001 From: Jin Hai Date: Wed, 18 Mar 2026 11:51:03 +0800 Subject: [PATCH] Fix compatiblity issue (#13667) ### What problem does this PR solve? 1. Change go admin server port from 9385 to 9383 to avoid conflicts 2. Start go server after python servers are started completely, in entrypoint.sh 3. Fix some database migration issue 4. Add more API routes in web to compliant with EE. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Signed-off-by: Jin Hai --- .github/workflows/tests.yml | 2 +- conf/service_conf.yaml | 2 ++ docker/.env | 2 +- docker/docker-compose.yml | 2 +- docker/entrypoint.sh | 20 ++++++++++++++++++++ internal/dao/database.go | 32 +++++++++++++++++++++++++++++++- internal/dao/migration.go | 12 ++++++++++-- internal/server/config.go | 4 ++-- web/vite.config.ts | 34 ++++++++++++++++++++++++++++++++-- 9 files changed, 100 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5837412929..c7315e5aa1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -187,7 +187,7 @@ jobs: ADMIN_SVR_HTTP_PORT=$((9381 + RUNNER_NUM * 10)) SVR_MCP_PORT=$((9382 + RUNNER_NUM * 10)) GO_HTTP_PORT=$((9384 + RUNNER_NUM * 10)) - GO_ADMIN_PORT=$((9385 + RUNNER_NUM * 10)) + GO_ADMIN_PORT=$((9383 + RUNNER_NUM * 10)) SANDBOX_EXECUTOR_MANAGER_PORT=$((9385 + RUNNER_NUM * 10)) SVR_WEB_HTTP_PORT=$((80 + RUNNER_NUM * 10)) SVR_WEB_HTTPS_PORT=$((443 + RUNNER_NUM * 10)) diff --git a/conf/service_conf.yaml b/conf/service_conf.yaml index b303d69ae7..6029f514fb 100644 --- a/conf/service_conf.yaml +++ b/conf/service_conf.yaml @@ -49,6 +49,8 @@ task_executor: user_default_llm: default_models: embedding_model: + name: 'bge-m3' + factory: 'xxxx' api_key: 'xxx' base_url: 'http://localhost:6380' # postgres: diff --git a/docker/.env b/docker/.env index 733689ccce..0440c5c012 100644 --- a/docker/.env +++ b/docker/.env @@ -153,7 +153,7 @@ SVR_HTTP_PORT=9380 ADMIN_SVR_HTTP_PORT=9381 SVR_MCP_PORT=9382 GO_HTTP_PORT=9384 -GO_ADMIN_PORT=9385 +GO_ADMIN_PORT=9383 # API_PROXY_SCHEME=hybrid # go and python hybrid deploy mode API_PROXY_SCHEME=python # use pure python server deployment diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 5214ee986b..945e5cf3fe 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -35,7 +35,7 @@ services: - ${ADMIN_SVR_HTTP_PORT}:9381 - ${SVR_MCP_PORT}:9382 # entry for MCP (host_port:docker_port). The docker_port must match the value you set for `mcp-port` above. - ${GO_HTTP_PORT}:9384 - - ${GO_ADMIN_PORT}:9385 + - ${GO_ADMIN_PORT}:9383 volumes: - ./ragflow-logs:/ragflow/logs - ./nginx/ragflow.conf:/etc/nginx/conf.d/ragflow.conf diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index b26b5034b1..b35a82d0a1 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -217,6 +217,24 @@ function ensure_db_init() { "$PY" -c "from api.db.db_models import init_database_tables as init_web_db; init_web_db()" } +function wait_for_server() { + local url="$1" + local server_name="$2" + local timeout=90 + local interval=2 + local start_time=$(date +%s) + + echo "Waiting for $server_name to be ready at $url..." + while ! curl -f -s -o /dev/null "$url"; do + if [ $(($(date +%s) - start_time)) -gt $timeout ]; then + echo "Timeout waiting for $server_name after $timeout seconds" + return 1 + fi + sleep $interval + done + echo "$server_name is ready." +} + # ----------------------------------------------------------------------------- # Start components based on flags # ----------------------------------------------------------------------------- @@ -232,6 +250,7 @@ if [[ "${ENABLE_WEBSERVER}" -eq 1 ]]; then "$PY" api/ragflow_server.py ${INIT_SUPERUSER_ARGS} & if [[ "${API_PROXY_SCHEME}" == "hybrid" ]]; then + wait_for_server "http://127.0.0.1:9380/healthz" "ragflow_server" echo "Starting RAGFlow server in hybrid mode..." bin/server_main & fi @@ -254,6 +273,7 @@ if [[ "${ENABLE_ADMIN_SERVER}" -eq 1 ]]; then while true; do "$PY" admin/server/admin_server.py & if [[ "${API_PROXY_SCHEME}" == "hybrid" ]]; then + wait_for_server "http://127.0.0.1:9381/api/v1/admin/ping" "admin_server" echo "Starting Admin server in hybrid mode..." bin/admin_server & fi diff --git a/internal/dao/database.go b/internal/dao/database.go index b0ef73d3d7..4050ed9d9d 100644 --- a/internal/dao/database.go +++ b/internal/dao/database.go @@ -22,6 +22,7 @@ import ( "log" "os" "path/filepath" + "strings" "time" "ragflow/internal/logger" @@ -29,6 +30,7 @@ import ( "ragflow/internal/server" "ragflow/internal/utility" + "go.uber.org/zap" gormLogger "gorm.io/gorm/logger" "gorm.io/driver/mysql" @@ -146,7 +148,7 @@ func InitDB() error { } for _, m := range models { - if err := DB.AutoMigrate(m); err != nil { + if err = autoMigrateSafely(DB, m); err != nil { return fmt.Errorf("failed to migrate model %T: %w", m, err) } } @@ -165,6 +167,34 @@ func GetDB() *gorm.DB { return DB } +// autoMigrateSafely runs AutoMigrate and ignores duplicate index errors +// This handles cases where indexes already exist (e.g., created by Python backend) +func autoMigrateSafely(db *gorm.DB, model interface{}) error { + err := db.AutoMigrate(model) + if err == nil { + return nil + } + + // Check if error is MySQL duplicate index error (Error 1061) + errStr := err.Error() + if strings.Contains(errStr, "Error 1061") && strings.Contains(errStr, "Duplicate key name") { + logger.Info("Index already exists, skipping", zap.String("error", errStr)) + return nil + } + + if strings.Contains(errStr, "Error 1060") && strings.Contains(errStr, "Duplicate column name") { + logger.Info("Column already exists, skipping", zap.String("error", errStr)) + return nil + } + + if strings.Contains(errStr, "Error 1050") && strings.Contains(errStr, "Table") { + logger.Info("Table already exists, skipping", zap.String("error", errStr)) + return nil + } + + return err +} + // InitLLMFactory initializes LLM factories and models from JSON file. // It reads the llm_factories.json configuration file and populates the database // with LLM factory and model information. If a factory or model already exists, diff --git a/internal/dao/migration.go b/internal/dao/migration.go index 4c2627d65d..2c0f4884bf 100644 --- a/internal/dao/migration.go +++ b/internal/dao/migration.go @@ -19,6 +19,7 @@ package dao import ( "fmt" "ragflow/internal/logger" + "strings" "go.uber.org/zap" "gorm.io/gorm" @@ -172,7 +173,14 @@ func migrateAddUniqueEmail(db *gorm.DB) error { } logger.Info("Adding unique index on user.email...") - if err := db.Exec(`ALTER TABLE user ADD UNIQUE INDEX idx_user_email_unique (email)`).Error; err != nil { + if err = db.Exec(`ALTER TABLE user ADD UNIQUE INDEX idx_user_email_unique (email)`).Error; err != nil { + + // Check if error is MySQL duplicate index error (Error 1061) + errStr := err.Error() + if strings.Contains(errStr, "Error 1061") && strings.Contains(errStr, "Duplicate key name") { + logger.Info("Index already exists, skipping", zap.String("error", errStr)) + return nil + } return fmt.Errorf("failed to add unique index on email: %w", err) } @@ -293,7 +301,7 @@ func addColumnIfNotExists(db *gorm.DB, tableName, columnName, columnDef string) // Check if column exists using raw SQL var count int64 - db.Raw(`SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS + db.Raw(`SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND COLUMN_NAME = ?`, tableName, columnName).Scan(&count) if count > 0 { return nil diff --git a/internal/server/config.go b/internal/server/config.go index 6bbd875979..98bc8bb75d 100644 --- a/internal/server/config.go +++ b/internal/server/config.go @@ -337,9 +337,9 @@ func Init(configPath string) error { globalConfig.Admin.Host = "127.0.0.1" } if globalConfig.Admin.Port == 0 { - globalConfig.Admin.Port = 9385 + globalConfig.Admin.Port = 9383 } else { - globalConfig.Admin.Port += 4 + globalConfig.Admin.Port += 2 } // Load REGISTER_ENABLED from environment variable (default: 1) diff --git a/web/vite.config.ts b/web/vite.config.ts index bca290b2f5..5c02fb5a6e 100644 --- a/web/vite.config.ts +++ b/web/vite.config.ts @@ -69,8 +69,38 @@ export default defineConfig(({ mode }) => { changeOrigin: true, ws: true, }, + '/api/v1/admin/roles': { + target: 'http://127.0.0.1:9381/', + changeOrigin: true, + ws: true, + }, + '/api/v1/admin/roles/owner/permission': { + target: 'http://127.0.0.1:9381/', + changeOrigin: true, + ws: true, + }, + '/api/v1/admin/roles_with_permission': { + target: 'http://127.0.0.1:9381/', + changeOrigin: true, + ws: true, + }, + '/api/v1/admin/whitelist': { + target: 'http://127.0.0.1:9381/', + changeOrigin: true, + ws: true, + }, + '/api/v1/admin/variables': { + target: 'http://127.0.0.1:9381/', + changeOrigin: true, + ws: true, + }, + '/api/v1/billing/current_plan': { + target: 'http://127.0.0.1:9381/', + changeOrigin: true, + ws: true, + }, '/api/v1/admin': { - target: 'http://127.0.0.1:9385/', + target: 'http://127.0.0.1:9383/', changeOrigin: true, ws: true, }, @@ -87,7 +117,7 @@ export default defineConfig(({ mode }) => { }, go: { '/api/v1/admin': { - target: 'http://127.0.0.1:9385/', + target: 'http://127.0.0.1:9383/', changeOrigin: true, ws: true, },