blob: d341dc3f65417928a03e596d084202353ec434aa [file] [log] [blame]
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Helper functions for common boilerplate tasks.
Top-level functions stored in __init__.py can be imported and used directly
(without needing a `RecipeApi` object) using `RECIPE_MODULES` imports. E.g.:
```
from RECIPE_MODULES.fuchsia.utils import memoize
@memoize
def expensive_computation(inputs):
return do_work(inputs)
def RunSteps(api, ...):
expensive_computation(...)
```
"""
from recipe_engine import recipe_api
class UtilsApi(recipe_api.RecipeApi):
def retry(self, func, max_attempts, sleep=5.0, backoff_factor=1.5):
"""Retry the given function with exponential backoff.
Args:
func (callable): A function that performs the action that should
be retried on failure. If it raises a `StepFailure` it will
be retried. Any other exception will end the retry loop and
bubble up.
max_attempts (int): How many times to try before giving up.
sleep (int or float): The time to sleep after the first attempt.
backoff_factor (int or float): The factor by which the sleep time
will be multiplied after each attempt.
"""
for attempt in range(max_attempts):
try:
return func()
except self.m.step.StepFailure:
if attempt == max_attempts - 1:
raise
self.m.time.sleep(sleep)
sleep *= backoff_factor