feat: gh-ost 平台配置开关键 + 云数据库参数支持
- ghost_enabled: 总开关, 关闭时返回403禁止dry-run/execute - ghost_path: gh-ost二进制路径, 从system_settings读取 - ghost_default_chunk_size: 每批拷贝行数 - ghost_max_load: 负载阈值限流 - ghost_allow_on_master: 单机MySQL允许直接执行 - handler改为从DB读配置, 不再依赖config包 - 5个配置项已插入system_settings(id=26-30)
This commit is contained in:
1 parent
8aaf2271b8
commit
5d59ca427e
1 file changed
+50
-9
@@ -3,17 +3,41 @@ package handler
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"sql-platform/config"
|
||||
"sql-platform/internal/ghost"
|
||||
"sql-platform/internal/model"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// getSetting reads a system_setting value by key
|
||||
func getSetting(key, fallback string) string {
|
||||
var s model.SystemSetting
|
||||
if model.DB.Where("`key` = ?", key).Take(&s).Error == nil && s.Value != "" {
|
||||
return s.Value
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
// isGhostEnabled checks if gh-ost is enabled in system settings
|
||||
func isGhostEnabled() bool {
|
||||
return getSetting("ghost_enabled", "true") == "true"
|
||||
}
|
||||
|
||||
// getGhostPath returns the gh-ost binary path from settings
|
||||
func getGhostPath() string {
|
||||
return getSetting("ghost_path", "gh-ost")
|
||||
}
|
||||
|
||||
// POST /api/v1/ghost/dry-run
|
||||
func GhOstDryRun(c *gin.Context) {
|
||||
if !isGhostEnabled() {
|
||||
c.JSON(http.StatusForbidden, gin.H{"detail": "gh-ost 功能已禁用,请在系统设置中开启"})
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
InstanceID int `json:"instance_id"`
|
||||
Database string `json:"database"`
|
||||
@@ -25,7 +49,6 @@ func GhOstDryRun(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Look up instance connection info
|
||||
task, err := buildGhOstTask(req.InstanceID, req.Database, req.Table, req.Alter)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"detail": err.Error()})
|
||||
@@ -33,8 +56,9 @@ func GhOstDryRun(c *gin.Context) {
|
||||
}
|
||||
task.DryRun = true
|
||||
task.Execute = false
|
||||
applyGhostSettings(task)
|
||||
|
||||
result, err := ghost.RunGhOst(c.Request.Context(), *task, config.C.GhOstPath)
|
||||
result, err := ghost.RunGhOst(c.Request.Context(), *task, getGhostPath())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, result)
|
||||
return
|
||||
@@ -51,12 +75,9 @@ func buildGhOstTask(instanceID int, database, table, alter string) (*ghost.GhOst
|
||||
if inst.DBType != "mysql" {
|
||||
return nil, fmt.Errorf("gh-ost only supports MySQL instances, got %s", inst.DBType)
|
||||
}
|
||||
// gh-ost needs separate host and port
|
||||
host := inst.Host
|
||||
port := inst.Port
|
||||
return &ghost.GhOstTask{
|
||||
Host: host,
|
||||
Port: port,
|
||||
Host: inst.Host,
|
||||
Port: inst.Port,
|
||||
User: inst.Username,
|
||||
Password: inst.Password,
|
||||
Database: database,
|
||||
@@ -65,8 +86,27 @@ func buildGhOstTask(instanceID int, database, table, alter string) (*ghost.GhOst
|
||||
}, nil
|
||||
}
|
||||
|
||||
// applyGhostSettings applies system_settings to the task (chunk-size, max-load, cloud flags)
|
||||
func applyGhostSettings(task *ghost.GhOstTask) {
|
||||
// Chunk size
|
||||
if cs, err := strconv.Atoi(getSetting("ghost_default_chunk_size", "1000")); err == nil && cs > 0 {
|
||||
task.ChunkSize = cs
|
||||
}
|
||||
// Max load
|
||||
if ml := getSetting("ghost_max_load", ""); ml != "" {
|
||||
task.MaxLoad = ml
|
||||
}
|
||||
// Allow on master
|
||||
task.AllowOnMaster = getSetting("ghost_allow_on_master", "true") == "true"
|
||||
}
|
||||
|
||||
// POST /api/v1/ghost/execute
|
||||
func GhOstExecute(c *gin.Context) {
|
||||
if !isGhostEnabled() {
|
||||
c.JSON(http.StatusForbidden, gin.H{"detail": "gh-ost 功能已禁用,请在系统设置中开启"})
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
InstanceID int `json:"instance_id"`
|
||||
Database string `json:"database"`
|
||||
@@ -85,8 +125,9 @@ func GhOstExecute(c *gin.Context) {
|
||||
}
|
||||
task.DryRun = false
|
||||
task.Execute = true
|
||||
applyGhostSettings(task)
|
||||
|
||||
taskID := ghost.RunGhOstAsync(*task, config.C.GhOstPath, nil)
|
||||
taskID := ghost.RunGhOstAsync(*task, getGhostPath(), nil)
|
||||
c.JSON(http.StatusAccepted, gin.H{
|
||||
"task_id": taskID,
|
||||
"message": "gh-ost execution started",
|
||||
|
||||
Reference in new issue
Block a user