refactor: queue
This commit is contained in:
@@ -17,6 +17,77 @@ import (
|
||||
// scriptTimeout 脚本执行超时上限(15 分钟)
|
||||
const scriptTimeout = 60 * time.Minute
|
||||
|
||||
// buildTask 单次构建任务的快照,handler 入队时构造。
|
||||
type buildTask struct {
|
||||
scriptPath string
|
||||
repoName string
|
||||
ref string
|
||||
commitID string
|
||||
}
|
||||
|
||||
// debounceEntry 单 key 的冷却去重状态。
|
||||
type debounceEntry struct {
|
||||
mu sync.Mutex
|
||||
lastExec time.Time
|
||||
}
|
||||
|
||||
var (
|
||||
// buildCh 单槽队列;handler enqueue 始终非阻塞,worker 唯一消费者
|
||||
buildCh = make(chan buildTask, 1)
|
||||
// lastExecMap 冷却去重状态,key: "repoName:ref", value: *debounceEntry
|
||||
lastExecMap sync.Map
|
||||
// 防抖冷却时间限制:3 分钟
|
||||
debounceDuration = 3 * time.Minute
|
||||
)
|
||||
|
||||
// enqueueBuildTask 入队;队列已满时丢老取新(drop-oldest)
|
||||
func enqueueBuildTask(t buildTask) {
|
||||
select {
|
||||
case buildCh <- t:
|
||||
return // 入队成功
|
||||
default:
|
||||
// 队列已满,丢弃旧 task
|
||||
select {
|
||||
case <-buildCh:
|
||||
default:
|
||||
}
|
||||
buildCh <- t // 阻塞不会发生,因为我们是唯一发送方
|
||||
}
|
||||
}
|
||||
|
||||
// startBuildWorker 启动单 worker goroutine 持续消费 buildCh
|
||||
func startBuildWorker() {
|
||||
go consumeBuild()
|
||||
}
|
||||
|
||||
// consumeBuild worker 主循环;取出 task,按冷却规则执行或跳过
|
||||
func consumeBuild() {
|
||||
for task := range buildCh {
|
||||
lockKey := fmt.Sprintf("%s:%s", task.repoName, task.ref)
|
||||
entryVal, _ := lastExecMap.LoadOrStore(lockKey, &debounceEntry{})
|
||||
entry := entryVal.(*debounceEntry)
|
||||
|
||||
entry.mu.Lock()
|
||||
now := time.Now()
|
||||
if !entry.lastExec.IsZero() && now.Sub(entry.lastExec) < debounceDuration {
|
||||
remainingSeconds := int((debounceDuration - now.Sub(entry.lastExec)).Seconds())
|
||||
if remainingSeconds < 0 {
|
||||
remainingSeconds = 0
|
||||
}
|
||||
entry.mu.Unlock()
|
||||
log.Printf("[SKIP] 3 分钟冷却中,跳过构建 [%s] commit %s 剩余 %d 秒\n",
|
||||
lockKey, shortCommit(task.commitID), remainingSeconds)
|
||||
continue
|
||||
}
|
||||
entry.lastExec = now
|
||||
entry.mu.Unlock()
|
||||
|
||||
log.Printf("[INFO] 开始执行脚本: %s (仓库: %s, 分支: %s, commit: %s)\n",
|
||||
task.scriptPath, task.repoName, task.ref, shortCommit(task.commitID))
|
||||
go runScript(task.scriptPath, task.repoName, task.ref, task.commitID)
|
||||
}
|
||||
}
|
||||
|
||||
// shortCommit 安全地取 commit 短 ID,避免空值/短值切片越界 panic
|
||||
func shortCommit(commitID string) string {
|
||||
if len(commitID) > 7 {
|
||||
|
||||
Reference in New Issue
Block a user