diff --git a/cmd/server/main.go b/cmd/server/main.go index bfd7900..cb3a207 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -12,8 +12,10 @@ import ( "syscall" "time" + "gitea.dcglab.co.uk/steve/restic-manager/internal/alert" "gitea.dcglab.co.uk/steve/restic-manager/internal/auth" "gitea.dcglab.co.uk/steve/restic-manager/internal/crypto" + "gitea.dcglab.co.uk/steve/restic-manager/internal/notification" "gitea.dcglab.co.uk/steve/restic-manager/internal/server/config" rmhttp "gitea.dcglab.co.uk/steve/restic-manager/internal/server/http" "gitea.dcglab.co.uk/steve/restic-manager/internal/server/maintenance" @@ -82,19 +84,24 @@ func run() error { hub := ws.NewHub() jobHub := ws.NewJobHub() + notifHub := notification.NewHub(st, aead, cfg.BaseURL) + alertEngine := alert.NewEngine(st, notifHub) + renderer, err := ui.New() if err != nil { return fmt.Errorf("ui: %w", err) } deps := rmhttp.Deps{ - Cfg: cfg, - Store: st, - AEAD: aead, - Hub: hub, - JobHub: jobHub, - UI: renderer, - Version: version, + Cfg: cfg, + Store: st, + AEAD: aead, + Hub: hub, + JobHub: jobHub, + AlertEngine: alertEngine, + NotificationHub: notifHub, + UI: renderer, + Version: version, } // First-run bootstrap: if the users table is empty, mint a one-time @@ -126,6 +133,8 @@ func run() error { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() + go alertEngine.Run(ctx) + errCh := make(chan error, 1) go func() { slog.Info("server listening", "addr", cfg.Listen, "version", version) @@ -177,9 +186,9 @@ func run() error { cutoff := time.Now().Add(-90 * time.Second) if ids, err := st.MarkHostsOfflineStaleReturnIDs(ctx, cutoff); err == nil && len(ids) > 0 { slog.Info("marked hosts offline (stale heartbeat)", "n", len(ids)) - // TODO(G1): notify engine once deps.AlertEngine is wired. - // for _, id := range ids { alertEngine.NotifyHostOffline(id) } - _ = ids + for _, id := range ids { + alertEngine.NotifyHostOffline(id) + } } case <-pendingDrainTick.C: srv.DrainAllDue(ctx)