92 lines
1.7 KiB
Go
92 lines
1.7 KiB
Go
package standby_ctrl
|
|
|
|
import (
|
|
"context"
|
|
"github.com/go-pkgz/cronrange"
|
|
"go.uber.org/zap"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Time 时间控制器
|
|
func Time(rootRules []cronrange.Rule, cron string, play func(c context.Context) error) func(c context.Context) error {
|
|
// 设定默认时间规则
|
|
if cron == "" {
|
|
cron = "* * * *"
|
|
}
|
|
|
|
rules, err := cronrange.Parse(cron)
|
|
if err != nil {
|
|
zap.S().Errorln("解析时间规则异常: ", err)
|
|
return nil
|
|
}
|
|
|
|
return func(c context.Context) error {
|
|
a := make(chan bool)
|
|
defer close(a)
|
|
|
|
// 等待组
|
|
var waitGroup sync.WaitGroup
|
|
defer waitGroup.Wait()
|
|
|
|
ticker := time.NewTicker(time.Second)
|
|
defer ticker.Stop()
|
|
|
|
waitGroup.Add(1)
|
|
go func() {
|
|
defer waitGroup.Done()
|
|
for {
|
|
select {
|
|
case <-c.Done():
|
|
return
|
|
case <-ticker.C:
|
|
if cronrange.Match(rules, time.Now()) && cronrange.Match(rootRules, time.Now()) {
|
|
a <- true
|
|
} else {
|
|
a <- false
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
|
|
var cancel context.CancelFunc
|
|
var m sync.Mutex
|
|
for {
|
|
select {
|
|
case <-c.Done():
|
|
if cancel != nil {
|
|
cancel()
|
|
cancel = nil
|
|
}
|
|
return nil
|
|
case r := <-a:
|
|
if r {
|
|
if ok := m.TryLock(); ok {
|
|
ctx, cc := context.WithCancel(context.TODO())
|
|
cancel = cc
|
|
waitGroup.Add(1)
|
|
go func() {
|
|
defer waitGroup.Done()
|
|
defer m.Unlock()
|
|
defer func() { cancel = nil }()
|
|
|
|
err := play(ctx)
|
|
if err != nil {
|
|
zap.S().Errorln("执行动作异常: ", err)
|
|
select {
|
|
case <-ctx.Done():
|
|
return
|
|
case <-time.After(time.Minute):
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
} else if cancel != nil {
|
|
cancel()
|
|
cancel = nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|