Files
ts3-monolith-go/cmd/ts3monolith/main.go
T
2026-10-30 10:56:13 +01:00

79 lines
2.0 KiB
Go

package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"os/signal"
"strconv"
"syscall"
"time"
"ts3monolith/internal/config"
"ts3monolith/internal/rrd"
"ts3monolith/internal/ts3"
webapp "ts3monolith/internal/web"
)
func main() {
log.SetFlags(log.LstdFlags | log.LUTC)
cfg, err := config.Load()
if err != nil {
log.Fatal(err)
}
tq := &ts3.Query{Addr: cfg.TSQueryHost + ":" + strconv.Itoa(cfg.TSQueryPort), User: cfg.TSQueryUser, Password: cfg.TSQueryPassword, VoicePort: cfg.TSVoicePort, Timeout: cfg.TSQueryTimeout}
rm := &rrd.Manager{Tool: cfg.RRDTool, Path: cfg.RRDPath, GraphDir: cfg.GraphDir}
if err := rm.Validate(); err != nil {
log.Fatal(err)
}
app, err := webapp.New(cfg, tq, rm)
if err != nil {
log.Fatal(err)
}
srv := &http.Server{Addr: cfg.ListenAddr, Handler: app.Handler(), ReadHeaderTimeout: 5 * time.Second, ReadTimeout: 10 * time.Second, WriteTimeout: 15 * time.Second, IdleTimeout: 60 * time.Second, MaxHeaderBytes: 16 << 10}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
go collect(ctx, cfg, tq, rm)
go func() {
<-ctx.Done()
c, cancel := context.WithTimeout(context.Background(), 8*time.Second)
defer cancel()
_ = srv.Shutdown(c)
}()
log.Printf("listening on %s", cfg.ListenAddr)
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
func collect(ctx context.Context, cfg config.Config, tq *ts3.Query, rm *rrd.Manager) {
run := func() {
c, cancel := context.WithTimeout(ctx, cfg.TSQueryTimeout)
defer cancel()
n, err := tq.CountOnline(c)
if err != nil {
log.Printf("stats query failed: %v", err)
return
}
c2, cancel2 := context.WithTimeout(ctx, 5*time.Second)
defer cancel2()
if err := rm.Update(c2, n); err != nil {
log.Printf("rrd update failed: %v", err)
}
}
run()
t := time.NewTicker(cfg.StatsInterval)
defer t.Stop()
for {
select {
case <-ctx.Done():
return
case <-t.C:
run()
}
}
}