diff --git a/cmd/root.go b/cmd/root.go index ba543cd..4099dc4 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -51,10 +51,10 @@ var rootCmd = &cobra.Command{ log.SetLevel(log.DebugLevel) } - // Check for updates in background (non-blocking) + // Check for updates if 24h have passed (non-blocking with 3s timeout) // Skip update check for the update command itself if cmd.Name() != "update" { - updater.CheckInBackground(cmd.Context(), Version) + updater.CheckAndUpdateState(cmd.Context(), Version) // Show notification if update is available if shouldNotify, latestVersion := updater.ShouldNotifyUpdate(Version); shouldNotify { diff --git a/internal/updater/checker.go b/internal/updater/checker.go index 8ca6eae..7914f25 100644 --- a/internal/updater/checker.go +++ b/internal/updater/checker.go @@ -87,33 +87,36 @@ func CheckForUpdate(ctx context.Context, currentVersion string) (*UpdateInfo, er }, nil } -// CheckInBackground performs a background check and updates the state file -func CheckInBackground(ctx context.Context, currentVersion string) { - go func() { - state, err := LoadState() - if err != nil { - // Silently fail - don't block CLI - return - } +// CheckAndUpdateState performs a check if needed and updates the state file +// This runs synchronously but with a timeout to avoid blocking the CLI +func CheckAndUpdateState(ctx context.Context, currentVersion string) { + state, err := LoadState() + if err != nil { + // Silently fail - don't block CLI + return + } - if !state.ShouldCheck() { - return - } + if !state.ShouldCheck() { + return + } - updateInfo, err := CheckForUpdate(ctx, currentVersion) - if err != nil { - // Silently fail - don't block CLI or spam errors - // Just update the timestamp so we don't retry immediately - state.LastCheck = time.Now() - _ = state.Save() - return - } + // Use a timeout context to ensure we don't block for too long + checkCtx, cancel := context.WithTimeout(ctx, 3*time.Second) + defer cancel() - // Update state + updateInfo, err := CheckForUpdate(checkCtx, currentVersion) + if err != nil { + // Silently fail - don't block CLI or spam errors + // Just update the timestamp so we don't retry immediately state.LastCheck = time.Now() - state.LatestVersion = updateInfo.LatestVersion _ = state.Save() - }() + return + } + + // Update state + state.LastCheck = time.Now() + state.LatestVersion = updateInfo.LatestVersion + _ = state.Save() } // ShouldNotifyUpdate checks if we should notify the user about an update