浏览代码

Merge pull request #445 from flipped-aurora/gva_gormv2_dev

Gva gormv2 dev
奇淼(piexlmax 3 年之前
父节点
当前提交
137143a7ed

+ 14 - 1
server/config.yaml

@@ -114,4 +114,17 @@ tencent-cos:
 
 # excel configuration
 excel:
-  dir: './resource/excel/'
+  dir: './resource/excel/'
+
+
+# timer task db clear table
+Timer:
+  spec: "@daily"  # 定时任务详细配置参考 https://pkg.go.dev/github.com/robfig/cron?utm_source=godoc
+  detail: [
+    # tableName: 需要清理的表名
+    # compareField: 需要比较时间的字段
+    # interval: 时间间隔, 具体配置详看 time.ParseDuration() 中字符串表示 且不能为负数
+    # 2160h = 24 * 30 * 3 -> 三个月
+    { tableName: "sys_operation_records" , compareField: "created_at", interval: "2160h" },
+    #{ tableName: "log2" , compareField: "created_at", interval: "2160h" }
+  ]

+ 1 - 0
server/config/config.go

@@ -18,4 +18,5 @@ type Server struct {
 	AliyunOSS  AliyunOSS  `mapstructure:"aliyun-oss" json:"aliyunOSS" yaml:"aliyun-oss"`
 	TencentCOS TencentCOS `mapstructure:"tencent-cos" json:"tencentCOS" yaml:"tencent-cos"`
 	Excel      Excel      `mapstructure:"excel" json:"excel" yaml:"excel"`
+	Timer      Timer      `mapstructure:"timer" json:"timer" yaml:"timer"`
 }

+ 13 - 0
server/config/timer.go

@@ -0,0 +1,13 @@
+package config
+
+type Timer struct {
+	Start  bool     `mapstructure:"start" json:"start" yaml:"start"`
+	Spec   string   `mapstructure:"spec" json:"spec" yaml:"spec"`
+	Detail []Detail `mapstructure:"detail" json:"detail" yaml:"detail"`
+}
+
+type Detail struct {
+	TableName    string `mapstructure:"tableName" json:"tableName" yaml:"tableName"`
+	CompareField string `mapstructure:"compareField" json:"compareField" yaml:"compareField"`
+	Interval     string `mapstructure:"interval" json:"interval" yaml:"interval"`
+}

+ 5 - 1
server/global/global.go

@@ -1,9 +1,12 @@
 package global
 
 import (
+	"gin-vue-admin/utils/timer"
+
 	"go.uber.org/zap"
 
 	"gin-vue-admin/config"
+
 	"github.com/go-redis/redis"
 	"github.com/spf13/viper"
 	"gorm.io/gorm"
@@ -15,5 +18,6 @@ var (
 	GVA_CONFIG config.Server
 	GVA_VP     *viper.Viper
 	//GVA_LOG    *oplogging.Logger
-	GVA_LOG *zap.Logger
+	GVA_LOG   *zap.Logger
+	GVA_Timer timer.Timer = timer.NewTimerTask()
 )

+ 1 - 0
server/go.mod

@@ -36,6 +36,7 @@ require (
 	github.com/pelletier/go-toml v1.6.0 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/qiniu/api.v7/v7 v7.4.1
+	github.com/robfig/cron/v3 v3.0.1
 	github.com/satori/go.uuid v1.2.0
 	github.com/shirou/gopsutil v3.21.1+incompatible
 	github.com/spf13/afero v1.2.2 // indirect

+ 24 - 0
server/initialize/timer.go

@@ -0,0 +1,24 @@
+package initialize
+
+import (
+	"fmt"
+	"gin-vue-admin/config"
+	"gin-vue-admin/global"
+	"gin-vue-admin/utils"
+)
+
+func Timer() {
+	if global.GVA_CONFIG.Timer.Start {
+		for _, detail := range global.GVA_CONFIG.Timer.Detail {
+			fmt.Println(detail)
+			go func(detail config.Detail) {
+				global.GVA_Timer.AddTaskByFunc("ClearDB", global.GVA_CONFIG.Timer.Spec, func() {
+					err := utils.ClearTable(global.GVA_DB, detail.TableName, detail.CompareField, detail.Interval)
+					if err != nil {
+						fmt.Println("timer error:", err)
+					}
+				})
+			}(detail)
+		}
+	}
+}

+ 1 - 0
server/main.go

@@ -17,6 +17,7 @@ func main() {
 	global.GVA_VP = core.Viper()      // 初始化Viper
 	global.GVA_LOG = core.Zap()       // 初始化zap日志库
 	global.GVA_DB = initialize.Gorm() // gorm连接数据库
+	initialize.Timer()
 	if global.GVA_DB != nil {
 		initialize.MysqlTables(global.GVA_DB) // 初始化表
 		// 程序结束前关闭数据库链接

+ 1 - 2
server/service/sys_casbin.go

@@ -90,8 +90,7 @@ func ClearCasbin(v int, p ...string) bool {
 //@return: *casbin.Enforcer
 
 func Casbin() *casbin.Enforcer {
-	admin := global.GVA_CONFIG.Mysql
-	a, _ := gormadapter.NewAdapter(global.GVA_CONFIG.System.DbType, admin.Username+":"+admin.Password+"@("+admin.Path+")/"+admin.Dbname, true)
+	a, _ := gormadapter.NewAdapterByDB(global.GVA_DB)
 	e, _ := casbin.NewEnforcer(global.GVA_CONFIG.Casbin.ModelPath, a)
 	e.AddFunction("ParamsMatch", ParamsMatchFunc)
 	_ = e.LoadPolicy()

+ 8 - 2
server/service/sys_initdb.go

@@ -41,7 +41,12 @@ func createTable(dsn string, driver string, createSql string) error {
 	if err != nil {
 		return err
 	}
-	defer db.Close()
+	defer func(db *sql.DB) {
+		err := db.Close()
+		if err != nil {
+
+		}
+	}(db)
 	if err = db.Ping(); err != nil {
 		return err
 	}
@@ -82,7 +87,6 @@ func InitDB(conf request.InitDB) error {
 		conf.Port = "3306"
 	}
 	dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/", conf.UserName, conf.Password, conf.Host, conf.Port)
-	fmt.Println(dsn)
 	createSql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;", conf.DBName)
 	if err := createTable(dsn, "mysql", createSql); err != nil {
 		return err
@@ -117,6 +121,7 @@ func InitDB(conf request.InitDB) error {
 		//global.GVA_LOG.Error("MySQL启动异常", zap.Any("err", err))
 		//os.Exit(0)
 		//return nil
+		_ = writeConfig(global.GVA_VP, BaseMysql)
 		return nil
 	} else {
 		sqlDB, _ := db.DB()
@@ -142,6 +147,7 @@ func InitDB(conf request.InitDB) error {
 		model.SysOperationRecord{},
 	)
 	if err != nil {
+		_ = writeConfig(global.GVA_VP, BaseMysql)
 		return err
 	}
 	err = initDB(

+ 29 - 0
server/utils/db_automation.go

@@ -0,0 +1,29 @@
+package utils
+
+import (
+	"errors"
+	"fmt"
+	"time"
+
+	"gorm.io/gorm"
+)
+
+//@author: [songzhibin97](https://github.com/songzhibin97)
+//@function: ClearTable
+//@description: 清理数据库表数据
+//@param: target db(数据库对象) *gorm.DB,tableName(表名) string,compareField(比较字段) string , interval string  间隔
+//@return: err
+
+func ClearTable(db *gorm.DB, tableName string, compareField string, interval string) error {
+	if db == nil {
+		return errors.New("db Cannot be empty")
+	}
+	duration, err := time.ParseDuration(interval)
+	if err != nil {
+		return err
+	}
+	if duration < 0 {
+		return errors.New("parse duration < 0")
+	}
+	return db.Debug().Exec(fmt.Sprintf("DELETE FROM %s WHERE %s < ?", tableName, compareField), time.Now().Add(-duration)).Error
+}

+ 109 - 0
server/utils/timer/timed_task.go

@@ -0,0 +1,109 @@
+package timer
+
+import (
+	"sync"
+
+	"github.com/robfig/cron/v3"
+)
+
+type Timer interface {
+	AddTaskByFunc(taskName string, spec string, task func()) (cron.EntryID, error)
+	AddTaskByJob(taskName string, spec string, job interface{ Run() }) (cron.EntryID, error)
+	FindCron(taskName string) (*cron.Cron, bool)
+	StartTask(taskName string)
+	StopTask(taskName string)
+	Remove(taskName string, id int)
+	Clear(taskName string)
+	Close()
+}
+
+// timer 定时任务管理
+type timer struct {
+	taskList map[string]*cron.Cron
+	sync.Mutex
+}
+
+// AddTaskByFunc 通过函数的方法添加任务
+func (t *timer) AddTaskByFunc(taskName string, spec string, task func()) (cron.EntryID, error) {
+	t.Lock()
+	defer t.Unlock()
+	if _, ok := t.taskList[taskName]; !ok {
+		t.taskList[taskName] = cron.New()
+	}
+	id, err := t.taskList[taskName].AddFunc(spec, task)
+	t.taskList[taskName].Start()
+	return id, err
+}
+
+// AddTaskByJob 通过接口的方法添加任务
+func (t *timer) AddTaskByJob(taskName string, spec string, job interface{ Run() }) (cron.EntryID, error) {
+	t.Lock()
+	defer t.Unlock()
+	if _, ok := t.taskList[taskName]; !ok {
+		t.taskList[taskName] = cron.New()
+	}
+	id, err := t.taskList[taskName].AddJob(spec, job)
+	t.taskList[taskName].Start()
+	return id, err
+}
+
+// FindCron 获取对应taskName的cron 可能会为空
+func (t *timer) FindCron(taskName string) (*cron.Cron, bool) {
+	t.Lock()
+	defer t.Unlock()
+	v, ok := t.taskList[taskName]
+	return v, ok
+}
+
+// StartTask 开始任务
+func (t *timer) StartTask(taskName string) {
+	t.Lock()
+	defer t.Unlock()
+	if v, ok := t.taskList[taskName]; ok {
+		v.Start()
+	}
+	return
+}
+
+// StopTask 停止任务
+func (t *timer) StopTask(taskName string) {
+	t.Lock()
+	defer t.Unlock()
+	if v, ok := t.taskList[taskName]; ok {
+		v.Stop()
+	}
+	return
+}
+
+// Remove 从taskName 删除指定任务
+func (t *timer) Remove(taskName string, id int) {
+	t.Lock()
+	defer t.Unlock()
+	if v, ok := t.taskList[taskName]; ok {
+		v.Remove(cron.EntryID(id))
+	}
+	return
+}
+
+// Clear 清除任务
+func (t *timer) Clear(taskName string) {
+	t.Lock()
+	defer t.Unlock()
+	if v, ok := t.taskList[taskName]; ok {
+		v.Stop()
+		delete(t.taskList, taskName)
+	}
+}
+
+// Close 释放资源
+func (t *timer) Close() {
+	t.Lock()
+	defer t.Unlock()
+	for _, v := range t.taskList {
+		v.Stop()
+	}
+}
+
+func NewTimerTask() Timer {
+	return &timer{taskList: make(map[string]*cron.Cron)}
+}