using Microsoft.SharePoint.Client; using SharepointToolbox.Web.Core.Models; namespace SharepointToolbox.Web.Core.Helpers; public static class ExecuteQueryRetryHelper { private const int MaxRetries = 5; public static async Task ExecuteQueryRetryAsync( ClientContext ctx, IProgress? progress = null, CancellationToken ct = default) { int attempt = 0; while (true) { ct.ThrowIfCancellationRequested(); try { await ctx.ExecuteQueryAsync(); return; } catch (Exception ex) when (IsThrottleException(ex) && attempt < MaxRetries) { attempt++; int delaySeconds = (int)Math.Pow(2, attempt) * 5; progress?.Report(OperationProgress.Indeterminate( $"Throttled by SharePoint — retrying in {delaySeconds}s (attempt {attempt}/{MaxRetries})…")); await Task.Delay(TimeSpan.FromSeconds(delaySeconds), ct); } } } internal static bool IsThrottleException(Exception ex) { var msg = ex.Message; return msg.Contains("429") || msg.Contains("503") || msg.Contains("throttl", StringComparison.OrdinalIgnoreCase); } }