|
25 | 25 | from urllib.error import HTTPError, URLError |
26 | 26 | from urllib.parse import urlencode, urlparse |
27 | 27 | from urllib.request import HTTPRedirectHandler, Request, build_opener, urlopen |
| 28 | +from github_backup import max_retries |
28 | 29 |
|
29 | 30 | try: |
30 | 31 | from . import __version__ |
@@ -75,7 +76,7 @@ def __init__(self, message, dmca_url=None): |
75 | 76 | ) |
76 | 77 |
|
77 | 78 | # Retry configuration |
78 | | -MAX_RETRIES = 5 |
| 79 | +MAX_RETRIES = max_retries.MAX_RETRIES |
79 | 80 |
|
80 | 81 |
|
81 | 82 | def logging_subprocess( |
@@ -468,6 +469,13 @@ def parse_args(args=None): |
468 | 469 | parser.add_argument( |
469 | 470 | "--exclude", dest="exclude", help="names of repositories to exclude", nargs="*" |
470 | 471 | ) |
| 472 | + parser.add_argument( |
| 473 | + "--retries", |
| 474 | + dest="max_retries", |
| 475 | + type=int, |
| 476 | + default=5, |
| 477 | + help="maximum number of retries for API calls (default: 5)", |
| 478 | + ) |
471 | 479 | return parser.parse_args(args) |
472 | 480 |
|
473 | 481 |
|
@@ -737,29 +745,32 @@ def is_retryable_status(status_code, headers): |
737 | 745 | except HTTPError as exc: |
738 | 746 | # HTTPError can be used as a response-like object |
739 | 747 | if not is_retryable_status(exc.code, exc.headers): |
| 748 | + logger.error(f"API Error: {exc.code} {exc.reason} for {request.full_url}") |
740 | 749 | raise # Non-retryable error |
741 | 750 |
|
742 | 751 | if attempt >= MAX_RETRIES - 1: |
743 | 752 | logger.error(f"HTTP {exc.code} failed after {MAX_RETRIES} attempts") |
| 753 | + logger.error(f"HTTP {exc.code} failed after {MAX_RETRIES} attempts for {request.full_url}") |
744 | 754 | raise |
745 | 755 |
|
746 | 756 | delay = calculate_retry_delay(attempt, exc.headers) |
747 | 757 | logger.warning( |
748 | | - f"HTTP {exc.code}, retrying in {delay:.1f}s " |
749 | | - f"(attempt {attempt + 1}/{MAX_RETRIES})" |
| 758 | + f"HTTP {exc.code} ({exc.reason}), retrying in {delay:.1f}s " |
| 759 | + f"(attempt {attempt + 1}/{MAX_RETRIES}) for {request.full_url}" |
| 760 | + |
750 | 761 | ) |
751 | 762 | if auth is None and exc.code in (403, 429): |
752 | 763 | logger.info("Hint: Authenticate to raise your GitHub rate limit") |
753 | 764 | time.sleep(delay) |
754 | 765 |
|
755 | 766 | except (URLError, socket.error) as e: |
756 | 767 | if attempt >= MAX_RETRIES - 1: |
757 | | - logger.error(f"Connection error failed after {MAX_RETRIES} attempts: {e}") |
| 768 | + logger.error(f"Connection error failed after {MAX_RETRIES} attempts: {e} for {request.full_url}") |
758 | 769 | raise |
759 | 770 | delay = calculate_retry_delay(attempt, {}) |
760 | 771 | logger.warning( |
761 | 772 | f"Connection error: {e}, retrying in {delay:.1f}s " |
762 | | - f"(attempt {attempt + 1}/{MAX_RETRIES})" |
| 773 | + f"(attempt {attempt + 1}/{MAX_RETRIES}) for {request.full_url}" |
763 | 774 | ) |
764 | 775 | time.sleep(delay) |
765 | 776 |
|
|
0 commit comments