package task import ( "sync" "time" "github.com/google/uuid" ) type Status string const ( StatusQueued Status = "queued" StatusRunning Status = "running" StatusSuccess Status = "success" StatusFailed Status = "failed" StatusCanceled Status = "canceled" ) type Task struct { ID string `json:"id"` Type string `json:"type"` Status Status `json:"status"` Progress int `json:"progress"` Message string `json:"message"` Error string `json:"error"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } func (t *Task) IsTerminal() bool { return t.Status == StatusSuccess || t.Status == StatusFailed || t.Status == StatusCanceled } type Store struct { mu sync.RWMutex tasks map[string]*Task } func NewStore() *Store { return &Store{tasks: make(map[string]*Task)} } func (s *Store) Create(taskType string) *Task { t := &Task{ ID: uuid.New().String(), Type: taskType, Status: StatusQueued, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC(), } s.mu.Lock() s.tasks[t.ID] = t s.mu.Unlock() return t } func (s *Store) Get(id string) (*Task, bool) { s.mu.RLock() defer s.mu.RUnlock() t, ok := s.tasks[id] if !ok { return nil, false } copy := *t return ©, true } func (s *Store) Update(id string, fn func(*Task)) { s.mu.Lock() defer s.mu.Unlock() if t, ok := s.tasks[id]; ok { fn(t) t.UpdatedAt = time.Now().UTC() } } func (s *Store) ActiveTask() (*Task, bool) { s.mu.RLock() defer s.mu.RUnlock() for _, t := range s.tasks { if t.Status == StatusQueued || t.Status == StatusRunning { copy := *t return ©, true } } return nil, false }