Files
iknowyou/back/internal/search/search.go
2026-04-06 15:12:34 +02:00

98 lines
1.8 KiB
Go

package search
import (
"context"
"sync"
"time"
"github.com/anotherhadi/iknowyou/internal/tools"
)
type Status string
const (
StatusRunning Status = "running"
StatusDone Status = "done"
StatusCancelled Status = "cancelled"
)
type ToolStatus struct {
Name string `json:"name"`
Skipped bool `json:"skipped"`
Reason string `json:"reason,omitempty"` // non-empty only when Skipped is true
ResultCount *int `json:"result_count,omitempty"` // nil = pending, 0 = no results
}
type Search struct {
ID string
Target string
InputType tools.InputType
Profile string
StartedAt time.Time
PlannedTools []ToolStatus
cancelFn context.CancelFunc
mu sync.RWMutex
events []tools.Event
status Status
finishedAt time.Time
}
func (s *Search) Events() []tools.Event {
s.mu.RLock()
defer s.mu.RUnlock()
out := make([]tools.Event, len(s.events))
copy(out, s.events)
return out
}
func (s *Search) Status() Status {
s.mu.RLock()
defer s.mu.RUnlock()
return s.status
}
func (s *Search) FinishedAt() time.Time {
s.mu.RLock()
defer s.mu.RUnlock()
return s.finishedAt
}
func (s *Search) Cancel() {
s.mu.Lock()
if s.status == StatusRunning {
s.status = StatusCancelled
s.finishedAt = time.Now()
}
s.mu.Unlock()
s.cancelFn()
}
func (s *Search) setToolResultCount(toolName string, count int) {
s.mu.Lock()
defer s.mu.Unlock()
for i, t := range s.PlannedTools {
if t.Name == toolName {
s.PlannedTools[i].ResultCount = &count
return
}
}
}
func (s *Search) append(e tools.Event) {
s.mu.Lock()
defer s.mu.Unlock()
s.events = append(s.events, e)
}
func (s *Search) markDone() {
s.mu.Lock()
defer s.mu.Unlock()
if s.status == StatusRunning {
s.status = StatusDone
s.finishedAt = time.Now()
}
}