-
Notifications
You must be signed in to change notification settings - Fork 48
/
AsyncMonitor.cs
109 lines (96 loc) · 5.14 KB
/
AsyncMonitor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// ------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
// ------------------------------------------------------------------------------
namespace Microsoft.Graph
{
using System;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// Monitor for async operations to the Graph service on the client.
/// </summary>
/// <typeparam name="T">The object type to return.</typeparam>
public class AsyncMonitor<T> : IAsyncMonitor<T>
{
private AsyncOperationStatus asyncOperationStatus;
private IBaseClient client;
internal string monitorUrl;
/// <summary>
/// Construct an Async Monitor.
/// </summary>
/// <param name="client">The client to monitor.</param>
/// <param name="monitorUrl">The URL to monitor.</param>
public AsyncMonitor(IBaseClient client, string monitorUrl)
{
this.client = client;
this.monitorUrl = monitorUrl;
}
/// <summary>
/// Poll to check for completion of an async call to the Graph service.
/// </summary>
/// <param name="progress">The progress status.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The operation task.</returns>
public async Task<T> PollForOperationCompletionAsync(IProgress<AsyncOperationStatus> progress, CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
using (var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, this.monitorUrl))
{
using (var responseMessage = await this.client.HttpProvider.SendAsync(httpRequestMessage).ConfigureAwait(false))
{
// The monitor service will return an Accepted status for any monitor operation that hasn't completed.
// If we have a success code that isn't Accepted, the operation is complete. Return the resulting object.
if (responseMessage.StatusCode != HttpStatusCode.Accepted && responseMessage.IsSuccessStatusCode)
{
using (var responseStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
return this.client.HttpProvider.Serializer.DeserializeObject<T>(responseStream);
}
}
using (var responseStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false))
{
this.asyncOperationStatus = this.client.HttpProvider.Serializer.DeserializeObject<AsyncOperationStatus>(responseStream);
if (this.asyncOperationStatus == null)
{
throw new ServiceException(
new Error
{
Code = ErrorConstants.Codes.GeneralException,
Message = "Error retrieving monitor status."
});
}
if (string.Equals(this.asyncOperationStatus.Status, "cancelled", StringComparison.OrdinalIgnoreCase))
{
return default(T);
}
if (string.Equals(this.asyncOperationStatus.Status, "failed", StringComparison.OrdinalIgnoreCase)
|| string.Equals(this.asyncOperationStatus.Status, "deleteFailed", StringComparison.OrdinalIgnoreCase))
{
object message = null;
if (this.asyncOperationStatus.AdditionalData != null)
{
this.asyncOperationStatus.AdditionalData.TryGetValue("message", out message);
}
throw new ServiceException(
new Error
{
Code = ErrorConstants.Codes.GeneralException,
Message = message as string
});
}
if (progress != null)
{
progress.Report(this.asyncOperationStatus);
}
}
}
}
await Task.Delay(CoreConstants.PollingIntervalInMs, cancellationToken).ConfigureAwait(false);
}
return default(T);
}
}
}