Files
monibuca/plugin/cascade/pkg/server_runner.go
T
2026-03-24 21:41:33 +08:00

158 lines
4.5 KiB
Go

package cascade
import (
"time"
"m7s.live/v5/pkg/util"
"gorm.io/gorm"
)
// {{ AURA-X: M2 - 服务器运行状态追踪 }}
// ServerRunner 记录每台服务器的运行时间段(在线/离线),持久化到数据库
// ServerRunner 服务器运行状态追踪器
type ServerRunner struct {
records util.Collection[string, *ServerRunRecord] // quicAddr -> 运行记录(内存缓存)
db *gorm.DB // 数据库连接
}
// NewServerRunner 创建新的服务器运行追踪器
// {{ AURA-X: 将在 M3 的 FailoverController 中被调用 }}
func NewServerRunner(db *gorm.DB) *ServerRunner {
sr := &ServerRunner{
records: util.Collection[string, *ServerRunRecord]{},
db: db,
}
// {{ AURA-X: 自动迁移数据库表 }}
sr.db.AutoMigrate(&ServerRunRecord{})
// {{ AURA-X: 加载所有离线记录到内存(在线的只保留最新一条) }}
sr.loadFromDB()
return sr
}
// loadFromDB 从数据库加载记录到内存
// {{ AURA-X: 在线记录只保留最新的,离线记录全部加载 }}
func (sr *ServerRunner) loadFromDB() {
var allRecords []ServerRunRecord
sr.db.Order("start_time asc").Find(&allRecords)
// 按 quicAddr 分组,只保留每个服务器的最新记录
latestByServer := make(map[string]*ServerRunRecord)
for i := range allRecords {
record := &allRecords[i]
// 如果记录还未结束(在线),只保留最新的
if record.EndTime == nil {
if existing, ok := latestByServer[record.QuicAddr]; !ok || existing.StartTime.Before(record.StartTime) {
latestByServer[record.QuicAddr] = record
}
} else {
// 离线记录全部加载
sr.records.Set(record)
}
}
// 添加在线记录
for _, record := range latestByServer {
sr.records.Set(record)
}
}
// RecordStart 记录服务器开始运行(连接成功)
func (sr *ServerRunner) RecordStart(quicAddr string, priority int) {
now := time.Now()
// 如果已有记录且未结束,先结束它
if existing, ok := sr.records.Get(quicAddr); ok && existing.EndTime == nil {
existing.EndTime = &now
// {{ AURA-X: 更新数据库 }}
sr.db.Model(existing).Update("end_time", now)
}
// 创建新的运行记录
record := &ServerRunRecord{
QuicAddr: quicAddr,
Priority: priority,
StartTime: now,
EndTime: nil,
}
// {{ AURA-X: 保存到数据库 }}
sr.db.Create(record)
// {{ AURA-X: 添加到内存缓存 }}
sr.records.Set(record)
}
// RecordStop 记录服务器停止运行(断开连接)
func (sr *ServerRunner) RecordStop(quicAddr string) {
now := time.Now()
// 更新现有记录
if existing, ok := sr.records.Get(quicAddr); ok && existing.EndTime == nil {
existing.EndTime = &now
// {{ AURA-X: 更新数据库 }}
sr.db.Model(existing).Update("end_time", now)
// {{ AURA-X: 从内存缓存中移除(因为已离线) }}
sr.records.RemoveByKey(quicAddr)
}
}
// IsOnline 检查服务器是否在线
func (sr *ServerRunner) IsOnline(quicAddr string) bool {
if record, ok := sr.records.Get(quicAddr); ok {
return record.EndTime == nil
}
return false
}
// GetRecord 获取服务器的当前运行记录
func (sr *ServerRunner) GetRecord(quicAddr string) *ServerRunRecord {
if record, ok := sr.records.Get(quicAddr); ok {
return record
}
return nil
}
// GetAllRecords 获取所有历史运行记录
func (sr *ServerRunner) GetAllRecords() []ServerRunRecord {
var records []ServerRunRecord
sr.db.Order("start_time desc").Find(&records)
return records
}
// GetOnlineServers 获取当前所有在线服务器地址
func (sr *ServerRunner) GetOnlineServers() []string {
var online []string
sr.records.Range(func(record *ServerRunRecord) bool {
if record.EndTime == nil {
online = append(online, record.QuicAddr)
}
return true
})
return online
}
// QueryByTimeRange 查询指定时间范围内的运行记录
func (sr *ServerRunner) QueryByTimeRange(start, end time.Time) []ServerRunRecord {
var records []ServerRunRecord
sr.db.Where("start_time >= ? AND start_time <= ?", start, end).Order("start_time asc").Find(&records)
return records
}
// GetServerHistory 获取指定服务器的所有历史记录
func (sr *ServerRunner) GetServerHistory(quicAddr string) []ServerRunRecord {
var records []ServerRunRecord
sr.db.Where("quic_addr = ?", quicAddr).Order("start_time desc").Find(&records)
return records
}
// Clear 清除所有运行记录(仅用于测试)
func (sr *ServerRunner) Clear() {
sr.db.Where("1=1").Delete(&ServerRunRecord{})
sr.records = util.Collection[string, *ServerRunRecord]{}
}