| 
1 | 1 | // Copyright (c) Microsoft. All rights reserved.  | 
2 | 2 | using System;  | 
 | 3 | +using System.ClientModel;  | 
3 | 4 | using System.Collections.Generic;  | 
4 | 5 | using System.Linq;  | 
5 | 6 | using System.Net;  | 
@@ -179,9 +180,11 @@ public static async IAsyncEnumerable<ChatMessageContent> GetMessagesAsync(Assist  | 
179 | 180 |         // Evaluate status and process steps and messages, as encountered.  | 
180 | 181 |         HashSet<string> processedStepIds = [];  | 
181 | 182 |         Dictionary<string, FunctionResultContent> functionSteps = [];  | 
182 |  | - | 
183 | 183 |         do  | 
184 | 184 |         {  | 
 | 185 | +            // Check for cancellation  | 
 | 186 | +            cancellationToken.ThrowIfCancellationRequested();  | 
 | 187 | + | 
185 | 188 |             // Poll run and steps until actionable  | 
186 | 189 |             await PollRunStatusAsync().ConfigureAwait(false);  | 
187 | 190 | 
 
  | 
@@ -301,20 +304,49 @@ async Task PollRunStatusAsync()  | 
301 | 304 | 
 
  | 
302 | 305 |             do  | 
303 | 306 |             {  | 
304 |  | -                // Reduce polling frequency after a couple attempts  | 
305 |  | -                await Task.Delay(agent.PollingOptions.GetPollingInterval(count), cancellationToken).ConfigureAwait(false);  | 
 | 307 | +                cancellationToken.ThrowIfCancellationRequested();  | 
 | 308 | + | 
 | 309 | +                if (count > 0)  | 
 | 310 | +                {  | 
 | 311 | +                    // Reduce polling frequency after a couple attempts  | 
 | 312 | +                    await Task.Delay(agent.PollingOptions.GetPollingInterval(count), cancellationToken).ConfigureAwait(false);  | 
 | 313 | +                }  | 
 | 314 | + | 
306 | 315 |                 ++count;  | 
307 | 316 | 
 
  | 
308 |  | -#pragma warning disable CA1031 // Do not catch general exception types  | 
309 | 317 |                 try  | 
310 | 318 |                 {  | 
311 | 319 |                     run = await client.GetRunAsync(threadId, run.Id, cancellationToken).ConfigureAwait(false);  | 
312 | 320 |                 }  | 
313 |  | -                catch  | 
 | 321 | +                // The presence of a `Status` code means the server responded with error...always fail in that case  | 
 | 322 | +                catch (ClientResultException clientException) when (clientException.Status <= 0)  | 
 | 323 | +                {  | 
 | 324 | +                    // Check maximum retry count  | 
 | 325 | +                    if (count >= agent.PollingOptions.MaximumRetryCount)  | 
 | 326 | +                    {  | 
 | 327 | +                        throw;  | 
 | 328 | +                    }  | 
 | 329 | + | 
 | 330 | +                    // Retry for potential transient failure  | 
 | 331 | +                    continue;  | 
 | 332 | +                }  | 
 | 333 | +                catch (AggregateException aggregateException) when (aggregateException.InnerException is ClientResultException innerClientException)  | 
314 | 334 |                 {  | 
315 |  | -                    // Retry anyway..  | 
 | 335 | +                    // The presence of a `Status` code means the server responded with error  | 
 | 336 | +                    if (innerClientException.Status > 0)  | 
 | 337 | +                    {  | 
 | 338 | +                        throw;  | 
 | 339 | +                    }  | 
 | 340 | + | 
 | 341 | +                    // Check maximum retry count  | 
 | 342 | +                    if (count >= agent.PollingOptions.MaximumRetryCount)  | 
 | 343 | +                    {  | 
 | 344 | +                        throw;  | 
 | 345 | +                    }  | 
 | 346 | + | 
 | 347 | +                    // Retry for potential transient failure  | 
 | 348 | +                    continue;  | 
316 | 349 |                 }  | 
317 |  | -#pragma warning restore CA1031 // Do not catch general exception types  | 
318 | 350 |             }  | 
319 | 351 |             while (s_pollingStatuses.Contains(run.Status));  | 
320 | 352 | 
 
  | 
@@ -373,6 +405,9 @@ public static async IAsyncEnumerable<StreamingChatMessageContent> InvokeStreamin  | 
373 | 405 |         IAsyncEnumerable<StreamingUpdate> asyncUpdates = client.CreateRunStreamingAsync(threadId, agent.Id, options, cancellationToken);  | 
374 | 406 |         do  | 
375 | 407 |         {  | 
 | 408 | +            // Check for cancellation  | 
 | 409 | +            cancellationToken.ThrowIfCancellationRequested();  | 
 | 410 | + | 
376 | 411 |             stepsToProcess.Clear();  | 
377 | 412 | 
 
  | 
378 | 413 |             await foreach (StreamingUpdate update in asyncUpdates.ConfigureAwait(false))  | 
 | 
0 commit comments