67 lines
1.4 KiB
Go
67 lines
1.4 KiB
Go
// Package syncgate 保证全局同一时间仅有一次 sync(Cron 与 Web 测试互斥)。
|
||
package syncgate
|
||
|
||
import (
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// Status 当前同步执行状态。
|
||
type Status struct {
|
||
Running bool `json:"running"`
|
||
LastStep string `json:"last_step,omitempty"`
|
||
LastDate string `json:"last_date,omitempty"`
|
||
LastError string `json:"last_error,omitempty"`
|
||
StartedAt time.Time `json:"started_at,omitempty"`
|
||
FinishedAt time.Time `json:"finished_at,omitempty"`
|
||
}
|
||
|
||
var (
|
||
mu sync.Mutex
|
||
status Status
|
||
)
|
||
|
||
// TryRun 若已有任务在执行则返回 false;否则在 goroutine 中执行 fn 并更新状态。
|
||
func TryRun(step, date string, fn func() error) bool {
|
||
mu.Lock()
|
||
if status.Running {
|
||
mu.Unlock()
|
||
return false
|
||
}
|
||
status.Running = true
|
||
status.LastStep = step
|
||
status.LastDate = date
|
||
status.LastError = ""
|
||
status.StartedAt = time.Now()
|
||
status.FinishedAt = time.Time{}
|
||
mu.Unlock()
|
||
|
||
go func() {
|
||
err := fn()
|
||
mu.Lock()
|
||
status.Running = false
|
||
status.FinishedAt = time.Now()
|
||
if err != nil {
|
||
status.LastError = err.Error()
|
||
} else {
|
||
status.LastError = ""
|
||
}
|
||
mu.Unlock()
|
||
}()
|
||
return true
|
||
}
|
||
|
||
// GetStatus 返回状态快照。
|
||
func GetStatus() Status {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
return status
|
||
}
|
||
|
||
// IsRunning 是否正在执行 sync。
|
||
func IsRunning() bool {
|
||
mu.Lock()
|
||
defer mu.Unlock()
|
||
return status.Running
|
||
}
|