mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-08 07:41:10 +08:00
Add files via upload
This commit is contained in:
129
backend/scheduler/scheduler.go
Normal file
129
backend/scheduler/scheduler.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 你的任务列表
|
||||
var funcs = []func(){
|
||||
SiteMonitor,
|
||||
RunWorkflows,
|
||||
}
|
||||
|
||||
// Scheduler 控制器
|
||||
type Scheduler struct {
|
||||
mu sync.Mutex
|
||||
ctx context.Context
|
||||
cancelFunc context.CancelFunc
|
||||
running bool
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// 启动调度器(在 goroutine 中运行)
|
||||
func (s *Scheduler) Start() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.running {
|
||||
return
|
||||
}
|
||||
|
||||
s.ctx, s.cancelFunc = context.WithCancel(context.Background())
|
||||
s.running = true
|
||||
s.wg.Add(1)
|
||||
|
||||
go s.loop() // goroutine 中运行任务调度
|
||||
}
|
||||
|
||||
// 停止调度器
|
||||
func (s *Scheduler) Stop() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if !s.running {
|
||||
return
|
||||
}
|
||||
|
||||
s.cancelFunc() // 取消上下文
|
||||
s.wg.Wait() // 等待 goroutine 完成退出
|
||||
s.running = false // 标记为未运行
|
||||
}
|
||||
|
||||
// 重启调度器
|
||||
func (s *Scheduler) Restart() {
|
||||
s.Stop()
|
||||
time.Sleep(500 * time.Millisecond) // 可选,避免 race
|
||||
s.Start()
|
||||
}
|
||||
|
||||
// 调度主循环(内部)
|
||||
func (s *Scheduler) loop() {
|
||||
defer s.wg.Done()
|
||||
|
||||
for {
|
||||
// fmt.Println("Scheduler loop")
|
||||
select {
|
||||
case <-s.ctx.Done():
|
||||
return // 外部关闭信号,退出
|
||||
default:
|
||||
start := time.Now()
|
||||
|
||||
var taskWg sync.WaitGroup
|
||||
taskWg.Add(len(funcs))
|
||||
|
||||
for _, f := range funcs {
|
||||
go func(fn func()) {
|
||||
defer taskWg.Done()
|
||||
fn()
|
||||
}(f)
|
||||
}
|
||||
taskWg.Wait()
|
||||
|
||||
// 间隔控制
|
||||
elapsed := time.Since(start)
|
||||
if elapsed < 10*time.Second {
|
||||
select {
|
||||
case <-time.After(10*time.Second - elapsed):
|
||||
case <-s.ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// package scheduler
|
||||
//
|
||||
// import (
|
||||
// "sync"
|
||||
// "time"
|
||||
// )
|
||||
//
|
||||
// var funcs = []func(){
|
||||
// SiteMonitor,
|
||||
// RunWorkflows,
|
||||
// }
|
||||
//
|
||||
// func Scheduler() {
|
||||
// for {
|
||||
// start := time.Now()
|
||||
//
|
||||
// var wg sync.WaitGroup
|
||||
// wg.Add(len(funcs))
|
||||
//
|
||||
// for _, f := range funcs {
|
||||
// go func(fn func()) {
|
||||
// defer wg.Done()
|
||||
// fn()
|
||||
// }(f)
|
||||
// }
|
||||
// wg.Wait()
|
||||
// // 保证每轮间隔至少10秒
|
||||
// elapsed := time.Since(start)
|
||||
// if elapsed < 10*time.Second {
|
||||
// time.Sleep(10*time.Second - elapsed)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
90
backend/scheduler/site_monitor.go
Normal file
90
backend/scheduler/site_monitor.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"ALLinSSL/backend/internal/report"
|
||||
"ALLinSSL/backend/internal/siteMonitor"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func SiteMonitor() {
|
||||
s, err := siteMonitor.GetSqlite()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
defer s.Close()
|
||||
data, err := s.Select()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
now := time.Now()
|
||||
loc := now.Location()
|
||||
var wg sync.WaitGroup
|
||||
for _, v := range data {
|
||||
if v["active"].(int64) == 1 {
|
||||
lastTimeStr := v["last_time"].(string)
|
||||
lastTime, err := time.ParseInLocation("2006-01-02 15:04:05", lastTimeStr, loc)
|
||||
if err != nil {
|
||||
// fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
if now.Sub(lastTime).Minutes() >= float64(v["cycle"].(int64)) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
Err := siteMonitor.UpdInfo(fmt.Sprintf("%d", v["id"].(int64)), v["site_domain"].(string), s, v["report_type"].(string))
|
||||
|
||||
path := fmt.Sprintf("data/site_monitor/%d", v["id"].(int64))
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
|
||||
return
|
||||
}
|
||||
errCount := 0
|
||||
file, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
errCount = 0
|
||||
}
|
||||
errCount, err = strconv.Atoi(string(file))
|
||||
if err != nil {
|
||||
errCount = 0
|
||||
}
|
||||
|
||||
// 此处应该发送错误邮件
|
||||
if Err != nil {
|
||||
errCount += 1
|
||||
os.WriteFile(path, []byte(strconv.Itoa(errCount)), os.ModePerm)
|
||||
repeatSendGap, ok := v["repeat_send_gap"].(int64)
|
||||
if !ok {
|
||||
repeatSendGap = 10
|
||||
}
|
||||
reportType, ok := v["report_type"].(string)
|
||||
if ok && errCount >= int(repeatSendGap) {
|
||||
s.TableName = "report"
|
||||
rdata, err := s.Where("type=?", []interface{}{reportType}).Select()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if len(rdata) <= 0 {
|
||||
return
|
||||
}
|
||||
_ = report.Notify(map[string]any{
|
||||
"provider": reportType,
|
||||
"provider_id": strconv.FormatInt(rdata[0]["id"].(int64), 10),
|
||||
"body": fmt.Sprintf("检测到域名为%s的网站出现异常,请保持关注!\n检测时间:%s", v["site_domain"].(string), now.Format("2006-01-02 15:04:05")),
|
||||
"subject": "ALLinSSL网站监控通知",
|
||||
})
|
||||
os.Remove(path)
|
||||
}
|
||||
} else {
|
||||
os.Remove(path)
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
104
backend/scheduler/workflow.go
Normal file
104
backend/scheduler/workflow.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
wf "ALLinSSL/backend/internal/workflow"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ExecTime struct {
|
||||
Type string `json:"type"` // "day", "week", "month"
|
||||
Month int `json:"month,omitempty"` // 每月几号 type="month"时必填
|
||||
Week int `json:"week,omitempty"` // 星期几 type="week"时必填
|
||||
Hour int `json:"hour"` // 几点 必填
|
||||
Minute int `json:"minute"` // 几分 必填
|
||||
}
|
||||
|
||||
func RunWorkflows() {
|
||||
s, err := wf.GetSqlite()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
defer s.Close()
|
||||
data, err := s.Select()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
now := time.Now()
|
||||
// 遍历工作流
|
||||
var wg sync.WaitGroup
|
||||
for _, workflow := range data {
|
||||
if workflow["exec_type"].(string) != "auto" {
|
||||
// fmt.Println("不是自动执行的工作流")
|
||||
continue
|
||||
}
|
||||
if workflow["active"].(int64) == 0 {
|
||||
// 1: 启用
|
||||
// 0: 禁用
|
||||
// fmt.Println("工作流未启用")
|
||||
continue
|
||||
}
|
||||
if workflow["last_run_status"] != nil && workflow["last_run_status"].(string) == "running" {
|
||||
// fmt.Println("工作流正在运行")
|
||||
continue
|
||||
}
|
||||
// if workflow["last"]
|
||||
if workflow["last_run_time"] != nil && now.Format("2006-01-02 15:04") == workflow["last_run_time"].(string)[0:16] {
|
||||
// fmt.Println("工作流已执行过")
|
||||
continue
|
||||
}
|
||||
// 判断是否到执行时间
|
||||
var execTime ExecTime
|
||||
execTimeStr := ""
|
||||
if et, ok := workflow["exec_time"].(string); ok {
|
||||
execTimeStr = et
|
||||
}
|
||||
err := json.Unmarshal([]byte(execTimeStr), &execTime)
|
||||
if err != nil {
|
||||
// fmt.Println("解析执行时间失败:", err)
|
||||
continue
|
||||
}
|
||||
if execTime.Minute != now.Minute() || execTime.Hour != now.Hour() {
|
||||
// fmt.Println("不在执行时间内1")
|
||||
continue
|
||||
}
|
||||
|
||||
if execTime.Type == "week" && execTime.Week != int(now.Weekday()) {
|
||||
// fmt.Println("不在执行时间内2")
|
||||
continue
|
||||
}
|
||||
if execTime.Type == "month" && execTime.Month != now.Day() {
|
||||
// fmt.Println("不在执行时间内3")
|
||||
continue
|
||||
}
|
||||
if content, ok := workflow["content"].(string); !ok {
|
||||
// fmt.Println("工作流内容为空")
|
||||
continue
|
||||
} else {
|
||||
wg.Add(1)
|
||||
go func(id int64, c string) {
|
||||
defer wg.Done()
|
||||
WorkflowID := strconv.FormatInt(id, 10)
|
||||
RunID, err := wf.AddWorkflowHistory(WorkflowID, "auto")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ctx := wf.NewExecutionContext(RunID)
|
||||
defer ctx.Logger.Close()
|
||||
err = wf.RunWorkflow(c, ctx)
|
||||
if err != nil {
|
||||
fmt.Println("执行工作流失败:", err)
|
||||
wf.SetWorkflowStatus(WorkflowID, RunID, "fail")
|
||||
} else {
|
||||
wf.SetWorkflowStatus(WorkflowID, RunID, "success")
|
||||
}
|
||||
}(workflow["id"].(int64), content)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
Reference in New Issue
Block a user