package provider import ( "bufio" "encoding/json" "fmt" "io" "orchestra/internal/domain" ) type Sink interface{ Append(domain.Event) error } type Provider interface { Ingest(io.Reader, Sink) (int, error) } // JSONL treats each line as an external task object. Replaying the same input // is safe because the store deduplicates the stable source/external_id key. type JSONL struct{} func (JSONL) Ingest(r io.Reader, sink Sink) (int, error) { sc := bufio.NewScanner(r) count := 0 line := 0 for sc.Scan() { line++ raw := sc.Bytes() if len(raw) == 0 { continue } var p map[string]any if err := json.Unmarshal(raw, &p); err != nil { return count, fmt.Errorf("line %d: %w", line, err) } if err := domain.ValidateCreated(p); err != nil { return count, fmt.Errorf("line %d: %w", line, err) } b, _ := json.Marshal(p) e := domain.Event{ID: domain.NewID(), Type: "TaskCreated", TaskID: domain.NewID(), Version: 1, Payload: b} if err := sink.Append(e); err != nil { return count, fmt.Errorf("line %d: %w", line, err) } count++ } return count, sc.Err() }