Skip to content

Commit 9916b87

Browse files
committed
retry method and self.logger.exception
Change-Id: I3db4b9dc4eaf8e16ce267c9a3e3929fb2ad2317a
1 parent c55842a commit 9916b87

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

python/src/etos_api/library/docker.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -235,24 +235,31 @@ def repository(self, repo: str) -> tuple[str, str]:
235235
async def digest(self, name: str) -> Optional[str]:
236236
"""Get a sha256 digest from an image in an image repository.
237237
238-
Retries on transient connection errors (e.g. DNS hiccups) up to
239-
MAX_RETRIES times with exponential backoff between attempts.
240-
The delay follows the same formula as urllib3 Retry used in
241-
etos-library: ``BACKOFF_FACTOR * 2 ** (attempt - 1)``.
242-
243238
:param name: The name of the container image.
244239
:return: The sha256 digest of the container image.
245240
"""
246241
self.logger.info("Figure out digest for %r", name)
247242
base, tag = self.tag(name)
248243
registry, repo = self.repository(base)
249244
manifest_url = f"https://{registry}/v2/{repo}/manifests/{tag}"
245+
return await self._retry(self._get_digest, name, manifest_url)
246+
247+
async def _retry(self, func, name: str, *args) -> Optional[str]:
248+
"""Call *func* with retries and exponential backoff.
250249
250+
Retries on transient connection errors (e.g. DNS hiccups) up to
251+
MAX_RETRIES times. The delay follows the same formula as urllib3
252+
Retry used in etos-library: ``BACKOFF_FACTOR * 2 ** (attempt - 1)``.
253+
254+
:param func: Async callable to invoke on each attempt.
255+
:param name: Image name (used only for logging).
256+
:param args: Positional arguments forwarded to *func*.
257+
:return: The value returned by *func*, or None after exhausting retries.
258+
"""
251259
last_exception = None
252260
for attempt in range(1, MAX_RETRIES + 1):
253261
try:
254-
digest = await self._get_digest(manifest_url)
255-
return digest
262+
return await func(*args)
256263
except _RETRYABLE_EXCEPTIONS as exception:
257264
last_exception = exception
258265
self.logger.warning(
@@ -267,11 +274,11 @@ async def digest(self, name: str) -> Optional[str]:
267274
self.logger.info("Retrying in %s seconds...", delay)
268275
await asyncio.sleep(delay)
269276

270-
self.logger.error(
271-
"All %d attempts to check container image %r failed: %s",
277+
self.logger.exception(
278+
"All %d attempts to check container image %r failed",
272279
MAX_RETRIES,
273280
name,
274-
last_exception,
281+
exc_info=last_exception,
275282
)
276283
return None
277284

0 commit comments

Comments
 (0)