From 00c668fc920e7bafbccf4639136f96ba8fb357b7 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Thu, 19 Feb 2026 10:08:43 +0100 Subject: [PATCH] =?UTF-8?q?v0.15.5:=20Fix=20startup=20hub=20report=20?= =?UTF-8?q?=E2=80=94=20Push()=20returns=20real=20errors,=20startup=20retri?= =?UTF-8?q?es=203x=20with=2015s=20delay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++++ controller/cmd/controller/main.go | 18 ++++++++++++++---- controller/internal/report/pusher.go | 7 ++----- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dd4295..8e07e10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ ## Changelog +### What was just completed (2026-02-19 session 55) +- **v0.15.5 — Fix startup hub report silently failing:** + + `Push()` now returns actual errors instead of always `nil`. Previously, push failures were logged internally but the caller could never detect them, leading to a misleading `[INFO] Startup hub report sent` log even when the push actually failed (e.g., hub returning HTTP 503 during simultaneous deployment). Removed the "Never returns error to caller" behavior: marshal error returns a wrapped error, and after 3 failed retries the error is returned to the caller (the internal `[WARN]` log before `return nil` is gone). + + Startup hub push now retries 3 times with 15-second delays between outer attempts, giving the hub time to come up when both are deployed together. Each outer attempt uses `Push()`'s own internal 3-retry logic (5s backoff), so the hub gets up to ~40s total to become ready. If all 3 outer attempts fail, logs a clear warning with the next scheduled push interval. + + **Files modified (2):** `internal/report/pusher.go`, `cmd/controller/main.go` + ### What was just completed (2026-02-19 session 54) - **v0.15.4 (controller) + hub v0.1.6 — Hub reporting improvements:** diff --git a/controller/cmd/controller/main.go b/controller/cmd/controller/main.go index fa42505..4e2eb59 100644 --- a/controller/cmd/controller/main.go +++ b/controller/cmd/controller/main.go @@ -290,10 +290,20 @@ func main() { if hubPusher != nil { if cfg.Hub.Enabled { r := report.BuildReport(cfg, stackMgr, backupMgr, cpuCollector, metricsStore, Version, sett.GetStoragePaths()) - if err := hubPusher.Push(r); err != nil { - logger.Printf("[WARN] Startup hub report failed: %v", err) - } else { - logger.Println("[INFO] Startup hub report sent") + var pushErr error + for attempt := 1; attempt <= 3; attempt++ { + pushErr = hubPusher.Push(r) + if pushErr == nil { + logger.Println("[INFO] Startup hub report sent") + break + } + logger.Printf("[WARN] Startup hub report attempt %d/3 failed: %v", attempt, pushErr) + if attempt < 3 { + time.Sleep(15 * time.Second) + } + } + if pushErr != nil { + logger.Printf("[WARN] Startup hub report failed after 3 attempts — next scheduled push in %s", cfg.Hub.PushInterval) } } else { // Send a minimal "disabled" notification so hub knows reporting is intentionally off diff --git a/controller/internal/report/pusher.go b/controller/internal/report/pusher.go index 2c69611..87c0168 100644 --- a/controller/internal/report/pusher.go +++ b/controller/internal/report/pusher.go @@ -36,7 +36,6 @@ func NewPusher(cfg *config.HubConfig, logger *log.Logger) *Pusher { } // Push sends a report to the hub. Retries 3 times with 5s backoff. -// Never returns error to caller — push failures should not affect controller operation. func (p *Pusher) Push(report *Report) error { if !p.enabled { return nil @@ -44,8 +43,7 @@ func (p *Pusher) Push(report *Report) error { data, err := json.Marshal(report) if err != nil { - p.logger.Printf("[WARN] Hub report marshal failed: %v", err) - return nil + return fmt.Errorf("marshal report: %w", err) } url := p.hubURL + "/api/v1/report" @@ -81,8 +79,7 @@ func (p *Pusher) Push(report *Report) error { lastErr = fmt.Errorf("HTTP %d", resp.StatusCode) } - p.logger.Printf("[WARN] Hub report push failed after 3 attempts: %v", lastErr) - return nil + return fmt.Errorf("hub push failed after 3 attempts: %w", lastErr) } // PushOnce sends a single report regardless of the enabled flag.