0

i am trying to overcome intermittent 409 error that occurs while uploading/updating metadata of a file in SharePoint's Document library using Microsoft Graph SDK. To retry failed calls SDK provides WithMaxRetry() and WithShouldRetry() options. The MaxRetry works for error codes 429, and i am assuming that ShouldRetry delegate offers us an option to implement our own logic for the retries. Based on this assumption, i have the below code:

_graphServiceClientFactory.GetClient().Drives[driveId].Root.ItemWithPath(path).ListItem.Fields.Request()
                       .WithShouldRetry((delay, attempt, httpResponse) =>
                        (attempt <= 5 &&
                        (httpResponse.StatusCode == HttpStatusCode.Conflict)))
                       .UpdateAsync(new FieldValueSet { AdditionalData = dataDictionary }); 

In my test the ShouldRetry delegate was never called/evaluated on failures/otherwise, there is no documentation on the usage of WithShouldRetry(). It would be helpful to get inputs on usage of WithShouldRetry() option.

Dev
  • 2,428
  • 2
  • 14
  • 15
user527614
  • 465
  • 5
  • 19
  • WithShouldRetry only works with the default Retry Middleware Handler. If you use a custom Retry Middleware Handler, you have to handle it's retrieval in your implementation. – Dev Dec 18 '20 at 16:07
  • @Dev: I have not used custom middleware. Is the way it is used above correct? If so, what could be the reason for delegate not being called. I am expecting it to be hit when there is a failure, but breakpoint was not being hit. – user527614 Dec 18 '20 at 16:37

1 Answers1

0

It appears that the WithShouldRetry() is faulty, i had reported this issue in GitHub (Microsft Graph SDK repo), and they have marked the issue as Bug.

As a workaround one could use Polly for retry as shown below,

var result = await Policy.Handle<ServiceException>(ex =>
                   ex.StatusCode == HttpStatusCode.Conflict ||
                   ex.StatusCode == HttpStatusCode.Locked ||
                   ex.StatusCode == HttpStatusCode.ServiceUnavailable ||
                    ex.StatusCode == HttpStatusCode.GatewayTimeout ||
                    ex.StatusCode == HttpStatusCode.TooManyRequests)
                    .Or<HttpRequestException>()
                   .WaitAndRetryAsync(3, retryCount => TimeSpan.FromSeconds(Math.Pow(2, retryCount) / 2))
                   .ExecuteAsync<FieldValueSet>(async () =>
                   await GetDriveItemWithPath(itemPath, driveId).ListItem.Fields.Request()
                   .WithMaxRetry(0)
                       .UpdateAsync(new FieldValueSet { AdditionalData = dataDictionary }));

By default Graph SDK does 3 retries for throttled and gateway timeout errors. In the above code those native retries have been blocked by calling WithMaxRetry(0). The internal retry logic of Graph SDK is made part of the Polly implementation.

Note: This Polly implementation should be a temporary solution, i believe it is best to utilize the WithShouldRetry() once the reported bug is resolved.

user527614
  • 465
  • 5
  • 19