alert: construct + run engine; expose hub to handlers

- Construct notification.NewHub and alert.NewEngine at boot in cmd/server/main.go
- Start go alertEngine.Run(ctx) after construction, before the HTTP listener
- Wire AlertEngine and NotificationHub into rmhttp.Deps (fields already existed)
- Remove the TODO(G1) in the offline sweeper; now calls NotifyHostOffline per ID
This commit is contained in:
2026-05-04 20:32:10 +01:00
parent b25f96e465
commit 809c4ed910
+19 -10
View File
@@ -12,8 +12,10 @@ import (
"syscall" "syscall"
"time" "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/auth"
"gitea.dcglab.co.uk/steve/restic-manager/internal/crypto" "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" "gitea.dcglab.co.uk/steve/restic-manager/internal/server/config"
rmhttp "gitea.dcglab.co.uk/steve/restic-manager/internal/server/http" rmhttp "gitea.dcglab.co.uk/steve/restic-manager/internal/server/http"
"gitea.dcglab.co.uk/steve/restic-manager/internal/server/maintenance" "gitea.dcglab.co.uk/steve/restic-manager/internal/server/maintenance"
@@ -82,19 +84,24 @@ func run() error {
hub := ws.NewHub() hub := ws.NewHub()
jobHub := ws.NewJobHub() jobHub := ws.NewJobHub()
notifHub := notification.NewHub(st, aead, cfg.BaseURL)
alertEngine := alert.NewEngine(st, notifHub)
renderer, err := ui.New() renderer, err := ui.New()
if err != nil { if err != nil {
return fmt.Errorf("ui: %w", err) return fmt.Errorf("ui: %w", err)
} }
deps := rmhttp.Deps{ deps := rmhttp.Deps{
Cfg: cfg, Cfg: cfg,
Store: st, Store: st,
AEAD: aead, AEAD: aead,
Hub: hub, Hub: hub,
JobHub: jobHub, JobHub: jobHub,
UI: renderer, AlertEngine: alertEngine,
Version: version, NotificationHub: notifHub,
UI: renderer,
Version: version,
} }
// First-run bootstrap: if the users table is empty, mint a one-time // 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) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop() defer stop()
go alertEngine.Run(ctx)
errCh := make(chan error, 1) errCh := make(chan error, 1)
go func() { go func() {
slog.Info("server listening", "addr", cfg.Listen, "version", version) slog.Info("server listening", "addr", cfg.Listen, "version", version)
@@ -177,9 +186,9 @@ func run() error {
cutoff := time.Now().Add(-90 * time.Second) cutoff := time.Now().Add(-90 * time.Second)
if ids, err := st.MarkHostsOfflineStaleReturnIDs(ctx, cutoff); err == nil && len(ids) > 0 { if ids, err := st.MarkHostsOfflineStaleReturnIDs(ctx, cutoff); err == nil && len(ids) > 0 {
slog.Info("marked hosts offline (stale heartbeat)", "n", len(ids)) slog.Info("marked hosts offline (stale heartbeat)", "n", len(ids))
// TODO(G1): notify engine once deps.AlertEngine is wired. for _, id := range ids {
// for _, id := range ids { alertEngine.NotifyHostOffline(id) } alertEngine.NotifyHostOffline(id)
_ = ids }
} }
case <-pendingDrainTick.C: case <-pendingDrainTick.C:
srv.DrainAllDue(ctx) srv.DrainAllDue(ctx)