Files
StackChan/server/internal/boot/cron.go
T
2026-04-27 10:35:03 +08:00

96 lines
2.1 KiB
Go

/*
SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
SPDX-License-Identifier: MIT
*/
package boot
import (
"context"
"stackChan/internal/web_socket"
"sync/atomic"
"time"
"github.com/gogf/gf/v2/frame/g"
)
func InitCron() {
startPingTimer()
startCleanTimer()
}
var (
pingTimerStarted atomic.Bool
cleanTimerStarted atomic.Bool
)
// startPingTimer starts the heartbeat timer, with panic recovery and restart logic.
func startPingTimer() {
if !pingTimerStarted.CompareAndSwap(false, true) {
return
}
ctx, cancel := context.WithCancel(context.Background())
_ = cancel // for future use
go func() {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
g.Log().Info(ctx, "The heartbeat sending timer has been activated")
for {
select {
case <-ctx.Done():
pingTimerStarted.Store(false)
return
case <-ticker.C:
func() {
defer func() {
if err := recover(); err != nil {
g.Log().Errorf(ctx, "Heartbeat sending task crash: %v, the timer is about to be restarted", err)
pingTimerStarted.Store(false)
go func() {
time.Sleep(time.Second)
startPingTimer()
}()
}
}()
web_socket.StartPingTime(ctx)
}()
}
}
}()
}
// startCleanTimer starts the connection cleaning timer, with panic recovery and restart logic.
func startCleanTimer() {
if !cleanTimerStarted.CompareAndSwap(false, true) {
return
}
ctx, cancel := context.WithCancel(context.Background())
_ = cancel // for future use
go func() {
ticker := time.NewTicker(15 * time.Second)
defer ticker.Stop()
g.Log().Info(ctx, "The connection cleaning timer has been started")
for {
select {
case <-ctx.Done():
cleanTimerStarted.Store(false)
return
case <-ticker.C:
func() {
defer func() {
if err := recover(); err != nil {
g.Log().Errorf(ctx, "Connection cleanup task crash: %v, about to restart the timer", err)
cleanTimerStarted.Store(false)
go func() {
time.Sleep(time.Second)
startCleanTimer()
}()
}
}()
web_socket.CheckExpiredLinks(ctx)
}()
}
}
}()
}