feat: add expiration handling for database entries and enhance user model with rules

This commit is contained in:
krau
2025-04-12 11:14:13 +08:00
parent 50fba3f910
commit 3bdef20e85
4 changed files with 59 additions and 11 deletions

View File

@@ -37,7 +37,8 @@ type logConfig struct {
}
type dbConfig struct {
Path string `toml:"path" mapstructure:"path"`
Path string `toml:"path" mapstructure:"path"`
Expire int64 `toml:"expire" mapstructure:"expire"`
}
type telegramConfig struct {
@@ -93,6 +94,7 @@ func Init() error {
viper.SetDefault("log.backup_count", 7)
viper.SetDefault("db.path", "data/saveany.db")
viper.SetDefault("db.expire", 86400*5)
if err := viper.SafeWriteConfigAs("config.toml"); err != nil {
if _, ok := err.(viper.ConfigFileAlreadyExistsError); !ok {

View File

@@ -1,6 +1,7 @@
package dao
import (
"errors"
"fmt"
"os"
"path/filepath"
@@ -17,8 +18,7 @@ var db *gorm.DB
func Init() {
if err := os.MkdirAll(filepath.Dir(config.Cfg.DB.Path), 0755); err != nil {
common.Log.Fatal("Failed to create data directory: ", err)
os.Exit(1)
common.Log.Panic("Failed to create data directory: ", err)
}
var err error
db, err = gorm.Open(sqlite.Open(config.Cfg.DB.Path), &gorm.Config{
@@ -32,17 +32,25 @@ func Init() {
PrepareStmt: true,
})
if err != nil {
common.Log.Fatal("Failed to open database: ", err)
os.Exit(1)
common.Log.Panic("Failed to open database: ", err)
}
common.Log.Debug("Database connected")
if err := db.AutoMigrate(&ReceivedFile{}, &User{}, &Dir{}, &CallbackData{}); err != nil {
common.Log.Fatal("迁移数据库失败, 如果您从旧版本升级, 建议手动删除数据库文件后重试: ", err)
if err := db.AutoMigrate(&ReceivedFile{}, &User{}, &Dir{}, &CallbackData{}, &Rule{}); err != nil {
common.Log.Panic("迁移数据库失败, 如果您从旧版本升级, 建议手动删除数据库文件后重试: ", err)
}
if err := syncUsers(); err != nil {
common.Log.Fatal("Failed to sync users:", err)
common.Log.Panic("Failed to sync users:", err)
}
common.Log.Debug("Database migrated")
if config.Cfg.DB.Expire == 0 {
return
}
if err := cleanExpiredData(db); err != nil {
common.Log.Error("Failed to clean expired data: ", err)
} else {
common.Log.Debug("Cleaned expired data")
}
go cleanJob(db)
}
func syncUsers() error {
@@ -81,3 +89,27 @@ func syncUsers() error {
return nil
}
func cleanExpiredData(db *gorm.DB) error {
var fileErr error
if err := db.Where("updated_at < ?", time.Now().Add(-time.Duration(config.Cfg.DB.Expire)*time.Second)).Unscoped().Delete(&ReceivedFile{}).Error; err != nil {
fileErr = fmt.Errorf("failed to delete expired files: %w", err)
}
var cbErr error
if err := db.Where("updated_at < ?", time.Now().Add(-time.Duration(config.Cfg.DB.Expire)*time.Second)).Unscoped().Delete(&CallbackData{}).Error; err != nil {
cbErr = fmt.Errorf("failed to delete expired callback data: %w", err)
}
return errors.Join(fileErr, cbErr)
}
func cleanJob(db *gorm.DB) {
tick := time.NewTicker(time.Duration(config.Cfg.DB.Expire) * time.Second)
defer tick.Stop()
for range tick.C {
if err := cleanExpiredData(db); err != nil {
common.Log.Error("Failed to clean expired data: ", err)
} else {
common.Log.Debug("Cleaned expired data")
}
}
}

View File

@@ -24,6 +24,8 @@ type User struct {
Silent bool
DefaultStorage string // Default storage name
Dirs []Dir
ApplyRule bool
Rules []Rule
}
type Dir struct {
@@ -37,3 +39,12 @@ type CallbackData struct {
gorm.Model
Data string
}
type Rule struct {
gorm.Model
UserID uint
Type string
Data string
StorageName string
DirPath string
}

View File

@@ -9,7 +9,9 @@ func CreateUser(chatID int64) error {
func GetAllUsers() ([]User, error) {
var users []User
err := db.Preload("Dirs").Find(&users).Error
err := db.Preload("Dirs").
Preload("Rules").
Find(&users).Error
return users, err
}
@@ -17,6 +19,7 @@ func GetUserByChatID(chatID int64) (*User, error) {
var user User
err := db.
Preload("Dirs").
Preload("Rules").
Where("chat_id = ?", chatID).First(&user).Error
return &user, err
}
@@ -26,5 +29,5 @@ func UpdateUser(user *User) error {
}
func DeleteUser(user *User) error {
return db.Unscoped().Select("Dirs").Delete(user).Error
return db.Unscoped().Select("Dirs", "Rules").Delete(user).Error
}