package usage import ( "context" "log/slog" "time" ) // AggregateFunc berechnet/aktualisiert Zaehlerstaende aus einer autoritativen // Quelle (z.B. "zaehle Zeilen in einer Modul-Tabelle") — die konkrete Quelle // haengt vom jeweiligen Modul ab und ist nicht Teil dieser Kachel. Das // Aggregations-Grundgerüst selbst (periodischer Trigger) ist es. type AggregateFunc func(ctx context.Context) error // RunPeriodicAggregation ruft aggregate in festen Abstaenden auf, bis ctx // beendet wird — dieselbe In-Prozess-Worker-Goroutine-Konvention wie // internal/tenant.Lifecycle.RunSweeper (Akzeptanzkriterium 1: "periodisch // aggregiert"). func RunPeriodicAggregation(ctx context.Context, interval time.Duration, aggregate AggregateFunc) { ticker := time.NewTicker(interval) defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: if err := aggregate(ctx); err != nil { slog.Error("nutzungszaehler-aggregation fehlgeschlagen", "error", err) } } } }