Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: recipe_engine/util.py

Issue 2362993002: More strategic retries in fetch. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2013 The LUCI Authors. All rights reserved. 1 # Copyright 2013 The LUCI Authors. All rights reserved.
2 # Use of this source code is governed under the Apache License, Version 2.0 2 # Use of this source code is governed under the Apache License, Version 2.0
3 # that can be found in the LICENSE file. 3 # that can be found in the LICENSE file.
4 4
5 import contextlib 5 import contextlib
6 import datetime
6 import functools 7 import functools
8 import logging
7 import os 9 import os
8 import sys 10 import sys
9 import traceback 11 import traceback
12 import time
10 import urllib 13 import urllib
11 14
12 from cStringIO import StringIO 15 from cStringIO import StringIO
13 16
14 class RecipeAbort(Exception): 17 class RecipeAbort(Exception):
15 pass 18 pass
16 19
17 20
18 class ModuleInjectionError(AttributeError): 21 class ModuleInjectionError(AttributeError):
19 pass 22 pass
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 self.lines[-1].write(s) 186 self.lines[-1].write(s)
184 break 187 break
185 self.lines[-1].write(s[:i]) 188 self.lines[-1].write(s[:i])
186 self.lines[-1] = self.lines[-1].getvalue() 189 self.lines[-1] = self.lines[-1].getvalue()
187 self.lines.append(StringIO()) 190 self.lines.append(StringIO())
188 s = s[i+1:] 191 s = s[i+1:]
189 192
190 def close(self): 193 def close(self):
191 if not isinstance(self.lines[-1], basestring): 194 if not isinstance(self.lines[-1], basestring):
192 self.lines[-1] = self.lines[-1].getvalue() 195 self.lines[-1] = self.lines[-1].getvalue()
196
197
198 class exponential_retry(object):
199 """Decorator which retries the function if an exception is encountered."""
200
201 def __init__(self, retries=None, delay=None, condition=None):
202 """Creates a new exponential retry decorator.
203
204 Args:
205 retries (int): Maximum number of retries before giving up.
206 delay (datetime.timedelta): Amount of time to wait before retrying. This
207 will double every retry attempt (exponential).
208 condition (func): If not None, a function that will be passed the
209 exception as its one argument. Retries will only happen if this
210 function returns True. If None, retries will always happen.
211 """
212 self.retries = retries or 5
213 self.delay = delay or datetime.timedelta(seconds=1)
214 self.condition = condition or (lambda e: True)
215
216 def __call__(self, f):
217 @functools.wraps(f)
218 def wrapper(*args, **kwargs):
219 retry_delay = self.delay
220 for i in xrange(self.retries):
221 try:
222 return f(*args, **kwargs)
223 except Exception as e:
224 if (i+1) >= self.retries or not self.condition(e):
225 raise
226 logging.exception('Exception encountered, retrying in %s',
227 retry_delay)
228 time.sleep(retry_delay.total_seconds())
229 retry_delay *= 2
230 return wrapper
OLDNEW
« recipe_engine/fetch.py ('K') | « recipe_engine/unittests/fetch_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698