84 lines
1.6 KiB
Go
84 lines
1.6 KiB
Go
package tasks
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Status string
|
|
|
|
const (
|
|
StatusRunning Status = "running"
|
|
StatusSuccess Status = "success"
|
|
StatusFailed Status = "failed"
|
|
)
|
|
|
|
type Task struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type"`
|
|
Status Status `json:"status"`
|
|
StartedAtMS int64 `json:"started_at_ms"`
|
|
EndedAtMS int64 `json:"ended_at_ms,omitempty"`
|
|
Error string `json:"error,omitempty"`
|
|
Result any `json:"result,omitempty"`
|
|
}
|
|
|
|
type Registry struct {
|
|
mu sync.Mutex
|
|
tasks map[string]Task
|
|
}
|
|
|
|
func NewRegistry() *Registry {
|
|
return &Registry{tasks: map[string]Task{}}
|
|
}
|
|
|
|
func (r *Registry) Start(typ string) Task {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
id := newID()
|
|
t := Task{
|
|
ID: id,
|
|
Type: typ,
|
|
Status: StatusRunning,
|
|
StartedAtMS: time.Now().UnixMilli(),
|
|
}
|
|
r.tasks[id] = t
|
|
return t
|
|
}
|
|
|
|
func (r *Registry) Finish(id string, result any, err error) (Task, bool) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
t, ok := r.tasks[id]
|
|
if !ok {
|
|
return Task{}, false
|
|
}
|
|
if err != nil {
|
|
t.Status = StatusFailed
|
|
t.Error = err.Error()
|
|
} else {
|
|
t.Status = StatusSuccess
|
|
t.Result = result
|
|
}
|
|
t.EndedAtMS = time.Now().UnixMilli()
|
|
r.tasks[id] = t
|
|
return t, true
|
|
}
|
|
|
|
func (r *Registry) Get(id string) (Task, bool) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
t, ok := r.tasks[id]
|
|
return t, ok
|
|
}
|
|
|
|
func newID() string {
|
|
b := make([]byte, 16)
|
|
if _, err := rand.Read(b); err != nil {
|
|
return hex.EncodeToString([]byte(time.Now().Format("20060102150405.000")))
|
|
}
|
|
return hex.EncodeToString(b)
|
|
}
|