Smail/backend/services/logstore/runtime.go
smail 5faadcd6eb
Some checks are pending
Security Checks / security (push) Waiting to run
保存三数据库日志与三十天清理实现,继续补充验收
2026-09-08 22:30:50 +08:00

72 lines
1.5 KiB
Go

package logstore
import (
"context"
"sync"
"sync/atomic"
"time"
"git.pcux.cn/xuans/Smail/utils/logpolicy"
log "github.com/sirupsen/logrus"
)
var active atomic.Pointer[Store]
func Current() *Store { return active.Load() }
// Record 同步落库,不建立无限内存队列;故障必须进入运行日志。
func Record(ctx context.Context, entry Entry) {
store := Current()
if store == nil {
return
}
bounded, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if err := store.Write(bounded, entry); err != nil {
log.WithError(err).Error("业务日志写入失败")
}
}
type Runtime struct {
cancel context.CancelFunc
done chan struct{}
once sync.Once
store *Store
}
func Start(store *Store) *Runtime {
ctx, cancel := context.WithCancel(context.Background())
runtime := &Runtime{cancel: cancel, done: make(chan struct{}), store: store}
active.Store(store)
go func() {
defer close(runtime.done)
ticker := time.NewTicker(logpolicy.MaintenanceInterval)
defer ticker.Stop()
for {
bounded, stop := context.WithTimeout(ctx, 2*time.Minute)
_, err := store.Cleanup(bounded, time.Now())
stop()
if err != nil && ctx.Err() == nil {
log.WithError(err).Error("过期业务日志清理失败,将在下一轮重试")
}
select {
case <-ctx.Done():
return
case <-ticker.C:
}
}
}()
return runtime
}
func (r *Runtime) Stop() {
if r == nil {
return
}
r.once.Do(func() {
active.CompareAndSwap(r.store, nil)
r.cancel()
<-r.done
})
}