diff --git a/internal/cloud/backend_taskStage_policyEvaluation_test.go b/internal/cloud/backend_taskStage_policyEvaluation_test.go index 3d08f74d90..7ea54ec9e9 100644 --- a/internal/cloud/backend_taskStage_policyEvaluation_test.go +++ b/internal/cloud/backend_taskStage_policyEvaluation_test.go @@ -79,7 +79,7 @@ func TestCloud_runTaskStageWithPolicyEvaluation(t *testing.T) { trs := policyEvaluationSummarizer{ cloud: b, } - c.context.Poll(func(i int) (bool, error) { + c.context.Poll(taskStageBackoffMin, taskStageBackoffMax, func(i int) (bool, error) { cont, _, _ := trs.Summarize(c.context, c.writer, c.taskStage()) if cont { return true, nil diff --git a/internal/cloud/backend_taskStage_taskResults_test.go b/internal/cloud/backend_taskStage_taskResults_test.go index 7e14a15282..d6bc731b34 100644 --- a/internal/cloud/backend_taskStage_taskResults_test.go +++ b/internal/cloud/backend_taskStage_taskResults_test.go @@ -151,7 +151,7 @@ func TestCloud_runTasksWithTaskResults(t *testing.T) { trs := taskResultSummarizer{ cloud: b, } - c.context.Poll(func(i int) (bool, error) { + c.context.Poll(taskStageBackoffMin, taskStageBackoffMax, func(i int) (bool, error) { cont, _, _ := trs.Summarize(c.context, c.writer, c.taskStage()) if cont { return true, nil diff --git a/internal/cloud/backend_taskStages.go b/internal/cloud/backend_taskStages.go index 2b288c8b15..72f62f7ba3 100644 --- a/internal/cloud/backend_taskStages.go +++ b/internal/cloud/backend_taskStages.go @@ -11,6 +11,11 @@ import ( type taskStages map[tfe.Stage]*tfe.TaskStage +const ( + taskStageBackoffMin = 4000.0 + taskStageBackoffMax = 12000.0 +) + const taskStageHeader = ` To view this run in a browser, visit: https://%s/app/%s/%s/runs/%s @@ -78,7 +83,7 @@ func (b *Cloud) runTaskStage(ctx *IntegrationContext, output IntegrationOutputWr summarizers = append(summarizers, s) } - return ctx.Poll(func(i int) (bool, error) { + return ctx.Poll(taskStageBackoffMin, taskStageBackoffMax, func(i int) (bool, error) { options := tfe.TaskStageReadOptions{ Include: []tfe.TaskStageIncludeOpt{tfe.TaskStageTaskResults, tfe.PolicyEvaluationsTaskResults}, } @@ -92,39 +97,57 @@ func (b *Cloud) runTaskStage(ctx *IntegrationContext, output IntegrationOutputWr // Waiting for it to start return true, nil // Note: Terminal statuses need to print out one last time just in case - case tfe.TaskStageRunning, tfe.TaskStagePassed, tfe.TaskStageCanceled, tfe.TaskStageErrored, tfe.TaskStageFailed: + case tfe.TaskStageRunning, tfe.TaskStagePassed: for _, s := range summarizers { cont, msg, err := s.Summarize(ctx, output, stage) - if cont { - if msg != nil { - if i%4 == 0 { - if i > 0 { - output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation - } - } - } - return true, nil + if err != nil { + errs.Append(err) + break + } + if !cont { + continue } + + // cont is true and we must continue to poll + if msg != nil { + output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation + } + return true, nil + } + case tfe.TaskStageCanceled, tfe.TaskStageErrored, tfe.TaskStageFailed: + for _, s := range summarizers { + cont, msg, err := s.Summarize(ctx, output, stage) if err != nil { errs.Append(err) + break + } + + if !cont { + continue + } + + // cont is true and we must continue to poll + if msg != nil { + output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation } + return true, nil } + return false, fmt.Errorf("Task Stage %s.", stage.Status) case tfe.TaskStageAwaitingOverride: for _, s := range summarizers { cont, msg, err := s.Summarize(ctx, output, stage) - if cont { - if msg != nil { - if i%4 == 0 { - if i > 0 { - output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation - } - } - } - return true, nil - } if err != nil { errs.Append(err) + break + } + if !cont { + continue + } + // cont is true and we must continue to poll + if msg != nil { + output.OutputElapsed(*msg, len(*msg)) // Up to 2 digits are allowed by the max message allocation } + return true, nil } cont, err := b.processStageOverrides(ctx, output, stage.ID) if err != nil { diff --git a/internal/cloud/cloud_integration.go b/internal/cloud/cloud_integration.go index 047fc57093..cd1c6be96a 100644 --- a/internal/cloud/cloud_integration.go +++ b/internal/cloud/cloud_integration.go @@ -38,14 +38,14 @@ type integrationCLIOutput struct { var _ IntegrationOutputWriter = (*integrationCLIOutput)(nil) // Compile time check -func (s *IntegrationContext) Poll(every func(i int) (bool, error)) error { +func (s *IntegrationContext) Poll(backoffMinInterval float64, backoffMaxInterval float64, every func(i int) (bool, error)) error { for i := 0; ; i++ { select { case <-s.StopContext.Done(): return s.StopContext.Err() case <-s.CancelContext.Done(): return s.CancelContext.Err() - case <-time.After(backoff(backoffMin, backoffMax, i)): + case <-time.After(backoff(backoffMinInterval, backoffMaxInterval, i)): // blocks for a time between min and max }