@@ -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