Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* | 1 /* |
2 Copyright 2013 Google Inc | 2 Copyright 2013 Google Inc |
3 | 3 |
4 Licensed under the Apache License, Version 2.0 (the "License"); | 4 Licensed under the Apache License, Version 2.0 (the "License"); |
5 you may not use this file except in compliance with the License. | 5 you may not use this file except in compliance with the License. |
6 You may obtain a copy of the License at | 6 You may obtain a copy of the License at |
7 | 7 |
8 http://www.apache.org/licenses/LICENSE-2.0 | 8 http://www.apache.org/licenses/LICENSE-2.0 |
9 | 9 |
10 Unless required by applicable law or agreed to in writing, software | 10 Unless required by applicable law or agreed to in writing, software |
11 distributed under the License is distributed on an "AS IS" BASIS, | 11 distributed under the License is distributed on an "AS IS" BASIS, |
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 See the License for the specific language governing permissions and | 13 See the License for the specific language governing permissions and |
14 limitations under the License. | 14 limitations under the License. |
15 */ | 15 */ |
16 | 16 |
17 using System; | 17 using System; |
18 using System.Net.Http; | 18 using System.Net.Http; |
19 using System.Threading; | 19 using System.Threading; |
20 using System.Threading.Tasks; | 20 using System.Threading.Tasks; |
21 | |
21 using Google.Apis.Logging; | 22 using Google.Apis.Logging; |
22 using Google.Apis.Util; | 23 using Google.Apis.Util; |
23 | 24 |
24 namespace Google.Apis.Http | 25 namespace Google.Apis.Http |
25 { | 26 { |
26 /// <summary> | 27 /// <summary> |
27 /// A thread-safe back-off handler which handles an abnormal Http response o r an exception with· | 28 /// A thread-safe back-off handler which handles an abnormal HTTP response o r an exception with· |
28 /// <see cref="IBackOff"/>. | 29 /// <see cref="IBackOff"/>. |
29 /// </summary> | 30 /// </summary> |
30 public class BackOffHandler : IHttpUnsuccessfulResponseHandler, IHttpExcepti onHandler | 31 public class BackOffHandler : IHttpUnsuccessfulResponseHandler, IHttpExcepti onHandler |
31 { | 32 { |
32 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<BackOffHandler>(); | 33 private static readonly ILogger Logger = ApplicationContext.Logger.ForTy pe<BackOffHandler>(); |
33 | 34 |
34 /// <summary> An initializer class to initialize a back-off handler. </s ummary> | 35 /// <summary> An initializer class to initialize a back-off handler. </s ummary> |
35 public class Initializer | 36 public class Initializer |
36 { | 37 { |
37 /// <summary> Gets the back-off policy used by this back-off handler . </summary> | 38 /// <summary> Gets the back-off policy used by this back-off handler . </summary> |
38 public IBackOff BackOff { get; private set; } | 39 public IBackOff BackOff { get; private set; } |
39 | 40 |
40 /// <summary>· | 41 /// <summary>· |
41 /// Gets or sets the maximum time span to wait. If the back-off inst ance returns a greater time span then· | 42 /// Gets or sets the maximum time span to wait. If the back-off inst ance returns a greater time span then· |
42 /// this value, this handler returns <c>false</c> to both <see cref= "HandleException"/> and· | 43 /// this value, this handler returns <c>false</c> to both <see cref= "HandleExceptionAsync"/> and· |
43 /// <see cref="HandleResponse"/>. Default value is 5 seconds per a r etry request. | 44 /// <see cref="HandleResponseAsync"/>. Default value is 5 seconds pe r a retry request. |
44 /// </summary> | 45 /// </summary> |
45 public TimeSpan MaxTimeSpan { get; set; } | 46 public TimeSpan MaxTimeSpan { get; set; } |
46 | 47 |
47 /// <summary>· | 48 /// <summary>· |
48 /// Gets or sets a delegate function which indicates if this back-of f handler should handle an abnormal· | 49 /// Gets or sets a delegate function which indicates if this back-of f handler should handle an abnormal· |
49 /// Http response. The default is <see cref="DefaultHandleUnsuccessf ulResponse"/>.· | 50 /// HTTP response. The default is <see cref="DefaultHandleUnsuccessf ulResponseFunc"/>.· |
50 /// </summary> | 51 /// </summary> |
51 public Func<HttpResponseMessage, bool> HandleUnsuccessfulResponseFun c { get; set; } | 52 public Func<HttpResponseMessage, bool> HandleUnsuccessfulResponseFun c { get; set; } |
52 | 53 |
53 /// <summary>· | 54 /// <summary>· |
54 /// Gets or sets a delegate function which indicates if this back-of f handler should handle an exception.· | 55 /// Gets or sets a delegate function which indicates if this back-of f handler should handle an exception.· |
55 /// The default is <see cref="DefaultHandleException"/>.· | 56 /// The default is <see cref="DefaultHandleExceptionFunc"/>.· |
peleyal
2013/09/10 01:14:44
remove extra space
The default (single space)
peleyal
2013/09/10 12:32:22
Done.
| |
56 /// </summary> | 57 /// </summary> |
57 public Func<Exception, bool> HandleExceptionFunc { get; set; } | 58 public Func<Exception, bool> HandleExceptionFunc { get; set; } |
58 | 59 |
59 /// <summary> Default function which handles server errors (503). </ summary> | 60 /// <summary> Default function which handles server errors (503). </ summary> |
60 public static readonly Func<HttpResponseMessage, bool> DefaultHandle UnsuccessfulResponseFunc = | 61 public static readonly Func<HttpResponseMessage, bool> DefaultHandle UnsuccessfulResponseFunc = |
61 (r) => (int)r.StatusCode == 503; | 62 (r) => (int)r.StatusCode == 503; |
62 | 63 |
63 /// <summary>· | 64 /// <summary>· |
64 /// Default function which handles exception which aren't· | 65 /// Default function which handles exception which aren't· |
65 /// <seealso cref="System.Threading.Tasks.TaskCanceledException"/> o r· | 66 /// <seealso cref="System.Threading.Tasks.TaskCanceledException"/> o r· |
(...skipping 16 matching lines...) Expand all Loading... | |
82 /// <summary> Gets the back-off policy used by this back-off handler. </ summary> | 83 /// <summary> Gets the back-off policy used by this back-off handler. </ summary> |
83 public IBackOff BackOff { get; private set; } | 84 public IBackOff BackOff { get; private set; } |
84 | 85 |
85 /// <summary>· | 86 /// <summary>· |
86 /// Gets the maximum time span to wait. If the back-off instance returns a greater time span, the handle method | 87 /// Gets the maximum time span to wait. If the back-off instance returns a greater time span, the handle method |
87 /// returns <c>false</c>. Default value is 5 seconds per a retry request . | 88 /// returns <c>false</c>. Default value is 5 seconds per a retry request . |
88 /// </summary> | 89 /// </summary> |
89 public TimeSpan MaxTimeSpan { get; private set; } | 90 public TimeSpan MaxTimeSpan { get; private set; } |
90 | 91 |
91 /// <summary>· | 92 /// <summary>· |
92 /// Gets a delegate function which indicates if this back-off handler sh ould handle an abnormal Http response.· | 93 /// Gets a delegate function which indicates if this back-off handler sh ould handle an abnormal HTTP response.· |
93 /// The default is <see cref="DefaultHandleUnsuccessfulResponse"/>.· | 94 /// The default is <see cref="DefaultHandleUnsuccessfulResponseFunc"/>.· |
94 /// </summary> | 95 /// </summary> |
95 public Func<HttpResponseMessage, bool> HandleUnsuccessfulResponseFunc { get; private set; } | 96 public Func<HttpResponseMessage, bool> HandleUnsuccessfulResponseFunc { get; private set; } |
96 | 97 |
97 /// <summary>· | 98 /// <summary>· |
98 /// Gets a delegate function which indicates if this back-off handler sh ould handle an exception. The· | 99 /// Gets a delegate function which indicates if this back-off handler sh ould handle an exception. The· |
99 /// default is <see cref="DefaultHandleException"/>.· | 100 /// default is <see cref="DefaultHandleExceptionFunc"/>.· |
100 /// </summary> | 101 /// </summary> |
101 public Func<Exception, bool> HandleExceptionFunc { get; private set; } | 102 public Func<Exception, bool> HandleExceptionFunc { get; private set; } |
102 | 103 |
103 /// <summary> Constructs a new back-off handler with the given back-off. </summary> | 104 /// <summary> Constructs a new back-off handler with the given back-off. </summary> |
104 public BackOffHandler(IBackOff backOff) | 105 public BackOffHandler(IBackOff backOff) |
105 : this(new Initializer(backOff)) | 106 : this(new Initializer(backOff)) |
106 { | 107 { |
107 } | 108 } |
108 | 109 |
109 /// <summary> Constructs a new back-off handler with the given initializ er. </summary> | 110 /// <summary> Constructs a new back-off handler with the given initializ er. </summary> |
110 public BackOffHandler(Initializer initializer) | 111 public BackOffHandler(Initializer initializer) |
111 { | 112 { |
112 BackOff = initializer.BackOff; | 113 BackOff = initializer.BackOff; |
113 MaxTimeSpan = initializer.MaxTimeSpan; | 114 MaxTimeSpan = initializer.MaxTimeSpan; |
114 HandleExceptionFunc = initializer.HandleExceptionFunc; | 115 HandleExceptionFunc = initializer.HandleExceptionFunc; |
115 HandleUnsuccessfulResponseFunc = initializer.HandleUnsuccessfulRespo nseFunc; | 116 HandleUnsuccessfulResponseFunc = initializer.HandleUnsuccessfulRespo nseFunc; |
116 } | 117 } |
117 | 118 |
118 #region IHttpUnsuccessfulResponseHandler | 119 #region IHttpUnsuccessfulResponseHandler |
119 | 120 |
120 public virtual bool HandleResponse(HandleUnsuccessfulResponseArgs args) | 121 public virtual async Task<bool> HandleResponseAsync(HandleUnsuccessfulRe sponseArgs args) |
121 { | 122 { |
122 // if the func returns true try to handle this current failed try | 123 // if the func returns true try to handle this current failed try |
123 return HandleUnsuccessfulResponseFunc != null && HandleUnsuccessfulR esponseFunc(args.Response) && | 124 return HandleUnsuccessfulResponseFunc != null && HandleUnsuccessfulR esponseFunc(args.Response) && |
124 Handle(args.SupportsRetry, args.CurrentFailedTry, args.Cancellat ionToken); | 125 await Handle(args.SupportsRetry, args.CurrentFailedTry, args.Can cellationToken); |
125 } | 126 } |
126 | 127 |
127 #endregion | 128 #endregion |
128 | 129 |
129 #region IHttpExceptionHandler | 130 #region IHttpExceptionHandler |
130 | 131 |
131 public virtual bool HandleException(HandleExceptionArgs args) | 132 public virtual async Task<bool> HandleExceptionAsync(HandleExceptionArgs args) |
132 { | 133 { |
133 // if the func returns true try to handle this current failed try | 134 // if the func returns true try to handle this current failed try |
134 return HandleExceptionFunc != null && HandleExceptionFunc(args.Excep tion) && | 135 return HandleExceptionFunc != null && HandleExceptionFunc(args.Excep tion) && |
135 Handle(args.SupportsRetry, args.CurrentFailedTry, args.Cancellat ionToken); | 136 await Handle(args.SupportsRetry, args.CurrentFailedTry, args.Can cellationToken); |
peleyal
2013/09/10 01:14:44
rename HandleAsync
peleyal
2013/09/10 12:32:22
Done.
| |
136 } | 137 } |
137 | 138 |
138 #endregion | 139 #endregion |
139 | 140 |
140 /// <summary> | 141 /// <summary> |
141 /// Handles back-off. In case the request doesn't support retry or the b ack-off time span is greater than the | 142 /// Handles back-off. In case the request doesn't support retry or the b ack-off time span is greater than the |
142 /// maximum time span allowed for a request, the handler returns <c>fals e</c>. Otherwise, current thread will | 143 /// maximum time span allowed for a request, the handler returns <c>fals e</c>. Otherwise, current thread will |
143 /// block for x milliseconds (x is defined by the <see cref="BackOff"/> instance), and this handler returns· | 144 /// block for x milliseconds (x is defined by the <see cref="BackOff"/> instance), and this handler returns· |
144 /// <c>true</c>. | 145 /// <c>true</c>. |
145 /// </summary> | 146 /// </summary> |
146 private bool Handle(bool supportsRetry, int currentFailedTry, Cancellati onToken cancellationToken) | 147 private async Task<bool> Handle(bool supportsRetry, int currentFailedTry , CancellationToken cancellationToken) |
147 { | 148 { |
148 if (!supportsRetry || BackOff.MaxNumOfRetries < currentFailedTry) | 149 if (!supportsRetry || BackOff.MaxNumOfRetries < currentFailedTry) |
149 { | 150 { |
150 return false; | 151 return false; |
151 } | 152 } |
152 | 153 |
153 TimeSpan ts = BackOff.GetNextBackOff(currentFailedTry); | 154 TimeSpan ts = BackOff.GetNextBackOff(currentFailedTry); |
154 if (ts > MaxTimeSpan || ts < TimeSpan.Zero) | 155 if (ts > MaxTimeSpan || ts < TimeSpan.Zero) |
155 { | 156 { |
156 return false; | 157 return false; |
157 } | 158 } |
158 | 159 |
159 Wait(ts, cancellationToken); | 160 await Wait(ts, cancellationToken); |
160 Logger.Debug("Back-Off handled the error. Waited {0}ms before next r etry...", ts.TotalMilliseconds); | 161 Logger.Debug("Back-Off handled the error. Waited {0}ms before next r etry...", ts.TotalMilliseconds); |
161 return true; | 162 return true; |
162 } | 163 } |
163 | 164 |
164 /// <summary> Waits the given time span. Override this method is recomme nded for mocking purposes.</summary> | 165 /// <summary> Waits the given time span. Override this method is recomme nded for mocking purposes.</summary> |
165 /// <param name="ts">TimeSpan to wait (and block the current thread)</pa ram> | 166 /// <param name="ts">TimeSpan to wait (and block the current thread)</pa ram> |
166 /// <param name="cancellationToken">The cancellation token in case the u ser wants to cancel the operation in· | 167 /// <param name="cancellationToken">The cancellation token in case the u ser wants to cancel the operation in· |
167 /// the middle</param> | 168 /// the middle</param> |
168 protected virtual void Wait(TimeSpan ts, CancellationToken cancellationT oken) | 169 protected virtual async Task Wait(TimeSpan ts, CancellationToken cancell ationToken) |
169 { | 170 { |
170 try | 171 await TaskEx.Delay(ts, cancellationToken); |
171 { | |
172 TaskEx.Delay(ts, cancellationToken).Wait(); | |
173 } | |
174 catch (Exception) { } | |
175 } | 172 } |
176 } | 173 } |
177 } | 174 } |
OLD | NEW |