Skip to content

Commit 393fdb3

Browse files
Frans FürstTimotheusBachinger
authored andcommitted
jenkins utils: add replace retry decorator with async_retry decorator
Change-Id: I7ec8e2bdb1e11da1f01806c836ea99f5cfd36597
1 parent 860a4b4 commit 393fdb3

File tree

4 files changed

+874
-753
lines changed

4 files changed

+874
-753
lines changed

.snippets/CMK-22793-async-retry.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
## Fix retry during download
2+
<!--
3+
type: bugfix
4+
scope: all
5+
affected: all
6+
-->
7+
8+
the previously used retry decorator was not async compatible.
9+

cmk_dev/jenkins_utils/__init__.py

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@
1313
import logging
1414
import os
1515
from argparse import ArgumentParser
16-
from collections.abc import AsyncIterable, Iterable, Mapping, MutableMapping, Sequence, Set
16+
from collections.abc import (
17+
AsyncIterable,
18+
Iterable,
19+
Mapping,
20+
MutableMapping,
21+
Sequence,
22+
Set,
23+
)
1724
from configparser import ConfigParser
1825
from contextlib import suppress
1926
from datetime import datetime
@@ -23,8 +30,7 @@
2330
import jenkins
2431
from jenkins import Jenkins
2532
from pydantic import BaseModel, Json, model_validator
26-
from retry import retry
27-
from trickkiste.misc import asyncify, compact_dict, date_str, dur_str, split_params
33+
from trickkiste.misc import async_retry, asyncify, compact_dict, date_str, dur_str, split_params
2834

2935
from cmk_dev.utils import Fatal
3036

@@ -40,6 +46,8 @@
4046

4147
JobResult = Literal["FAILURE", "SUCCESS", "ABORTED", "UNSTABLE", "PROGRESS", "RUNNING"]
4248

49+
MAX_ATTEMPTS = 3
50+
4351

4452
def log() -> logging.Logger:
4553
"""Convenience function retrieves 'our' logger"""
@@ -74,6 +82,7 @@ def correct_base(cls, obj: Json[dict[str, Any]]) -> Json[dict[str, Any]]:
7482

7583
class Config:
7684
"""Mandatory docstring"""
85+
7786
# Activate this in ordert to enforce a stricter pydantic validation which
7887
# raises on unknown attributes. Activate it in development only since it will
7988
# break runtimes when Jenkins API changes again.
@@ -793,15 +802,13 @@ async def failing_transition_numbers(
793802
last_build.number if last_build else None,
794803
)
795804

796-
@asyncify
797-
@retry(tries=3, delay=1, logger=log())
798-
def raw_jobs(self) -> GenMap:
805+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
806+
async def raw_jobs(self) -> GenMap:
799807
"""Async wrapper for get_jobs()"""
800808
return self.client.get_jobs()
801809

802-
@asyncify
803-
@retry(tries=3, delay=1, logger=log())
804-
def raw_job_info(self, job_full_name: str) -> GenMap:
810+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
811+
async def raw_job_info(self, job_full_name: str) -> GenMap:
805812
"""Fetches Jenkins job info for @job_full_name"""
806813
log().debug("fetch job info for %s", job_full_name)
807814
return self.client.get_job_info(job_full_name)
@@ -814,14 +821,12 @@ async def job_info(self, job_full_name: str | Sequence[str]) -> Job:
814821
)
815822
)
816823

817-
@asyncify
818-
@retry(tries=3, delay=1, logger=log())
819-
def raw_build_info(self, job_full_name: str, build_number: int) -> GenMap:
824+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
825+
async def raw_build_info(self, job_full_name: str, build_number: int) -> GenMap:
820826
"""Returns raw Jenkins job info for @job_full_name"""
821827
log().debug("fetch build log for %s:%d", job_full_name, build_number)
822828
return self.client.get_build_info(job_full_name, build_number)
823829

824-
@retry(tries=3, delay=1, logger=log())
825830
async def build_info(self, job_full_name: str | Sequence[str], build_number: int) -> Build:
826831
"""Fetches Jenkins build info for @job_full_name#@build_number"""
827832
return Build.model_validate(
@@ -831,19 +836,18 @@ async def build_info(self, job_full_name: str | Sequence[str], build_number: int
831836
)
832837
)
833838

834-
@asyncify
835-
@retry(tries=3, delay=1, logger=log())
836-
def queue_info(self) -> Sequence[QueueItem]:
839+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
840+
async def queue_info(self) -> Sequence[QueueItem]:
837841
"""Async wrapper for get_queue_info()"""
838842
return list(map(QueueItem.model_validate, self.client.get_queue_info()))
839843

840-
@asyncify
841-
def queue_item(self, number: int, depth: int = 1) -> QueueItem:
844+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
845+
async def queue_item(self, number: int, depth: int = 1) -> QueueItem:
842846
"""Async wrapper for get_queue_item()"""
843847
return QueueItem.model_validate(self.client.get_queue_item(number, depth=depth))
844848

845-
@asyncify
846-
def build_stages(self, job: str | Sequence[str] | Job, build_number: int) -> BuildStages:
849+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
850+
async def build_stages(self, job: str | Sequence[str] | Job, build_number: int) -> BuildStages:
847851
"""Returns validated build stages info"""
848852
return BuildStages.model_validate(
849853
self.client.get_build_stages(
@@ -858,8 +862,8 @@ def build_stages(self, job: str | Sequence[str] | Job, build_number: int) -> Bui
858862
)
859863
)
860864

861-
@asyncify
862-
def fetch_jvm_ressource_stats(self) -> Mapping[str, int]:
865+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
866+
async def fetch_jvm_ressource_stats(self) -> Mapping[str, int]:
863867
"""Returns information about available and used memory in JVM"""
864868
log().debug("fetch JVM ressource stats via script")
865869
return {
@@ -881,18 +885,18 @@ def fetch_jvm_ressource_stats(self) -> Mapping[str, int]:
881885
).items()
882886
}
883887

884-
@asyncify
885-
def running_builds(self) -> Sequence[SimpleBuild]:
888+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
889+
async def running_builds(self) -> Sequence[SimpleBuild]:
886890
"""Async validating wrapper for Jenkins.get_running_builds()"""
887891
return list(map(SimpleBuild.model_validate, self.client.get_running_builds()))
888892

889-
@asyncify
890-
def build_nodes(self) -> Sequence[BuildNode]:
893+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
894+
async def build_nodes(self) -> Sequence[BuildNode]:
891895
"""Async validating wrapper for Jenkins.get_nodes()"""
892896
return list(map(BuildNode.model_validate, self.client.get_nodes()))
893897

894-
@asyncify
895-
def node_info(self, name: str) -> BuildNode:
898+
@async_retry(tries=MAX_ATTEMPTS, delay=1, logger=log())
899+
async def node_info(self, name: str) -> BuildNode:
896900
"""Async validating wrapper for Jenkins.get_node_info()"""
897901
return BuildNode.model_validate(self.client.get_node_info(name))
898902

0 commit comments

Comments
 (0)