From d9e622e37b4670e6dcbd28021a3492e4f33339a0 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Wed, 6 Nov 2024 15:13:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AE=9A=E6=97=B6=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8F=8A=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dao/cid.go | 22 ++++++++++++++---- go.mod | 1 + go.sum | 2 ++ handler/cid.go | 59 ++++++++++++++++++++++++++++++++++++++++++++--- main.go | 16 +++++++++++++ proto/user_req.go | 6 +++++ 6 files changed, 99 insertions(+), 7 deletions(-) diff --git a/dao/cid.go b/dao/cid.go index f6872ea..6233dc6 100644 --- a/dao/cid.go +++ b/dao/cid.go @@ -10,6 +10,7 @@ type CID struct { Auth_id int `gorm:"column:auth_id"` Name string `gorm:"column:name"` Url string `gorm:"column:url"` + Time int `gorm:"column:time"` // 定时任务,单位秒,大于0表示定时任务 Script string `gorm:"column:script"` Token string `gorm:"column:token"` // 用于外部回调 } @@ -24,8 +25,8 @@ type CIDRunLog struct { } // CreateCID 创建持续集成、部署 -func CreateCID(name, url, script, token string, auth_id int) uint { - cid := CID{Name: name, Url: url, Script: script, Token: token, Auth_id: auth_id} +func CreateCID(name, url, script, token string, time, auth_id int) uint { + cid := CID{Name: name, Url: url, Script: script, Token: token, Auth_id: auth_id, Time: time} result := DB.Debug().Create(&cid) if result.Error != nil { return 0 @@ -57,7 +58,7 @@ func FindCIDByAuthID(auth_id int) []CID { } // UpdateCIDByID 更新持续集成、部署 -func UpdateCIDByID(id, auth_id int, name, url, script, token string) bool { +func UpdateCIDByID(id, auth_id, time int, name, url, script, token string) bool { pd := FindCIDByID(id, auth_id) if pd.ID == 0 { return false @@ -66,7 +67,7 @@ func UpdateCIDByID(id, auth_id int, name, url, script, token string) bool { if token == "" { token = pd.Token } - result := DB.Debug().Model(&CID{}).Where("id = ? and auth_id = ?", id, auth_id).Updates(CID{Name: name, Url: url, Script: script, Token: token}) + result := DB.Debug().Model(&CID{}).Where("id = ? and auth_id = ?", id, auth_id).Updates(CID{Name: name, Url: url, Script: script, Token: token, Time: time}) if result.Error != nil { return false } @@ -106,3 +107,16 @@ func FindCIDByIDAndToken(id int, token string) CID { DB.Debug().Where("id = ? and token = ?", id, token).First(&cid) return cid } + +func FindCIDByTime() []CID { + var cids []CID + DB.Debug().Where("time > 0").Find(&cids) + return cids +} + +// FindCIDByID 查找持续集成、部署 +func FindCIDByCID(id uint) CID { + var cid CID + DB.Debug().Where("id = ? ", id).First(&cid) + return cid +} diff --git a/go.mod b/go.mod index d311974..b324382 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/golang-jwt/jwt v3.2.2+incompatible github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 + github.com/robfig/cron/v3 v3.0.1 gorm.io/driver/mysql v1.5.6 gorm.io/driver/postgres v1.5.9 gorm.io/gorm v1.25.10 diff --git a/go.sum b/go.sum index ff6741f..40ddc6a 100644 --- a/go.sum +++ b/go.sum @@ -86,6 +86,8 @@ github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6 github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/handler/cid.go b/handler/cid.go index 2e5994c..cd1010d 100644 --- a/handler/cid.go +++ b/handler/cid.go @@ -2,6 +2,7 @@ package handler import ( "bytes" + "encoding/json" "fmt" "github.com/gin-gonic/gin" "os/exec" @@ -9,11 +10,13 @@ import ( "strings" "videoplayer/dao" "videoplayer/proto" + "videoplayer/worker" ) type CIDCreateReq struct { Name string `json:"name" form:"name"` Url string `json:"url" form:"url"` + Time int `json:"time" form:"time"` // 定时任务,单位秒,大于0表示定时任务 Script string `json:"script" form:"script"` } @@ -33,6 +36,7 @@ type CIDUpdateReq struct { ID int `json:"id" form:"id"` Name string `json:"name" form:"name"` Url string `json:"url" form:"url"` + Time int `json:"time" form:"time"` // 定时任务,单位秒,大于0表示定时任务 Script string `json:"script" form:"script"` Token string `json:"cidtoken" form:"cidtoken"` } @@ -82,8 +86,7 @@ func CreateCID(c *gin.Context) { id, _ := c.Get("id") authID := int(id.(float64)) token, _ := generateRandomHexString(32) - - res := dao.CreateCID(req.Name, req.Url, req.Script, token, authID) + res := dao.CreateCID(req.Name, req.Url, req.Script, token, req.Time, authID) if res != 0 { c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": res}) } else { @@ -118,7 +121,7 @@ func UpdateCID(c *gin.Context) { // 获取用户ID id, _ := c.Get("id") authID := int(id.(float64)) - cid := dao.UpdateCIDByID(req.ID, authID, req.Name, req.Url, req.Script, req.Token) + cid := dao.UpdateCIDByID(req.ID, authID, req.Time, req.Name, req.Url, req.Script, req.Token) if cid == false { c.JSON(200, gin.H{"error": "CID not found", "code": proto.OperationFailed, "message": "failed"}) return @@ -222,3 +225,53 @@ echo "end"` //fmt.Println("bash content:", scriptContent) dao.CreateRunLog(id, authID, scriptContent, out.String(), err3_info) //添加执行日志 } + +// 定时任务处理逻辑 +func RunCron() { + //从redis查看是否有定时任务 + //如果有定时任务,执行定时任务 + //如果没有定时任务,查找数据库是否有定时任务,如果有,则加入redis,如果没有,则不做任何操作 + key := "cron_cid_runs" + res := worker.GetRedis(key) + if res == "" { + cids := dao.FindCIDByTime() + cid_workers := make([]proto.CIDRUN, 0) + for _, v := range cids { + cid_worker := proto.CIDRUN{CID: v.ID, Curr: v.Time, Every: v.Time} + cid_workers = append(cid_workers, cid_worker) + } + if len(cid_workers) > 0 { + //将定时任务加入redis + json_data, err := json.Marshal(cid_workers) + if err != nil { + fmt.Println("json marshal failed") + } + worker.SetRedis(key, string(json_data)) + } + } else { + var cid_workers []proto.CIDRUN + cid_redis_workers := worker.GetRedis(key) + err := json.Unmarshal([]byte(cid_redis_workers), &cid_workers) + if err != nil { + fmt.Println("json unmarshal failed") + } + for _, v := range cid_workers { + //查找定时任务 + if v.Curr-10 <= 0 { + cid := dao.FindCIDByCID(v.CID) + if cid.ID != 0 { + go RunShell("cron", cid.Url, cid.Script, int(cid.ID), cid.Auth_id) + } + } else { + v.Curr = v.Curr - 10 + } + } + //将定时任务加入redis + json_data, err := json.Marshal(cid_workers) + if err != nil { + fmt.Println("json marshal failed") + } + worker.SetRedis(key, string(json_data)) + } + +} diff --git a/main.go b/main.go index 48c4966..c42348e 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,9 @@ package main import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt" + "github.com/robfig/cron/v3" "io" + "log" "os" "strings" "videoplayer/dao" @@ -33,6 +35,14 @@ func main() { handler.SetUpToolGroup(r) // Tool defer dao.Close() defer worker.CloseRedis() + //定时任务 + c := cron.New(cron.WithSeconds()) + // 添加每 10 秒执行一次的任务 + _, err = c.AddFunc("@every 10s", myTask) + if err != nil { + log.Fatal("添加定时任务失败: ", err) + } + c.Start() r.Run(":8083") // listen and serve on 0.0.0.0:8083 } func init() { @@ -138,3 +148,9 @@ func JWTAuthMiddleware() gin.HandlerFunc { c.Next() } } + +func myTask() { + // 定时任务 + //redis中取出数据 + handler.RunCron() +} diff --git a/proto/user_req.go b/proto/user_req.go index be15ea6..2413f7b 100644 --- a/proto/user_req.go +++ b/proto/user_req.go @@ -11,3 +11,9 @@ type UpdateUserInfoReq struct { Run bool `json:"run" form:"run"` //是否运行 Avatar string `json:"avatar" form:"avatar"` //头像 } + +type CIDRUN struct { + CID uint `json:"cid" form:"cid"` //持续集成ID,查找持续集成任务 + Curr int `json:"curr" form:"curr"` //当前剩余时间,每次执行减10s小于等于0则执行 + Every int `json:"every" form:"every"` //每隔多少秒执行一次,小于等于0表示不执行,时间粒度为10s +}