// Package engine runs modules through the Detect/Plan/Apply/Verify phases. package engine import ( "fmt" "io" "sync" "gitlab.hive-brain.de/MDietermann/Archduino/internal/module" ) // Event is a single item streamed from a module during Apply. type Event struct { ModuleID string Kind EventKind Current int Total int Message string } type EventKind int const ( EventProgress EventKind = iota EventLog ) // BufferedReporter stores every event in memory. Used in tests. type BufferedReporter struct { mu sync.Mutex events []Event } func NewBufferedReporter() *BufferedReporter { return &BufferedReporter{} } func (b *BufferedReporter) Progress(id string, current, total int, msg string) { b.mu.Lock() defer b.mu.Unlock() b.events = append(b.events, Event{ModuleID: id, Kind: EventProgress, Current: current, Total: total, Message: msg}) } func (b *BufferedReporter) Log(id, line string) { b.mu.Lock() defer b.mu.Unlock() b.events = append(b.events, Event{ModuleID: id, Kind: EventLog, Message: line}) } func (b *BufferedReporter) Events() []Event { b.mu.Lock() defer b.mu.Unlock() out := make([]Event, len(b.events)) copy(out, b.events) return out } // PlainReporter writes human-readable lines to w. Concurrency-safe. type PlainReporter struct { mu sync.Mutex w io.Writer } func NewPlainReporter(w io.Writer) *PlainReporter { return &PlainReporter{w: w} } func (p *PlainReporter) Progress(id string, current, total int, msg string) { p.mu.Lock() defer p.mu.Unlock() fmt.Fprintf(p.w, "[%s] (%d/%d) %s\n", id, current, total, msg) } func (p *PlainReporter) Log(id, line string) { p.mu.Lock() defer p.mu.Unlock() fmt.Fprintf(p.w, "[%s] %s\n", id, line) } // Compile-time guarantee both types satisfy module.Reporter. var ( _ module.Reporter = (*BufferedReporter)(nil) _ module.Reporter = (*PlainReporter)(nil) )