Files
wild-central-api/internal/services/broadcast_writer.go
2025-10-11 17:06:14 +00:00

67 lines
1.6 KiB
Go

package services
import (
"bytes"
"os"
"github.com/wild-cloud/wild-central/daemon/internal/operations"
)
// broadcastWriter writes output to both a file and broadcasts to SSE clients
type broadcastWriter struct {
file *os.File
broadcaster *operations.Broadcaster
opID string
buffer *bytes.Buffer
}
// newBroadcastWriter creates a writer that writes to file and broadcasts
func newBroadcastWriter(file *os.File, broadcaster *operations.Broadcaster, opID string) *broadcastWriter {
return &broadcastWriter{
file: file,
broadcaster: broadcaster,
opID: opID,
buffer: &bytes.Buffer{},
}
}
// Write implements io.Writer interface
func (w *broadcastWriter) Write(p []byte) (n int, err error) {
// Write to file first
n, err = w.file.Write(p)
if err != nil {
return n, err
}
// Buffer the data and broadcast complete lines
if w.broadcaster != nil {
w.buffer.Write(p)
// Extract and broadcast complete lines
for {
line, err := w.buffer.ReadBytes('\n')
if err != nil {
// No complete line, put back what we read and break
w.buffer.Write(line)
break
}
// Broadcast the line without the trailing newline
if len(line) > 0 && line[len(line)-1] == '\n' {
line = line[:len(line)-1]
}
w.broadcaster.Publish(w.opID, line)
}
}
return n, nil
}
// Flush broadcasts any remaining buffered data
func (w *broadcastWriter) Flush() {
if w.broadcaster != nil && w.buffer.Len() > 0 {
// Broadcast the remaining incomplete line
w.broadcaster.Publish(w.opID, w.buffer.Bytes())
w.buffer.Reset()
}
}