|
88 | 88 | log: logging.Logger = logging.getLogger(__name__) |
89 | 89 | log.addFilter(SensitiveHeadersFilter()) |
90 | 90 |
|
| 91 | + |
| 92 | +def _should_not_retry(exc: Exception) -> bool: |
| 93 | + """ |
| 94 | + Check if an exception should propagate immediately without retry. |
| 95 | +
|
| 96 | + This includes task cancellation signals from async frameworks |
| 97 | + and task executors like Celery that should not be caught and retried. |
| 98 | +
|
| 99 | + Args: |
| 100 | + exc: The exception to check |
| 101 | +
|
| 102 | + Returns: |
| 103 | + True if the exception should propagate without retry, False otherwise |
| 104 | + """ |
| 105 | + exc_class = exc.__class__ |
| 106 | + exc_module = exc_class.__module__ |
| 107 | + exc_name = exc_class.__name__ |
| 108 | + |
| 109 | + # Celery task termination (don't import celery - check by name) |
| 110 | + # Examples: SoftTimeLimitExceeded, TimeLimitExceeded, Terminated |
| 111 | + if exc_module.startswith("celery") and ("Limit" in exc_name or "Terminated" in exc_name): |
| 112 | + return True |
| 113 | + |
| 114 | + # asyncio cancellation |
| 115 | + if exc_module == "asyncio" and exc_name == "CancelledError": |
| 116 | + return True |
| 117 | + |
| 118 | + return False |
| 119 | + |
| 120 | + |
91 | 121 | # TODO: make base page type vars covariant |
92 | 122 | SyncPageT = TypeVar("SyncPageT", bound="BaseSyncPage[Any]") |
93 | 123 | AsyncPageT = TypeVar("AsyncPageT", bound="BaseAsyncPage[Any]") |
@@ -1001,6 +1031,10 @@ def request( |
1001 | 1031 | except Exception as err: |
1002 | 1032 | log.debug("Encountered Exception", exc_info=True) |
1003 | 1033 |
|
| 1034 | + # Check if this is a termination signal that should not be retried |
| 1035 | + if _should_not_retry(err): |
| 1036 | + raise |
| 1037 | + |
1004 | 1038 | if remaining_retries > 0: |
1005 | 1039 | self._sleep_for_retry( |
1006 | 1040 | retries_taken=retries_taken, |
@@ -1548,6 +1582,10 @@ async def request( |
1548 | 1582 | except Exception as err: |
1549 | 1583 | log.debug("Encountered Exception", exc_info=True) |
1550 | 1584 |
|
| 1585 | + # Check if this is a termination signal that should not be retried |
| 1586 | + if _should_not_retry(err): |
| 1587 | + raise |
| 1588 | + |
1551 | 1589 | if remaining_retries > 0: |
1552 | 1590 | await self._sleep_for_retry( |
1553 | 1591 | retries_taken=retries_taken, |
|
0 commit comments