Smail/backend/services/verification/cleanup.go
smail f60d3b0880
Some checks are pending
Security Checks / security (push) Waiting to run
整理前后端与测试构建目录并完善配置和安全引导
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
2026-09-05 19:19:52 +08:00

73 lines
1.3 KiB
Go

package verification
import (
"errors"
"sync"
"time"
)
var ErrCleanupAlreadyStarted = errors.New("verification cleanup already started")
type CleanupRunner struct {
store *Store
mu sync.Mutex
stop chan struct{}
done chan struct{}
stopping bool
}
func NewCleanupRunner(store *Store) *CleanupRunner {
return &CleanupRunner{store: store}
}
// Start 启动单实例过期清理器;验证码不会从持久化介质恢复。
func (r *CleanupRunner) Start(interval time.Duration) error {
if r == nil || r.store == nil || interval <= 0 {
return ErrInvalidChallenge
}
r.mu.Lock()
if r.stop != nil || r.stopping {
r.mu.Unlock()
return ErrCleanupAlreadyStarted
}
r.stop = make(chan struct{})
r.done = make(chan struct{})
stop, done := r.stop, r.done
r.mu.Unlock()
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
defer close(done)
for {
select {
case <-ticker.C:
r.store.Cleanup()
case <-stop:
return
}
}
}()
return nil
}
func (r *CleanupRunner) Stop() {
if r == nil {
return
}
r.mu.Lock()
stop, done := r.stop, r.done
if stop == nil || r.stopping {
r.mu.Unlock()
return
}
r.stopping = true
r.mu.Unlock()
if stop != nil {
close(stop)
<-done
}
r.mu.Lock()
r.stop, r.done, r.stopping = nil, nil, false
r.mu.Unlock()
}