feat: 定时发布系统 — Phase 5 完成

- Post ScheduledAt 字段
- Scheduler goroutine 每分钟扫描到期文章
- Create/Update 校验最短 30min 定时
- Approve 审核晚于定时则即时发布
- public 列表+空间页过滤未到期文章
- 写文章页 datetime-local 选择器(min=now+30min)
- AutoMigrate 追加新表
This commit is contained in:
2026-06-22 00:39:04 +08:00
parent 0b8f6f890d
commit e9b7401dc9
14 changed files with 132 additions and 15 deletions

View File

@ -0,0 +1,45 @@
package scheduler
import (
"log"
"time"
"metazone.cc/mce/internal/model"
)
// PostStore Scheduler 所需的最小帖子仓储接口ISP
type PostStore interface {
FindScheduledDue() ([]model.Post, error)
Update(post *model.Post) error
}
// StartPublishScheduler 启动定时发布调度器goroutine每分钟扫描到期文章
func StartPublishScheduler(repo PostStore, interval time.Duration) {
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
log.Printf("[Scheduler] 定时发布调度器已启动,间隔=%v", interval)
for range ticker.C {
func() {
defer func() {
if r := recover(); r != nil {
log.Printf("[Scheduler] panic recovered: %v", r)
}
}()
posts, err := repo.FindScheduledDue()
if err != nil {
log.Printf("[Scheduler] 扫描失败: %v", err)
return
}
for _, p := range posts {
p.ScheduledAt = nil
if err := repo.Update(&p); err != nil {
log.Printf("[Scheduler] 发布 postID=%d 失败: %v", p.ID, err)
continue
}
log.Printf("[Scheduler] 定时发布 postID=%d title=%q", p.ID, p.Title)
}
}()
}
}()
}