From 4cc8e2b04391afc276eb3483f102407808e541ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sondre=20Lilleb=C3=B8=20Gundersen?= Date: Sun, 3 Apr 2022 10:56:06 +0200 Subject: [PATCH 1/2] chore: Update pre-commit config --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6136171..0ec1d87 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/ambv/black - rev: 21.12b0 + rev: 22.3.0 hooks: - id: black args: ['--quiet'] @@ -24,7 +24,7 @@ repos: - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade - rev: v2.31.0 + rev: v2.31.1 hooks: - id: pyupgrade args: ['--py3-plus', '--py36-plus', '--py37-plus', '--keep-runtime-typing'] @@ -40,7 +40,7 @@ repos: 'flake8-type-checking', ] - repo: https://github.com/pre-commit/mirrors-mypy - rev: 'v0.931' + rev: 'v0.942' hooks: - id: mypy additional_dependencies: [types-dateparser] From 772c2ca7ce85329168a9ebae2e4ec94e767a01f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sondre=20Lilleb=C3=B8=20Gundersen?= Date: Sun, 3 Apr 2022 10:59:38 +0200 Subject: [PATCH 2/2] fix: Improve error handling for timeouts Adds explicit handling of timeout errors, which is the only error we expect to see. Other exception types will also be returned and propagated so we can add explicit handling for them if needed. --- main.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/main.py b/main.py index ae7062a..36ae39d 100644 --- a/main.py +++ b/main.py @@ -10,7 +10,7 @@ from urllib.parse import quote_from_bytes from dateparser import parse -from httpx import AsyncClient +from httpx import AsyncClient, TimeoutException from pydantic import BaseModel, conint, validator if TYPE_CHECKING: @@ -128,9 +128,11 @@ async def delete_org_package_versions( await semaphore.acquire() try: response = await http_client.delete(url) + post_deletion_output(response=response, image_name=image_name, version_id=version_id) + except TimeoutException as e: + print(f'Request to delete {image_name.value} timed out with error `{e}`') finally: semaphore.release() - post_deletion_output(response=response, image_name=image_name, version_id=version_id) async def delete_package_versions( @@ -148,9 +150,11 @@ async def delete_package_versions( await semaphore.acquire() try: response = await http_client.delete(url) + post_deletion_output(response=response, image_name=image_name, version_id=version_id) + except TimeoutException as e: + print(f'Request to delete {image_name.value} timed out with error `{e}`') finally: semaphore.release() - post_deletion_output(response=response, image_name=image_name, version_id=version_id) class GithubAPI: @@ -221,10 +225,7 @@ def parse_image_names(cls, v: str) -> list[ImageName]: @validator('skip_tags', 'filter_tags', pre=True) def parse_comma_separate_string_as_list(cls, v: str) -> list[str]: - if not v: - return [] - else: - return [i.strip() for i in v.split(',')] + return [] if not v else [i.strip() for i in v.split(',')] @validator('cut_off', pre=True) def parse_human_readable_datetime(cls, v: str) -> datetime: @@ -330,7 +331,18 @@ async def get_and_delete_old_versions(image_name: ImageName, inputs: Inputs, htt if not tasks: print(f'No more versions to delete for {image_name.value}') - await asyncio.gather(*tasks) + results = await asyncio.gather(*tasks, return_exceptions=True) + + for item in results: + if isinstance(item, Exception): + try: + raise item + except Exception as e: + # Unhandled errors *shouldn't* occur + print( + f'Unhandled exception raised at runtime: `{e}`. ' + f'Please report this at https://github.com/snok/container-retention-policy/issues/new' + ) async def main(