diff --git a/internal/command/views/cloud.go b/internal/command/views/cloud.go index 8b9d4adeef73..4dcdf52f3f86 100644 --- a/internal/command/views/cloud.go +++ b/internal/command/views/cloud.go @@ -53,24 +53,13 @@ func (v *CloudHuman) Diagnostics(diags tfdiags.Diagnostics) { } func (v *CloudHuman) RetryLog(attemptNum int, resp *http.Response) { - // Ignore the first retry to make sure any delayed output will - // be written to the console before we start logging retries. - // - // The retry logic in the TFE client will retry both rate limited - // requests and server errors, but in the cloud backend we only - // care about server errors so we ignore rate limit (429) errors. - if attemptNum == 0 || (resp != nil && resp.StatusCode == 429) { - v.lastRetry = time.Now() + msg, updatedRetryTime := retryLogHelper(attemptNum, resp, &v.lastRetry, v.PrepareMessage) + if msg == "" { + v.lastRetry = updatedRetryTime return } - var msg string - if attemptNum == 1 { - msg = v.PrepareMessage(InitialRetryErrorMessage) - } else { - msg = v.PrepareMessage(RepeatedRetryErrorMessage, time.Since(v.lastRetry).Round(time.Second)) - } - + v.lastRetry = updatedRetryTime v.view.streams.Println(msg) } @@ -108,24 +97,13 @@ func (v *CloudJSON) Diagnostics(diags tfdiags.Diagnostics) { } func (v *CloudJSON) RetryLog(attemptNum int, resp *http.Response) { - // Ignore the first retry to make sure any delayed output will - // be written to the console before we start logging retries. - // - // The retry logic in the TFE client will retry both rate limited - // requests and server errors, but in the cloud backend we only - // care about server errors so we ignore rate limit (429) errors. - if attemptNum == 0 || (resp != nil && resp.StatusCode == 429) { - v.lastRetry = time.Now() + msg, updatedRetryTime := retryLogHelper(attemptNum, resp, &v.lastRetry, v.PrepareMessage) + if msg == "" { + v.lastRetry = updatedRetryTime return } - var msg string - if attemptNum == 1 { - msg = v.PrepareMessage(InitialRetryErrorMessage) - } else { - msg = v.PrepareMessage(RepeatedRetryErrorMessage, time.Since(v.lastRetry).Round(time.Second)) - } - + v.lastRetry = updatedRetryTime v.view.view.streams.Println(msg) } @@ -195,3 +173,24 @@ Terraform to prevent data loss! Trying to restore the connection... const repeatdRetryError = `[reset][yellow]Still trying to restore the connection... (%s elapsed)[reset]` const repeatdRetryErrorJSON = `Still trying to restore the connection... (%s elapsed)` + +// retryLogHelper handles the retry logic for both CloudHuman and CloudJSON. +// It returns the prepared message for the specific retry attempt. +func retryLogHelper(attemptNum int, resp *http.Response, lastRetry *time.Time, prepareMessage func(CloudMessageCode, ...any) string) (string, time.Time) { + // Skip the first retry to ensure any delayed output is logged before retries begin. + // + // While the TFE client retries both rate-limited (429) and server error requests, + // the cloud backend only handles server errors, ignoring rate limit (429) errors. + if attemptNum == 0 || (resp != nil && resp.StatusCode == 429) { + return "", time.Now() + } + + var msg string + if attemptNum == 1 { + msg = prepareMessage(InitialRetryErrorMessage) + } else { + msg = prepareMessage(RepeatedRetryErrorMessage, time.Since(*lastRetry).Round(time.Second)) + } + + return msg, time.Now() +}