Add files via upload

This commit is contained in:
zhangch-dev
2025-05-06 18:51:53 +08:00
committed by GitHub
parent 0ccc0620f3
commit e7b5ac85e1
52 changed files with 7266 additions and 0 deletions

View 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)
// }
// }
// }

View 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()
}
}
}
}

View 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()
}