增加反链计算按钮
This commit is contained in:
+73
-8
@@ -13,6 +13,7 @@ import (
|
||||
"os" // 文件写入
|
||||
"path/filepath" // 路径拼接
|
||||
"strings" // 字符串操作
|
||||
"sync" // 互斥锁(保护手动触发的并发安全)
|
||||
"time" // 时间计算(下次运行时间、睡眠)
|
||||
|
||||
"sese-engine/storage" // 持久化存储
|
||||
@@ -22,6 +23,11 @@ import (
|
||||
type Runner struct {
|
||||
db *storage.DB
|
||||
storagePath string // 存储根目录(用于写入 prosper.json)
|
||||
mu sync.Mutex
|
||||
running bool // 是否正在计算中
|
||||
nextRun time.Time // 下次计划执行时间
|
||||
lastRunAt *time.Time // 上次完成时间(nil 表示尚未运行)
|
||||
lastError string // 上次错误信息(空字符串表示无错误)
|
||||
}
|
||||
|
||||
// New 创建一个 Runner 实例。
|
||||
@@ -29,6 +35,23 @@ func New(db *storage.DB, storagePath string) *Runner {
|
||||
return &Runner{db: db, storagePath: storagePath}
|
||||
}
|
||||
|
||||
// Status 返回反链计算器的当前状态快照。
|
||||
func (r *Runner) Status() map[string]interface{} {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
m := map[string]interface{}{
|
||||
"running": r.running,
|
||||
"next_run": r.nextRun.Format(time.RFC3339),
|
||||
}
|
||||
if r.lastRunAt != nil {
|
||||
m["last_run"] = r.lastRunAt.Format(time.RFC3339)
|
||||
}
|
||||
if r.lastError != "" {
|
||||
m["last_error"] = r.lastError
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Run 无限循环,每 48 小时执行一次反向链接计算。
|
||||
// 每次运行对齐到凌晨 2:00(便于在低峰期执行重计算)。
|
||||
func (r *Runner) Run() {
|
||||
@@ -39,22 +62,64 @@ func (r *Runner) Run() {
|
||||
if !target.After(now) {
|
||||
target = target.Add(48 * time.Hour) // 已过凌晨 2 点,则等明天的 2 点
|
||||
}
|
||||
|
||||
r.mu.Lock()
|
||||
r.nextRun = target
|
||||
r.mu.Unlock()
|
||||
|
||||
sleep := target.Sub(now)
|
||||
log.Printf("[backlink] next run at %v (in %v)", target.Format(time.RFC3339), sleep.Round(time.Minute))
|
||||
time.Sleep(sleep)
|
||||
|
||||
log.Printf("[backlink] starting computation at %v", time.Now().Format(time.RFC3339))
|
||||
if err := r.compute(); err != nil {
|
||||
log.Printf("[backlink] error: %v", err)
|
||||
} else {
|
||||
log.Printf("[backlink] done")
|
||||
}
|
||||
r.doCompute()
|
||||
}
|
||||
}
|
||||
|
||||
// RunNow 立即执行一次计算(用于手动触发或测试)。
|
||||
// RunNow 立即执行一次计算(用于手动触发)。
|
||||
// 如果已有计算正在运行则返回 nil(幂等)。
|
||||
// 执行后重新计算下次自动运行的定时。
|
||||
func (r *Runner) RunNow() error {
|
||||
return r.compute()
|
||||
r.mu.Lock()
|
||||
if r.running {
|
||||
r.mu.Unlock()
|
||||
log.Printf("[backlink] RunNow: already running, skipping")
|
||||
return nil
|
||||
}
|
||||
r.mu.Unlock()
|
||||
r.doCompute()
|
||||
return nil
|
||||
}
|
||||
|
||||
// doCompute 执行一次完整的计算,更新状态字段。
|
||||
func (r *Runner) doCompute() {
|
||||
r.mu.Lock()
|
||||
r.running = true
|
||||
r.lastError = ""
|
||||
r.mu.Unlock()
|
||||
|
||||
log.Printf("[backlink] starting computation at %v", time.Now().Format(time.RFC3339))
|
||||
err := r.compute()
|
||||
|
||||
now := time.Now()
|
||||
r.mu.Lock()
|
||||
r.running = false
|
||||
r.lastRunAt = &now
|
||||
if err != nil {
|
||||
r.lastError = err.Error()
|
||||
}
|
||||
// 重新计算下次自动运行时间
|
||||
target := time.Date(now.Year(), now.Month(), now.Day(), 2, 0, 0, 0, now.Location())
|
||||
if !target.After(now) {
|
||||
target = target.Add(48 * time.Hour)
|
||||
}
|
||||
r.nextRun = target
|
||||
r.mu.Unlock()
|
||||
|
||||
if err != nil {
|
||||
log.Printf("[backlink] error: %v", err)
|
||||
} else {
|
||||
log.Printf("[backlink] done, next run at %v", target.Format(time.RFC3339))
|
||||
}
|
||||
}
|
||||
|
||||
// ---- 计算核心 ----
|
||||
|
||||
Reference in New Issue
Block a user