From 695bc8178a534b875f0769bd0cd22d92fae76382 Mon Sep 17 00:00:00 2001 From: Shayne Boyer Date: Thu, 26 Feb 2026 18:25:46 -0500 Subject: [PATCH 1/2] perf: skip redundant recursive traversal in provisioning progress polling Track root operation count and running-ops state between poll cycles. When the operation count is unchanged and no operations are still running, skip the expensive recursive deployment traversal. Keeps 3s poll cadence for near-real-time responsiveness but avoids redundant ARM API calls during the idle tail of long provisioning runs (e.g., waiting for Cosmos DB or Container Apps Environment). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../infra/provisioning_progress_display.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/cli/azd/pkg/infra/provisioning_progress_display.go b/cli/azd/pkg/infra/provisioning_progress_display.go index ca564d0dd75..cf59fca6cee 100644 --- a/cli/azd/pkg/infra/provisioning_progress_display.go +++ b/cli/azd/pkg/infra/provisioning_progress_display.go @@ -30,6 +30,12 @@ type ProvisioningProgressDisplay struct { resourceManager ResourceManager console input.Console deployment Deployment + // Tracks root operation count from the last poll cycle to skip + // expensive recursive traversal when nothing has changed. + lastRootOpCount int + // Whether any operations were still running at last poll. + // When true, we always do the full traversal on next poll. + hasRunningOps bool } func NewProvisioningProgressDisplay( @@ -93,6 +99,15 @@ func (display *ProvisioningProgressDisplay) ReportProgress( return err } + // Quick check: skip processing if nothing has changed since last poll. + // This avoids redundant recursive traversal when the deployment is idle + // (e.g., waiting for a long-running resource to finish). + currentOpCount := len(operations) + if currentOpCount == display.lastRootOpCount && !display.hasRunningOps { + return nil + } + display.lastRootOpCount = currentOpCount + newlyDeployedResources := []*armresources.DeploymentOperation{} newlyFailedResources := []*armresources.DeploymentOperation{} runningDeployments := []*armresources.DeploymentOperation{} @@ -123,6 +138,11 @@ func (display *ProvisioningProgressDisplay) ReportProgress( displayedResources := append(newlyDeployedResources, newlyFailedResources...) display.logNewlyCreatedResources(ctx, displayedResources, runningDeployments) + + // Track whether any operations are still running so the next poll + // cycle knows to do the full traversal or can skip it. + display.hasRunningOps = len(runningDeployments) > 0 + return nil } From 6324b58bef545af7df8c91872ed1e6dcbd8af503 Mon Sep 17 00:00:00 2001 From: Shayne Boyer Date: Thu, 26 Feb 2026 20:16:27 -0500 Subject: [PATCH 2/2] fix: initialize lastRootOpCount to -1 so first poll always processes Prevents skipping the first poll cycle when zero operations are returned, which would leave users without the initial spinner. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cli/azd/pkg/infra/provisioning_progress_display.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/azd/pkg/infra/provisioning_progress_display.go b/cli/azd/pkg/infra/provisioning_progress_display.go index cf59fca6cee..d9a266a34ba 100644 --- a/cli/azd/pkg/infra/provisioning_progress_display.go +++ b/cli/azd/pkg/infra/provisioning_progress_display.go @@ -32,6 +32,7 @@ type ProvisioningProgressDisplay struct { deployment Deployment // Tracks root operation count from the last poll cycle to skip // expensive recursive traversal when nothing has changed. + // Initialized to -1 so the first poll always processes. lastRootOpCount int // Whether any operations were still running at last poll. // When true, we always do the full traversal on next poll. @@ -48,6 +49,7 @@ func NewProvisioningProgressDisplay( deployment: deployment, resourceManager: rm, console: console, + lastRootOpCount: -1, } }