自动在空闲时间执行定时任务

This commit is contained in:
刘祥超
2024-04-17 13:10:55 +08:00
parent 234887cc1d
commit 7220c53ced
13 changed files with 218 additions and 49 deletions

View File

@@ -5,6 +5,7 @@ package cachehits
import (
"github.com/TeaOSLab/EdgeNode/internal/goman"
"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
"github.com/TeaOSLab/EdgeNode/internal/utils/idles"
memutils "github.com/TeaOSLab/EdgeNode/internal/utils/mem"
"github.com/iwind/TeaGo/Tea"
"sync"
@@ -58,7 +59,7 @@ func NewStat(goodRatio uint64) *Stat {
}
func (this *Stat) init() {
for range this.ticker.C {
idles.RunTicker(this.ticker, func() {
var currentTime = fasttime.Now().Unix()
this.mu.RLock()
@@ -73,7 +74,7 @@ func (this *Stat) init() {
}
}
this.mu.RUnlock()
}
})
}
func (this *Stat) IncreaseCached(category string) {

View File

@@ -3,6 +3,7 @@
package counters
import (
"github.com/TeaOSLab/EdgeNode/internal/goman"
"github.com/TeaOSLab/EdgeNode/internal/utils/fasttime"
memutils "github.com/TeaOSLab/EdgeNode/internal/utils/mem"
syncutils "github.com/TeaOSLab/EdgeNode/internal/utils/sync"
@@ -56,11 +57,11 @@ func (this *Counter[T]) WithGC() *Counter[T] {
return this
}
this.gcTicker = time.NewTicker(1 * time.Second)
go func() {
goman.New(func() {
for range this.gcTicker.C {
this.GC()
}
}()
})
return this
}

View File

@@ -5,6 +5,7 @@ package fsutils
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
"github.com/TeaOSLab/EdgeNode/internal/goman"
"github.com/iwind/TeaGo/Tea"
"github.com/shirou/gopsutil/v3/load"
"os"
@@ -55,7 +56,7 @@ func init() {
}
// test disk
go func() {
goman.New(func() {
// load last result from local disk
cacheData, cacheErr := os.ReadFile(Tea.Root + "/data/" + diskSpeedDataFile)
if cacheErr == nil {
@@ -83,17 +84,17 @@ func init() {
}
}
}
}()
})
// check high load
go func() {
goman.New(func() {
var ticker = time.NewTicker(5 * time.Second)
for range ticker.C {
stat, _ := load.Avg()
IsInExtremelyHighLoad = stat != nil && stat.Load1 > extremelyHighLoad1Threshold
IsInHighLoad = stat != nil && stat.Load1 > highLoad1Threshold && !DiskIsFast()
}
}()
})
}
func DiskIsFast() bool {
@@ -145,8 +146,12 @@ func calculateDiskMaxWrites() {
func WaitLoad(maxLoad float64, maxLoops int, delay time.Duration) {
for i := 0; i < maxLoops; i++ {
stat, err := load.Avg()
if err == nil && stat.Load1 > maxLoad {
time.Sleep(delay)
if err == nil {
if stat.Load1 > maxLoad {
time.Sleep(delay)
} else {
return
}
}
}
}

View File

@@ -22,7 +22,7 @@ func TestWrites(t *testing.T) {
}
func TestWaitLoad(t *testing.T) {
fsutils.WaitLoad(100, 1, 1 * time.Minute)
fsutils.WaitLoad(100, 5, 1*time.Minute)
}
func BenchmarkWrites(b *testing.B) {

128
internal/utils/idles/run.go Normal file
View File

@@ -0,0 +1,128 @@
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package idles
import (
"encoding/json"
teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
"github.com/TeaOSLab/EdgeNode/internal/goman"
fsutils "github.com/TeaOSLab/EdgeNode/internal/utils/fs"
"github.com/iwind/TeaGo/Tea"
"github.com/shirou/gopsutil/v3/load"
"os"
"sort"
"time"
)
const maxSamples = 7
const cacheFile = "idles.cache"
var hourlyLoadMap = map[int]*HourlyLoad{}
var minLoadHour = -1
type HourlyLoad struct {
Hour int `json:"hour"`
Avg float64 `json:"avg"`
Values []float64 `json:"values"`
}
func init() {
if !teaconst.IsMain {
return
}
// recover from cache
{
data, err := os.ReadFile(Tea.Root + "/data/" + cacheFile)
if err == nil {
_ = json.Unmarshal(data, &hourlyLoadMap)
}
}
goman.New(func() {
var ticker = time.NewTicker(1 * time.Hour)
for range ticker.C {
CheckHourlyLoad(time.Now().Hour())
}
})
}
func CheckHourlyLoad(hour int) {
avgLoad, err := load.Avg()
if err != nil {
return
}
hourlyLoad, ok := hourlyLoadMap[hour]
if !ok {
hourlyLoad = &HourlyLoad{
Hour: hour,
}
hourlyLoadMap[hour] = hourlyLoad
}
if len(hourlyLoad.Values) >= maxSamples {
hourlyLoad.Values = hourlyLoad.Values[:maxSamples-1]
}
hourlyLoad.Values = append(hourlyLoad.Values, avgLoad.Load15)
var sum float64
for _, v := range hourlyLoad.Values {
sum += v
}
hourlyLoad.Avg = sum / float64(len(hourlyLoad.Values))
// calculate min load hour
var allLoads = []*HourlyLoad{}
for _, v := range hourlyLoadMap {
allLoads = append(allLoads, v)
}
sort.Slice(allLoads, func(i, j int) bool {
return allLoads[i].Avg < allLoads[j].Avg
})
minLoadHour = allLoads[0].Hour
// write to cache
hourlyLoadMapJSON, err := json.Marshal(hourlyLoadMap)
if err == nil {
_ = os.WriteFile(Tea.Root+"/data/"+cacheFile, hourlyLoadMapJSON, 0666)
}
}
func Run(f func()) {
defer f()
if minLoadHour < 0 {
fsutils.WaitLoad(15, 8, time.Hour)
return
}
var hour = time.Now().Hour()
if minLoadHour == hour {
fsutils.WaitLoad(15, 10, time.Minute)
return
}
if minLoadHour < hour {
time.Sleep(time.Duration(24-hour+minLoadHour) * time.Hour)
} else {
time.Sleep(time.Duration(minLoadHour-hour) * time.Hour)
}
fsutils.WaitLoad(15, 10, time.Minute)
}
func RunTicker(ticker *time.Ticker, f func()) {
for range ticker.C {
Run(f)
}
}
func TestMinLoadHour() int {
return minLoadHour
}
func TestHourlyLoadMap() map[int]*HourlyLoad {
return hourlyLoadMap
}

View File

@@ -0,0 +1,41 @@
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
package idles_test
import (
"github.com/TeaOSLab/EdgeNode/internal/utils/idles"
"github.com/TeaOSLab/EdgeNode/internal/utils/testutils"
"github.com/iwind/TeaGo/logs"
timeutil "github.com/iwind/TeaGo/utils/time"
"testing"
"time"
)
func TestCheckHourlyLoad(t *testing.T) {
for i := 0; i < 10; i++ {
idles.CheckHourlyLoad(1)
idles.CheckHourlyLoad(2)
idles.CheckHourlyLoad(3)
}
t.Log(idles.TestMinLoadHour())
logs.PrintAsJSON(idles.TestHourlyLoadMap(), t)
}
func TestRun(t *testing.T) {
//idles.CheckHourlyLoad(time.Now().Hour())
idles.Run(func() {
t.Log("run once")
})
}
func TestRunTicker(t *testing.T) {
if !testutils.IsSingleTesting() {
return
}
var ticker = time.NewTicker(10 * time.Second)
idles.RunTicker(ticker, func() {
t.Log(timeutil.Format("H:i:s"), "run once")
})
}