124 lines
3.3 KiB
Go
124 lines
3.3 KiB
Go
package model
|
|
|
|
import (
|
|
"github.com/QuantumNous/new-api/common"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
const (
|
|
SystemInstanceStatusOnline = "online"
|
|
SystemInstanceStatusStale = "stale"
|
|
|
|
SystemInstanceStaleAfterSeconds int64 = 90
|
|
)
|
|
|
|
type SystemInstance struct {
|
|
NodeName string `json:"node_name" gorm:"type:varchar(128);primaryKey"`
|
|
Info string `json:"info" gorm:"type:text"`
|
|
StartedAt int64 `json:"started_at" gorm:"bigint;index"`
|
|
LastSeenAt int64 `json:"last_seen_at" gorm:"bigint;index"`
|
|
CreatedAt int64 `json:"created_at" gorm:"bigint;index"`
|
|
UpdatedAt int64 `json:"updated_at" gorm:"bigint;index"`
|
|
}
|
|
|
|
type SystemInstanceResponse struct {
|
|
NodeName string `json:"node_name"`
|
|
Status string `json:"status"`
|
|
StaleAfterSeconds int64 `json:"stale_after_seconds"`
|
|
StartedAt int64 `json:"started_at"`
|
|
LastSeenAt int64 `json:"last_seen_at"`
|
|
Info any `json:"info"`
|
|
}
|
|
|
|
func (instance *SystemInstance) BeforeCreate(_ *gorm.DB) error {
|
|
now := common.GetTimestamp()
|
|
if instance.CreatedAt == 0 {
|
|
instance.CreatedAt = now
|
|
}
|
|
if instance.UpdatedAt == 0 {
|
|
instance.UpdatedAt = now
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func UpsertSystemInstance(nodeName string, info any, startedAt int64, lastSeenAt int64) error {
|
|
infoText, err := marshalSystemInstanceInfo(info)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if lastSeenAt == 0 {
|
|
lastSeenAt = common.GetTimestamp()
|
|
}
|
|
instance := &SystemInstance{
|
|
NodeName: nodeName,
|
|
Info: infoText,
|
|
StartedAt: startedAt,
|
|
LastSeenAt: lastSeenAt,
|
|
UpdatedAt: lastSeenAt,
|
|
}
|
|
return DB.Clauses(clause.OnConflict{
|
|
Columns: []clause.Column{{Name: "node_name"}},
|
|
DoUpdates: clause.AssignmentColumns([]string{
|
|
"info",
|
|
"started_at",
|
|
"last_seen_at",
|
|
"updated_at",
|
|
}),
|
|
}).Create(instance).Error
|
|
}
|
|
|
|
func ListSystemInstances() ([]*SystemInstance, error) {
|
|
var instances []*SystemInstance
|
|
err := DB.Order("last_seen_at desc").Find(&instances).Error
|
|
return instances, err
|
|
}
|
|
|
|
func DeleteStaleSystemInstances(now int64) (int64, error) {
|
|
result := DB.Where("last_seen_at < ?", now-SystemInstanceStaleAfterSeconds).Delete(&SystemInstance{})
|
|
return result.RowsAffected, result.Error
|
|
}
|
|
|
|
func DeleteStaleSystemInstance(nodeName string, now int64) (bool, error) {
|
|
result := DB.Where("node_name = ? AND last_seen_at < ?", nodeName, now-SystemInstanceStaleAfterSeconds).Delete(&SystemInstance{})
|
|
return result.RowsAffected > 0, result.Error
|
|
}
|
|
|
|
func (instance *SystemInstance) ToResponse(now int64) SystemInstanceResponse {
|
|
status := SystemInstanceStatusOnline
|
|
if now-instance.LastSeenAt > SystemInstanceStaleAfterSeconds {
|
|
status = SystemInstanceStatusStale
|
|
}
|
|
return SystemInstanceResponse{
|
|
NodeName: instance.NodeName,
|
|
Status: status,
|
|
StaleAfterSeconds: SystemInstanceStaleAfterSeconds,
|
|
StartedAt: instance.StartedAt,
|
|
LastSeenAt: instance.LastSeenAt,
|
|
Info: decodeSystemInstanceInfo(instance.Info),
|
|
}
|
|
}
|
|
|
|
func marshalSystemInstanceInfo(v any) (string, error) {
|
|
if v == nil {
|
|
return "", nil
|
|
}
|
|
data, err := common.Marshal(v)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(data), nil
|
|
}
|
|
|
|
func decodeSystemInstanceInfo(data string) any {
|
|
if data == "" {
|
|
return nil
|
|
}
|
|
var value any
|
|
if err := common.UnmarshalJsonStr(data, &value); err != nil {
|
|
return data
|
|
}
|
|
return value
|
|
}
|