From e0cbc201409706d4036b5a7280d2ef687b00557c Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Mon, 9 Feb 2026 17:13:20 +1100 Subject: [PATCH] potential performance improvements for hourly inventory --- internal/tasks/inventorySnapshots.go | 41 ++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/internal/tasks/inventorySnapshots.go b/internal/tasks/inventorySnapshots.go index bb071fa..3059a9e 100644 --- a/internal/tasks/inventorySnapshots.go +++ b/internal/tasks/inventorySnapshots.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "log/slog" + "sort" "strconv" "strings" "sync" @@ -164,6 +165,7 @@ func (c *CronTask) RunVcenterSnapshotHourly(ctx context.Context, logger *slog.Lo if concurrencyLimit > 0 { sem = make(chan struct{}, concurrencyLimit) } + var deferredReportTables sync.Map c.Logger.Info("Starting hourly snapshots", "vcenter_count", len(c.Settings.Values.Settings.VcenterAddresses), "concurrency_limit", concurrencyLimit) for _, url := range c.Settings.Values.Settings.VcenterAddresses { wg.Add(1) @@ -182,7 +184,7 @@ func (c *CronTask) RunVcenterSnapshotHourly(ctx context.Context, logger *slog.Lo defer cancel() c.Logger.Info("Starting hourly snapshot for vcenter", "url", url) - if err := c.captureHourlySnapshotForVcenter(runCtx, startTime, tableName, url); err != nil { + if err := c.captureHourlySnapshotForVcenter(runCtx, startTime, tableName, url, &deferredReportTables); err != nil { atomic.AddInt64(&errCount, 1) c.Logger.Error("hourly snapshot failed", "error", err, "url", url) } else { @@ -211,6 +213,22 @@ func (c *CronTask) RunVcenterSnapshotHourly(ctx context.Context, logger *slog.Lo } metrics.RecordHourlySnapshot(startTime, rowCount, err) + var deferredTables []string + deferredReportTables.Range(func(key, _ interface{}) bool { + name, ok := key.(string) + if ok && strings.TrimSpace(name) != "" && name != tableName { + deferredTables = append(deferredTables, name) + } + return true + }) + sort.Strings(deferredTables) + for _, reportTable := range deferredTables { + if err := c.generateReport(ctx, reportTable); err != nil { + c.Logger.Warn("failed to regenerate deferred hourly report after deletions", "error", err, "table", reportTable) + } else { + c.Logger.Debug("Regenerated deferred hourly report after deletions", "table", reportTable) + } + } if err := c.generateReport(ctx, tableName); err != nil { c.Logger.Warn("failed to generate hourly report", "error", err, "table", tableName) } @@ -277,7 +295,7 @@ func (c *CronTask) RunHourlySnapshotRetry(ctx context.Context, logger *slog.Logg continue } logger.Info("Retrying hourly snapshot", "vcenter", f.Vcenter, "snapshot_time", startTime, "attempt", f.Attempts+1) - if err := c.captureHourlySnapshotForVcenter(ctx, startTime, tableName, f.Vcenter); err != nil { + if err := c.captureHourlySnapshotForVcenter(ctx, startTime, tableName, f.Vcenter, nil); err != nil { logger.Warn("retry failed", "vcenter", f.Vcenter, "error", err) } } @@ -1037,7 +1055,7 @@ func (c *CronTask) initVcenterResources(ctx context.Context, log *slog.Logger, u return vc, res, cleanup, nil } -func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTime time.Time, tableName string, url string) error { +func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTime time.Time, tableName string, url string, deferredReportTables *sync.Map) error { log := c.Logger.With("vcenter", url) ctx = context.WithValue(ctx, ctxLoggerKey{}, log) started := time.Now() @@ -1356,11 +1374,18 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim if len(reportTables) == 0 { reportTables[tableName] = struct{}{} } - for reportTable := range reportTables { - if err := c.generateReport(ctx, reportTable); err != nil { - log.Warn("failed to regenerate hourly report after deletions", "error", err, "table", reportTable) - } else { - log.Debug("Regenerated hourly report after deletions", "table", reportTable) + if deferredReportTables != nil { + for reportTable := range reportTables { + deferredReportTables.Store(reportTable, struct{}{}) + } + log.Debug("Queued hourly report regeneration after deletions", "tables", len(reportTables)) + } else { + for reportTable := range reportTables { + if err := c.generateReport(ctx, reportTable); err != nil { + log.Warn("failed to regenerate hourly report after deletions", "error", err, "table", reportTable) + } else { + log.Debug("Regenerated hourly report after deletions", "table", reportTable) + } } } }