broadcast/cmd/broadcast/main.go

155 lines
2.6 KiB
Go

package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"git.abbiamoundominio.org/blallo/broadcast"
"git.sr.ht/~blallo/logz/interface"
"git.sr.ht/~blallo/logz/zlog"
)
var (
debug = flag.Bool("debug", false, "Enable debug logging")
)
func main() {
logger := zlog.NewConsoleLogger()
flag.Parse()
if flag.NArg() < 1 {
logger.Err(map[string]any{
"msg": "Wrong number of arguments",
})
os.Exit(1)
}
if *debug {
logger.SetLevel(logz.LogDebug)
}
prog := flag.Arg(0)
cmdLine := flag.Args()[1:]
radio, err := broadcast.NewRadio(logger, prog, cmdLine...)
if err != nil {
logger.Err(map[string]any{
"msg": "Failed to start",
"err": err,
})
os.Exit(2)
}
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
start := make(chan os.Signal)
stop := make(chan os.Signal)
status := make(chan os.Signal)
signal.Notify(start, syscall.SIGUSR1)
signal.Notify(stop, syscall.SIGTSTP)
signal.Notify(status, syscall.SIGUSR2)
go func() {
for {
select {
case <-ctx.Done():
return
case <-start:
resp := <-radio.Start()
if resp != nil {
logger.Warn(map[string]any{
"msg": "Failed to start",
"err": resp.(error).Error(),
})
} else {
logger.Info(map[string]any{
"msg": "Started",
})
}
}
}
}()
go func() {
for {
select {
case <-ctx.Done():
return
case <-stop:
resp := <-radio.Stop()
if resp != nil {
logger.Warn(map[string]any{
"msg": "Failed to stop",
"err": resp.(error).Error(),
})
} else {
logger.Info(map[string]any{
"msg": "Stopped",
})
}
}
}
}()
go func() {
for {
select {
case <-ctx.Done():
return
case <-status:
resp := <-radio.Status()
for i, line := range resp.([]string) {
logger.Info(map[string]any{
"msg": line,
"lineNum": i,
})
}
}
}
}()
go func() {
resp, err := withTimeout(ctx, radio.Start())
if err != nil {
logger.Err(map[string]any{
"msg": "Cannot start",
"err": err.Error(),
})
} else {
if resp != nil {
logger.Info(map[string]any{
"msg": "Started",
"resp": resp.(error).Error(),
})
}
}
}()
if err := radio.Run(ctx); err != nil {
logger.Err(map[string]any{
"msg": "Execution failed",
"err": err.Error(),
})
os.Exit(2)
}
}
func withTimeout[T any](ctx context.Context, respCh <-chan T) (zero T, err error) {
shortCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
select {
case <-shortCtx.Done():
return zero, shortCtx.Err()
case resp := <-respCh:
return resp, nil
}
}