feat: 添加数据库集成、定时任务调度器和事件Hook体系

- 新增数据库配置项(DB_TYPE, DB_HOST, DB_PORT等),支持MySQL和PostgreSQL
- 集成GORM实现数据库连接和自动迁移功能
- 添加定时任务调度器(cmd/scheduler),基于robfig/cron实现秒级调度
- 实现事件Hook体系,支持同步/异步处理和优先级排序
- 更新构建脚本,编译server、cli、scheduler三个二进制文件
- 配置systemd服务管理定时任务调度器
- 重构项目结构,新增crontab和hooks目录模块
- 更新README文档,完善各组件使用说明和部署配置
This commit is contained in:
shiran
2026-04-15 12:39:59 +08:00
parent 6050d11f27
commit aa9f892a32
22 changed files with 753 additions and 141 deletions
+11
View File
@@ -0,0 +1,11 @@
package db
import "gorm.io/gorm"
// HostGroup 主机组
type HostGroup struct {
gorm.Model
Name string `json:"name" gorm:"not null;comment:主机组名称;index"`
Description string `json:"description" gorm:"null;comment:主机组描述;index"`
ParentID uint `json:"parent_id" gorm:"null;comment:父级ID;index"`
}
+100
View File
@@ -0,0 +1,100 @@
package db
import (
"apiServer_service/utils/logger"
"fmt"
"os"
"sync"
"time"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var (
DB *gorm.DB
once sync.Once
)
func ConnectDatabase() {
once.Do(func() {
dbType := os.Getenv("DB_TYPE")
dbUser := os.Getenv("DB_USER")
dbPassword := os.Getenv("DB_PASSWORD")
dbName := os.Getenv("DB_NAME")
dbHost := os.Getenv("DB_HOST")
dbPort := os.Getenv("DB_PORT")
if dbType == "" {
logger.Warn("Database", "DB_TYPE 未配置,跳过数据库连接")
return
}
var dialector gorm.Dialector
switch dbType {
case "mysql":
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
dbUser, dbPassword, dbHost, dbPort, dbName)
dialector = mysql.Open(dsn)
case "postgres":
dbSchema := os.Getenv("DB_SCHEMA")
if dbSchema == "" {
dbSchema = "public"
}
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Shanghai search_path=%s",
dbHost, dbUser, dbPassword, dbName, dbPort, dbSchema)
dialector = postgres.Open(dsn)
default:
logger.Fatal("Database", fmt.Sprintf("不支持的 DB_TYPE: %s(仅支持 mysql / postgres", dbType))
return
}
conn, err := gorm.Open(dialector, &gorm.Config{})
if err != nil {
logger.Fatal("Database", "连接失败: ", err)
return
}
sqlDB, err := conn.DB()
if err != nil {
logger.Fatal("Database", "获取底层连接池失败: ", err)
return
}
sqlDB.SetMaxOpenConns(50)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetConnMaxLifetime(30 * time.Minute)
sqlDB.SetConnMaxIdleTime(10 * time.Minute)
DB = conn
logger.Info("Database", fmt.Sprintf("连接成功 (%s)", dbType))
})
}
func GetDB() *gorm.DB {
if DB == nil {
ConnectDatabase()
}
return DB
}
// Migrate 自动迁移所有模型,新增模型在此注册
func Migrate() {
if DB == nil {
logger.Warn("Database", "数据库未连接,跳过迁移")
return
}
models := []interface{}{
&HostGroup{},
}
for _, model := range models {
if err := DB.AutoMigrate(model); err != nil {
logger.Error("Database", fmt.Sprintf("迁移 %T 失败: %v", model, err))
} else {
logger.Info("Database", fmt.Sprintf("迁移 %T 完成", model))
}
}
}