root / trunk / Pithos.Network / PithosClient.cs @ 82db721b
History | View | Annotate | Download (14.5 kB)
1 | 4d301e8e | Panagiotis Kanavos | // ----------------------------------------------------------------------- |
---|---|---|---|
2 | 4d301e8e | Panagiotis Kanavos | // <copyright file="PithosClient.cs" company="Microsoft"> |
3 | 4d301e8e | Panagiotis Kanavos | // TODO: Update copyright text. |
4 | 4d301e8e | Panagiotis Kanavos | // </copyright> |
5 | 4d301e8e | Panagiotis Kanavos | // ----------------------------------------------------------------------- |
6 | 4d301e8e | Panagiotis Kanavos | |
7 | 4d301e8e | Panagiotis Kanavos | using System.Collections.Specialized; |
8 | 4d301e8e | Panagiotis Kanavos | using System.Diagnostics; |
9 | 4d301e8e | Panagiotis Kanavos | using System.Diagnostics.Contracts; |
10 | 7d915c34 | Panagiotis Kanavos | using System.IO; |
11 | 4d301e8e | Panagiotis Kanavos | using System.Net; |
12 | 4d301e8e | Panagiotis Kanavos | using System.Runtime.Serialization; |
13 | 7d915c34 | Panagiotis Kanavos | using System.Threading.Tasks; |
14 | 4d301e8e | Panagiotis Kanavos | |
15 | 4d301e8e | Panagiotis Kanavos | namespace Pithos.Network |
16 | 4d301e8e | Panagiotis Kanavos | { |
17 | 4d301e8e | Panagiotis Kanavos | using System; |
18 | 4d301e8e | Panagiotis Kanavos | using System.Collections.Generic; |
19 | 4d301e8e | Panagiotis Kanavos | using System.Linq; |
20 | 4d301e8e | Panagiotis Kanavos | using System.Text; |
21 | 4d301e8e | Panagiotis Kanavos | |
22 | 4d301e8e | Panagiotis Kanavos | /// <summary> |
23 | 4d301e8e | Panagiotis Kanavos | /// TODO: Update summary. |
24 | 4d301e8e | Panagiotis Kanavos | /// </summary> |
25 | 4d301e8e | Panagiotis Kanavos | public class PithosClient:WebClient |
26 | 4d301e8e | Panagiotis Kanavos | { |
27 | 4d301e8e | Panagiotis Kanavos | public int Timeout { get; set; } |
28 | 4d301e8e | Panagiotis Kanavos | |
29 | 4d301e8e | Panagiotis Kanavos | public bool TimedOut { get; set; } |
30 | 4d301e8e | Panagiotis Kanavos | |
31 | 4d301e8e | Panagiotis Kanavos | public HttpStatusCode StatusCode { get; private set; } |
32 | 4d301e8e | Panagiotis Kanavos | |
33 | 4d301e8e | Panagiotis Kanavos | public string StatusDescription { get; set; } |
34 | 4d301e8e | Panagiotis Kanavos | |
35 | 4d301e8e | Panagiotis Kanavos | |
36 | 4d301e8e | Panagiotis Kanavos | public int Retries { get; set; } |
37 | 4d301e8e | Panagiotis Kanavos | |
38 | 4d301e8e | Panagiotis Kanavos | private readonly Dictionary<string, string> _parameters=new Dictionary<string, string>(); |
39 | 4d301e8e | Panagiotis Kanavos | public Dictionary<string, string> Parameters |
40 | 4d301e8e | Panagiotis Kanavos | { |
41 | 4d301e8e | Panagiotis Kanavos | get { return _parameters; } |
42 | 4d301e8e | Panagiotis Kanavos | } |
43 | 4d301e8e | Panagiotis Kanavos | |
44 | 4d301e8e | Panagiotis Kanavos | public PithosClient():base() |
45 | 4d301e8e | Panagiotis Kanavos | { |
46 | 4d301e8e | Panagiotis Kanavos | |
47 | 4d301e8e | Panagiotis Kanavos | } |
48 | 4d301e8e | Panagiotis Kanavos | |
49 | d15e99b4 | Panagiotis Kanavos | |
50 | 4d301e8e | Panagiotis Kanavos | public PithosClient(PithosClient other) |
51 | 4d301e8e | Panagiotis Kanavos | : base() |
52 | 4d301e8e | Panagiotis Kanavos | { |
53 | 4d301e8e | Panagiotis Kanavos | CopyHeaders(other); |
54 | 4d301e8e | Panagiotis Kanavos | Timeout = other.Timeout; |
55 | 4d301e8e | Panagiotis Kanavos | Retries = other.Retries; |
56 | 82db721b | Panagiotis Kanavos | BaseAddress = other.BaseAddress; |
57 | 4d301e8e | Panagiotis Kanavos | |
58 | 4d301e8e | Panagiotis Kanavos | foreach (var parameter in other.Parameters) |
59 | 4d301e8e | Panagiotis Kanavos | { |
60 | 4d301e8e | Panagiotis Kanavos | Parameters.Add(parameter.Key,parameter.Value); |
61 | 4d301e8e | Panagiotis Kanavos | } |
62 | 4d301e8e | Panagiotis Kanavos | |
63 | 4d301e8e | Panagiotis Kanavos | this.Proxy = other.Proxy; |
64 | 4d301e8e | Panagiotis Kanavos | } |
65 | 4d301e8e | Panagiotis Kanavos | |
66 | 4d301e8e | Panagiotis Kanavos | protected override WebRequest GetWebRequest(Uri address) |
67 | 4d301e8e | Panagiotis Kanavos | { |
68 | 4d301e8e | Panagiotis Kanavos | TimedOut = false; |
69 | 4d301e8e | Panagiotis Kanavos | HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest; |
70 | 4d301e8e | Panagiotis Kanavos | request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip; |
71 | 4d301e8e | Panagiotis Kanavos | if(Timeout>0) |
72 | 4d301e8e | Panagiotis Kanavos | request.Timeout = Timeout; |
73 | 4d301e8e | Panagiotis Kanavos | return request; |
74 | 4d301e8e | Panagiotis Kanavos | } |
75 | 4d301e8e | Panagiotis Kanavos | |
76 | 4d301e8e | Panagiotis Kanavos | protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) |
77 | 4d301e8e | Panagiotis Kanavos | { |
78 | 4d301e8e | Panagiotis Kanavos | var response = (HttpWebResponse) base.GetWebResponse(request, result); |
79 | 4d301e8e | Panagiotis Kanavos | StatusCode=response.StatusCode; |
80 | 4d301e8e | Panagiotis Kanavos | StatusDescription=response.StatusDescription; |
81 | 4d301e8e | Panagiotis Kanavos | return response; |
82 | 4d301e8e | Panagiotis Kanavos | } |
83 | 4d301e8e | Panagiotis Kanavos | |
84 | 4d301e8e | Panagiotis Kanavos | |
85 | 4d301e8e | Panagiotis Kanavos | |
86 | 4d301e8e | Panagiotis Kanavos | protected override WebResponse GetWebResponse(WebRequest request) |
87 | 4d301e8e | Panagiotis Kanavos | { |
88 | 7d915c34 | Panagiotis Kanavos | try |
89 | 7d915c34 | Panagiotis Kanavos | { |
90 | 7d915c34 | Panagiotis Kanavos | |
91 | 4d301e8e | Panagiotis Kanavos | var response = (HttpWebResponse)base.GetWebResponse(request); |
92 | 4d301e8e | Panagiotis Kanavos | StatusCode = response.StatusCode; |
93 | 4d301e8e | Panagiotis Kanavos | StatusDescription = response.StatusDescription; |
94 | 4d301e8e | Panagiotis Kanavos | return response; |
95 | 7d915c34 | Panagiotis Kanavos | } |
96 | 7d915c34 | Panagiotis Kanavos | catch (WebException exc) |
97 | 7d915c34 | Panagiotis Kanavos | { |
98 | 82db721b | Panagiotis Kanavos | if (exc.Response!=null && exc.Response.ContentLength > 0) |
99 | 7d915c34 | Panagiotis Kanavos | { |
100 | 82db721b | Panagiotis Kanavos | string content = GetContent(exc.Response); |
101 | 7d915c34 | Panagiotis Kanavos | Trace.TraceError(content); |
102 | 7d915c34 | Panagiotis Kanavos | } |
103 | 7d915c34 | Panagiotis Kanavos | throw; |
104 | 7d915c34 | Panagiotis Kanavos | } |
105 | 7d915c34 | Panagiotis Kanavos | } |
106 | 7d915c34 | Panagiotis Kanavos | |
107 | 7d915c34 | Panagiotis Kanavos | private static string GetContent(WebResponse webResponse) |
108 | 7d915c34 | Panagiotis Kanavos | { |
109 | 7d915c34 | Panagiotis Kanavos | string content; |
110 | 7d915c34 | Panagiotis Kanavos | using (var stream = webResponse.GetResponseStream()) |
111 | 7d915c34 | Panagiotis Kanavos | using (var reader = new StreamReader(stream)) |
112 | 7d915c34 | Panagiotis Kanavos | { |
113 | 7d915c34 | Panagiotis Kanavos | content = reader.ReadToEnd(); |
114 | 7d915c34 | Panagiotis Kanavos | } |
115 | 7d915c34 | Panagiotis Kanavos | return content; |
116 | 4d301e8e | Panagiotis Kanavos | } |
117 | 4d301e8e | Panagiotis Kanavos | |
118 | 4d301e8e | Panagiotis Kanavos | public string DownloadStringWithRetry(string address,int retries=0) |
119 | 4d301e8e | Panagiotis Kanavos | { |
120 | 4d301e8e | Panagiotis Kanavos | if (address == null) |
121 | 4d301e8e | Panagiotis Kanavos | throw new ArgumentNullException("address"); |
122 | 4d301e8e | Panagiotis Kanavos | |
123 | 4d301e8e | Panagiotis Kanavos | var actualAddress = GetActualAddress(address); |
124 | 4d301e8e | Panagiotis Kanavos | |
125 | 82db721b | Panagiotis Kanavos | TraceStart("GET",actualAddress); |
126 | 82db721b | Panagiotis Kanavos | |
127 | 4d301e8e | Panagiotis Kanavos | var actualRetries = (retries == 0) ? Retries : retries; |
128 | d15e99b4 | Panagiotis Kanavos | |
129 | d15e99b4 | Panagiotis Kanavos | |
130 | 7d915c34 | Panagiotis Kanavos | |
131 | 7d915c34 | Panagiotis Kanavos | var task = Retry(() => |
132 | 4d301e8e | Panagiotis Kanavos | { |
133 | 4d301e8e | Panagiotis Kanavos | var uriString = String.Join("/", BaseAddress, actualAddress); |
134 | 4d301e8e | Panagiotis Kanavos | var content = base.DownloadString(uriString); |
135 | 4d301e8e | Panagiotis Kanavos | |
136 | 4d301e8e | Panagiotis Kanavos | if (StatusCode == HttpStatusCode.NoContent) |
137 | 4d301e8e | Panagiotis Kanavos | return String.Empty; |
138 | 4d301e8e | Panagiotis Kanavos | return content; |
139 | 4d301e8e | Panagiotis Kanavos | |
140 | 4d301e8e | Panagiotis Kanavos | }, actualRetries); |
141 | 4d301e8e | Panagiotis Kanavos | |
142 | 7d915c34 | Panagiotis Kanavos | var result = task.Result; |
143 | 4d301e8e | Panagiotis Kanavos | return result; |
144 | 4d301e8e | Panagiotis Kanavos | } |
145 | 4d301e8e | Panagiotis Kanavos | |
146 | 4d301e8e | Panagiotis Kanavos | public void Head(string address,int retries=0) |
147 | 4d301e8e | Panagiotis Kanavos | { |
148 | 4d301e8e | Panagiotis Kanavos | RetryWithoutContent(address, retries, "HEAD"); |
149 | 4d301e8e | Panagiotis Kanavos | } |
150 | 4d301e8e | Panagiotis Kanavos | |
151 | 4d301e8e | Panagiotis Kanavos | public void PutWithRetry(string address, int retries = 0) |
152 | 4d301e8e | Panagiotis Kanavos | { |
153 | 4d301e8e | Panagiotis Kanavos | RetryWithoutContent(address, retries, "PUT"); |
154 | 4d301e8e | Panagiotis Kanavos | } |
155 | 4d301e8e | Panagiotis Kanavos | |
156 | 4d301e8e | Panagiotis Kanavos | public void DeleteWithRetry(string address,int retries=0) |
157 | 4d301e8e | Panagiotis Kanavos | { |
158 | 4d301e8e | Panagiotis Kanavos | RetryWithoutContent(address, retries, "DELETE"); |
159 | 4d301e8e | Panagiotis Kanavos | } |
160 | 4d301e8e | Panagiotis Kanavos | |
161 | 4d301e8e | Panagiotis Kanavos | public string GetHeaderValue(string headerName) |
162 | 4d301e8e | Panagiotis Kanavos | { |
163 | 4d301e8e | Panagiotis Kanavos | var values=this.ResponseHeaders.GetValues(headerName); |
164 | 4d301e8e | Panagiotis Kanavos | if (values == null) |
165 | 4d301e8e | Panagiotis Kanavos | throw new WebException(String.Format("The {0} header is missing", headerName)); |
166 | 4d301e8e | Panagiotis Kanavos | else |
167 | 4d301e8e | Panagiotis Kanavos | return values[0]; |
168 | 4d301e8e | Panagiotis Kanavos | } |
169 | 4d301e8e | Panagiotis Kanavos | |
170 | 4d301e8e | Panagiotis Kanavos | private void RetryWithoutContent(string address, int retries, string method) |
171 | 4d301e8e | Panagiotis Kanavos | { |
172 | 4d301e8e | Panagiotis Kanavos | if (address == null) |
173 | 4d301e8e | Panagiotis Kanavos | throw new ArgumentNullException("address"); |
174 | 4d301e8e | Panagiotis Kanavos | |
175 | 82db721b | Panagiotis Kanavos | var actualAddress = GetActualAddress(address); |
176 | 4d301e8e | Panagiotis Kanavos | var actualRetries = (retries == 0) ? Retries : retries; |
177 | 82db721b | Panagiotis Kanavos | |
178 | 7d915c34 | Panagiotis Kanavos | var task = Retry(() => |
179 | 4d301e8e | Panagiotis Kanavos | { |
180 | 4d301e8e | Panagiotis Kanavos | var uriString = String.Join("/",BaseAddress ,actualAddress); |
181 | 4d301e8e | Panagiotis Kanavos | var uri = new Uri(uriString); |
182 | 4d301e8e | Panagiotis Kanavos | var request = GetWebRequest(uri); |
183 | 4d301e8e | Panagiotis Kanavos | request.Method = method; |
184 | 4d301e8e | Panagiotis Kanavos | if (ResponseHeaders!=null) |
185 | 4d301e8e | Panagiotis Kanavos | ResponseHeaders.Clear(); |
186 | 4d301e8e | Panagiotis Kanavos | |
187 | 82db721b | Panagiotis Kanavos | TraceStart(method, uriString); |
188 | 82db721b | Panagiotis Kanavos | |
189 | 4d301e8e | Panagiotis Kanavos | var response = (HttpWebResponse)GetWebResponse(request); |
190 | 4d301e8e | Panagiotis Kanavos | StatusCode = response.StatusCode; |
191 | 4d301e8e | Panagiotis Kanavos | StatusDescription = response.StatusDescription; |
192 | 4d301e8e | Panagiotis Kanavos | |
193 | 4d301e8e | Panagiotis Kanavos | |
194 | 4d301e8e | Panagiotis Kanavos | return 0; |
195 | 4d301e8e | Panagiotis Kanavos | }, actualRetries); |
196 | 4d301e8e | Panagiotis Kanavos | |
197 | 7d915c34 | Panagiotis Kanavos | task.Wait(); |
198 | 4d301e8e | Panagiotis Kanavos | } |
199 | 4d301e8e | Panagiotis Kanavos | |
200 | 82db721b | Panagiotis Kanavos | private static void TraceStart(string method, string actualAddress) |
201 | 82db721b | Panagiotis Kanavos | { |
202 | 82db721b | Panagiotis Kanavos | Trace.WriteLine(String.Format("[{0}] {1} {2}", method, DateTime.Now, actualAddress)); |
203 | 82db721b | Panagiotis Kanavos | } |
204 | 82db721b | Panagiotis Kanavos | |
205 | 4d301e8e | Panagiotis Kanavos | private string GetActualAddress(string address) |
206 | 4d301e8e | Panagiotis Kanavos | { |
207 | 4d301e8e | Panagiotis Kanavos | if (Parameters.Count == 0) |
208 | 4d301e8e | Panagiotis Kanavos | return address; |
209 | 4d301e8e | Panagiotis Kanavos | var addressBuilder=new StringBuilder(address); |
210 | 4d301e8e | Panagiotis Kanavos | |
211 | 4d301e8e | Panagiotis Kanavos | bool isFirst = true; |
212 | 4d301e8e | Panagiotis Kanavos | foreach (var parameter in Parameters) |
213 | 4d301e8e | Panagiotis Kanavos | { |
214 | 4d301e8e | Panagiotis Kanavos | if(isFirst) |
215 | 4d301e8e | Panagiotis Kanavos | addressBuilder.AppendFormat("?{0}={1}", parameter.Key, parameter.Value); |
216 | 4d301e8e | Panagiotis Kanavos | else |
217 | 4d301e8e | Panagiotis Kanavos | addressBuilder.AppendFormat("&{0}={1}", parameter.Key, parameter.Value); |
218 | 4d301e8e | Panagiotis Kanavos | isFirst = false; |
219 | 4d301e8e | Panagiotis Kanavos | } |
220 | 4d301e8e | Panagiotis Kanavos | return addressBuilder.ToString(); |
221 | 4d301e8e | Panagiotis Kanavos | } |
222 | 4d301e8e | Panagiotis Kanavos | |
223 | 4d301e8e | Panagiotis Kanavos | public string DownloadStringWithRetry(Uri address,int retries=0) |
224 | 4d301e8e | Panagiotis Kanavos | { |
225 | 4d301e8e | Panagiotis Kanavos | if (address == null) |
226 | 4d301e8e | Panagiotis Kanavos | throw new ArgumentNullException("address"); |
227 | 4d301e8e | Panagiotis Kanavos | |
228 | 4d301e8e | Panagiotis Kanavos | var actualRetries = (retries == 0) ? Retries : retries; |
229 | 7d915c34 | Panagiotis Kanavos | var task = Retry(() => |
230 | 4d301e8e | Panagiotis Kanavos | { |
231 | 4d301e8e | Panagiotis Kanavos | var content = base.DownloadString(address); |
232 | 4d301e8e | Panagiotis Kanavos | |
233 | 4d301e8e | Panagiotis Kanavos | if (StatusCode == HttpStatusCode.NoContent) |
234 | 4d301e8e | Panagiotis Kanavos | return String.Empty; |
235 | 4d301e8e | Panagiotis Kanavos | return content; |
236 | 4d301e8e | Panagiotis Kanavos | |
237 | 4d301e8e | Panagiotis Kanavos | }, actualRetries); |
238 | 4d301e8e | Panagiotis Kanavos | |
239 | 7d915c34 | Panagiotis Kanavos | var result = task.Result; |
240 | 4d301e8e | Panagiotis Kanavos | return result; |
241 | 4d301e8e | Panagiotis Kanavos | } |
242 | 4d301e8e | Panagiotis Kanavos | |
243 | d15e99b4 | Panagiotis Kanavos | |
244 | 4d301e8e | Panagiotis Kanavos | /// <summary> |
245 | d15e99b4 | Panagiotis Kanavos | /// Copies headers from another PithosClient |
246 | 4d301e8e | Panagiotis Kanavos | /// </summary> |
247 | 4d301e8e | Panagiotis Kanavos | /// <param name="source">The PithosClient from which the headers are copied</param> |
248 | 4d301e8e | Panagiotis Kanavos | public void CopyHeaders(PithosClient source) |
249 | 4d301e8e | Panagiotis Kanavos | { |
250 | 4d301e8e | Panagiotis Kanavos | Contract.Requires(source != null, "source can't be null"); |
251 | 4d301e8e | Panagiotis Kanavos | if (source == null) |
252 | 4d301e8e | Panagiotis Kanavos | throw new ArgumentNullException("source", "source can't be null"); |
253 | 4d301e8e | Panagiotis Kanavos | CopyHeaders(source.Headers,Headers); |
254 | 4d301e8e | Panagiotis Kanavos | } |
255 | 4d301e8e | Panagiotis Kanavos | |
256 | 4d301e8e | Panagiotis Kanavos | /// <summary> |
257 | d15e99b4 | Panagiotis Kanavos | /// Copies headers from one header collection to another |
258 | 4d301e8e | Panagiotis Kanavos | /// </summary> |
259 | d15e99b4 | Panagiotis Kanavos | /// <param name="source">The source collection from which the headers are copied</param> |
260 | d15e99b4 | Panagiotis Kanavos | /// <param name="target">The target collection to which the headers are copied</param> |
261 | 4d301e8e | Panagiotis Kanavos | public static void CopyHeaders(WebHeaderCollection source,WebHeaderCollection target) |
262 | 4d301e8e | Panagiotis Kanavos | { |
263 | 4d301e8e | Panagiotis Kanavos | Contract.Requires(source != null, "source can't be null"); |
264 | 4d301e8e | Panagiotis Kanavos | Contract.Requires(target != null, "target can't be null"); |
265 | 4d301e8e | Panagiotis Kanavos | if (source == null) |
266 | 4d301e8e | Panagiotis Kanavos | throw new ArgumentNullException("source", "source can't be null"); |
267 | 4d301e8e | Panagiotis Kanavos | if (target == null) |
268 | 4d301e8e | Panagiotis Kanavos | throw new ArgumentNullException("target", "target can't be null"); |
269 | 4d301e8e | Panagiotis Kanavos | for (int i = 0; i < source.Count; i++) |
270 | 4d301e8e | Panagiotis Kanavos | { |
271 | 4d301e8e | Panagiotis Kanavos | target.Add(source.GetKey(i), source[i]); |
272 | 4d301e8e | Panagiotis Kanavos | } |
273 | 4d301e8e | Panagiotis Kanavos | } |
274 | 4d301e8e | Panagiotis Kanavos | |
275 | 4d301e8e | Panagiotis Kanavos | public void AssertStatusOK(string message) |
276 | 4d301e8e | Panagiotis Kanavos | { |
277 | 4d301e8e | Panagiotis Kanavos | if (StatusCode >= HttpStatusCode.BadRequest) |
278 | 4d301e8e | Panagiotis Kanavos | throw new WebException(String.Format("{0} with code {1} - {2}", message, StatusCode, StatusDescription)); |
279 | 4d301e8e | Panagiotis Kanavos | } |
280 | 4d301e8e | Panagiotis Kanavos | |
281 | 7d915c34 | Panagiotis Kanavos | /*private Func<T> Retry<T>(Func< T> original, int retryCount) |
282 | 4d301e8e | Panagiotis Kanavos | { |
283 | 4d301e8e | Panagiotis Kanavos | return () => |
284 | 4d301e8e | Panagiotis Kanavos | { |
285 | 4d301e8e | Panagiotis Kanavos | while (true) |
286 | 4d301e8e | Panagiotis Kanavos | { |
287 | 4d301e8e | Panagiotis Kanavos | try |
288 | 4d301e8e | Panagiotis Kanavos | { |
289 | 4d301e8e | Panagiotis Kanavos | return original(); |
290 | 4d301e8e | Panagiotis Kanavos | } |
291 | 4d301e8e | Panagiotis Kanavos | catch (WebException e) |
292 | 4d301e8e | Panagiotis Kanavos | { |
293 | 4d301e8e | Panagiotis Kanavos | var statusCode = ((HttpWebResponse)e.Response).StatusCode; |
294 | 4d301e8e | Panagiotis Kanavos | this.StatusCode = statusCode; |
295 | 4d301e8e | Panagiotis Kanavos | |
296 | 4d301e8e | Panagiotis Kanavos | switch (e.Status) |
297 | 4d301e8e | Panagiotis Kanavos | { |
298 | 4d301e8e | Panagiotis Kanavos | case WebExceptionStatus.Timeout: |
299 | 4d301e8e | Panagiotis Kanavos | |
300 | 4d301e8e | Panagiotis Kanavos | TimedOut = true; |
301 | 4d301e8e | Panagiotis Kanavos | if (retryCount == 0) |
302 | 4d301e8e | Panagiotis Kanavos | { |
303 | 4d301e8e | Panagiotis Kanavos | Trace.TraceError("[ERROR] Timed out too many times. {0}\n", e); |
304 | 4d301e8e | Panagiotis Kanavos | throw new RetryException("Timed out too many times.", e); |
305 | 4d301e8e | Panagiotis Kanavos | } |
306 | 4d301e8e | Panagiotis Kanavos | retryCount--; |
307 | 4d301e8e | Panagiotis Kanavos | Trace.TraceError( |
308 | 4d301e8e | Panagiotis Kanavos | "[RETRY] Timed out after {0} ms. Will retry {1} more times\n{2}", Timeout, |
309 | 4d301e8e | Panagiotis Kanavos | retryCount, e); |
310 | 4d301e8e | Panagiotis Kanavos | |
311 | 4d301e8e | Panagiotis Kanavos | break; |
312 | 4d301e8e | Panagiotis Kanavos | case WebExceptionStatus.ProtocolError: |
313 | 4d301e8e | Panagiotis Kanavos | switch (statusCode) |
314 | 4d301e8e | Panagiotis Kanavos | { |
315 | 4d301e8e | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
316 | 4d301e8e | Panagiotis Kanavos | { |
317 | 4d301e8e | Panagiotis Kanavos | return default(T); |
318 | 4d301e8e | Panagiotis Kanavos | } |
319 | 4d301e8e | Panagiotis Kanavos | case HttpStatusCode.ServiceUnavailable: |
320 | 4d301e8e | Panagiotis Kanavos | { |
321 | 4d301e8e | Panagiotis Kanavos | |
322 | 4d301e8e | Panagiotis Kanavos | TimedOut = false; |
323 | 4d301e8e | Panagiotis Kanavos | if (retryCount == 0) |
324 | 4d301e8e | Panagiotis Kanavos | { |
325 | 4d301e8e | Panagiotis Kanavos | Trace.TraceError("[ERROR] Failed too many times. {0}\n", e); |
326 | 4d301e8e | Panagiotis Kanavos | throw new RetryException("Failed too many times.", e); |
327 | 4d301e8e | Panagiotis Kanavos | } |
328 | 4d301e8e | Panagiotis Kanavos | retryCount--; |
329 | 4d301e8e | Panagiotis Kanavos | Trace.TraceError( |
330 | 4d301e8e | Panagiotis Kanavos | "[RETRY] Failed due to 503. Will retry {0} more times\n{1}", retryCount, e); |
331 | 4d301e8e | Panagiotis Kanavos | break; |
332 | 4d301e8e | Panagiotis Kanavos | } |
333 | 4d301e8e | Panagiotis Kanavos | default: |
334 | 4d301e8e | Panagiotis Kanavos | throw; |
335 | 4d301e8e | Panagiotis Kanavos | } |
336 | 4d301e8e | Panagiotis Kanavos | break; |
337 | 4d301e8e | Panagiotis Kanavos | default: |
338 | 4d301e8e | Panagiotis Kanavos | throw; |
339 | 4d301e8e | Panagiotis Kanavos | } |
340 | 4d301e8e | Panagiotis Kanavos | } |
341 | 4d301e8e | Panagiotis Kanavos | } |
342 | 4d301e8e | Panagiotis Kanavos | }; |
343 | 7d915c34 | Panagiotis Kanavos | }*/ |
344 | 7d915c34 | Panagiotis Kanavos | |
345 | 7d915c34 | Panagiotis Kanavos | private Task<T> Retry<T>(Func< T> original, int retryCount) |
346 | 7d915c34 | Panagiotis Kanavos | { |
347 | 7d915c34 | Panagiotis Kanavos | return Task.Factory.StartNew(() => original()).ContinueWith(_original => |
348 | 7d915c34 | Panagiotis Kanavos | { |
349 | 7d915c34 | Panagiotis Kanavos | if(_original.IsFaulted ) |
350 | 7d915c34 | Panagiotis Kanavos | { |
351 | 7d915c34 | Panagiotis Kanavos | var e = _original.Exception.InnerException; |
352 | 7d915c34 | Panagiotis Kanavos | if (e is WebException) |
353 | 7d915c34 | Panagiotis Kanavos | { |
354 | 7d915c34 | Panagiotis Kanavos | var we = (e as WebException); |
355 | 82db721b | Panagiotis Kanavos | |
356 | 82db721b | Panagiotis Kanavos | var statusCode = HttpStatusCode.RequestTimeout; |
357 | 82db721b | Panagiotis Kanavos | if (we.Response != null) |
358 | 82db721b | Panagiotis Kanavos | { |
359 | 82db721b | Panagiotis Kanavos | statusCode = ((HttpWebResponse) we.Response).StatusCode; |
360 | 82db721b | Panagiotis Kanavos | this.StatusCode = statusCode; |
361 | 82db721b | Panagiotis Kanavos | } |
362 | 7d915c34 | Panagiotis Kanavos | |
363 | 7d915c34 | Panagiotis Kanavos | if (we.Status==WebExceptionStatus.Timeout || |
364 | 7d915c34 | Panagiotis Kanavos | (we.Status==WebExceptionStatus.ProtocolError && statusCode==HttpStatusCode.ServiceUnavailable)) |
365 | 7d915c34 | Panagiotis Kanavos | { |
366 | 7d915c34 | Panagiotis Kanavos | TimedOut = true; |
367 | 7d915c34 | Panagiotis Kanavos | if (retryCount == 0) |
368 | 7d915c34 | Panagiotis Kanavos | { |
369 | 7d915c34 | Panagiotis Kanavos | Trace.TraceError("[ERROR] Timed out too many times. {0}\n", e); |
370 | 7d915c34 | Panagiotis Kanavos | throw new RetryException("Timed out too many times.", e); |
371 | 7d915c34 | Panagiotis Kanavos | } |
372 | 7d915c34 | Panagiotis Kanavos | Trace.TraceError( |
373 | 7d915c34 | Panagiotis Kanavos | "[RETRY] Timed out after {0} ms. Will retry {1} more times\n{2}", Timeout, |
374 | 7d915c34 | Panagiotis Kanavos | retryCount, e); |
375 | 7d915c34 | Panagiotis Kanavos | return Retry(original, retryCount - 1); |
376 | 7d915c34 | Panagiotis Kanavos | } |
377 | 7d915c34 | Panagiotis Kanavos | |
378 | 7d915c34 | Panagiotis Kanavos | if (statusCode==HttpStatusCode.NotFound) |
379 | 82db721b | Panagiotis Kanavos | return Task<T>.Factory.StartNew(() => default(T)); |
380 | 7d915c34 | Panagiotis Kanavos | } |
381 | 7d915c34 | Panagiotis Kanavos | throw e; |
382 | 7d915c34 | Panagiotis Kanavos | } |
383 | 7d915c34 | Panagiotis Kanavos | else |
384 | 7d915c34 | Panagiotis Kanavos | return Task<T>.Factory.StartNew(() => _original.Result); |
385 | 7d915c34 | Panagiotis Kanavos | }).Unwrap(); |
386 | 4d301e8e | Panagiotis Kanavos | } |
387 | 4d301e8e | Panagiotis Kanavos | |
388 | 4d301e8e | Panagiotis Kanavos | |
389 | 4d301e8e | Panagiotis Kanavos | } |
390 | 4d301e8e | Panagiotis Kanavos | |
391 | 4d301e8e | Panagiotis Kanavos | public class RetryException:Exception |
392 | 4d301e8e | Panagiotis Kanavos | { |
393 | 4d301e8e | Panagiotis Kanavos | public RetryException() |
394 | 4d301e8e | Panagiotis Kanavos | :base() |
395 | 4d301e8e | Panagiotis Kanavos | { |
396 | 4d301e8e | Panagiotis Kanavos | |
397 | 4d301e8e | Panagiotis Kanavos | } |
398 | 4d301e8e | Panagiotis Kanavos | |
399 | 4d301e8e | Panagiotis Kanavos | public RetryException(string message) |
400 | 4d301e8e | Panagiotis Kanavos | :base(message) |
401 | 4d301e8e | Panagiotis Kanavos | { |
402 | 4d301e8e | Panagiotis Kanavos | |
403 | 4d301e8e | Panagiotis Kanavos | } |
404 | 4d301e8e | Panagiotis Kanavos | |
405 | 4d301e8e | Panagiotis Kanavos | public RetryException(string message,Exception innerException) |
406 | 4d301e8e | Panagiotis Kanavos | :base(message,innerException) |
407 | 4d301e8e | Panagiotis Kanavos | { |
408 | 4d301e8e | Panagiotis Kanavos | |
409 | 4d301e8e | Panagiotis Kanavos | } |
410 | 4d301e8e | Panagiotis Kanavos | |
411 | 4d301e8e | Panagiotis Kanavos | public RetryException(SerializationInfo info,StreamingContext context) |
412 | 4d301e8e | Panagiotis Kanavos | :base(info,context) |
413 | 4d301e8e | Panagiotis Kanavos | { |
414 | 4d301e8e | Panagiotis Kanavos | |
415 | 4d301e8e | Panagiotis Kanavos | } |
416 | 4d301e8e | Panagiotis Kanavos | } |
417 | 4d301e8e | Panagiotis Kanavos | } |