|
1 | 1 | import asyncio |
| 2 | +from concurrent.futures import CancelledError as ConcurrentCancelledError |
2 | 3 | import math |
3 | 4 | from fractions import Fraction |
4 | 5 |
|
@@ -160,6 +161,26 @@ def get_status_polling_error() -> str: |
160 | 161 | assert polling_attempts["count"] == 1 |
161 | 162 |
|
162 | 163 |
|
| 164 | +def test_poll_until_terminal_status_does_not_retry_concurrent_cancelled_errors(): |
| 165 | + attempts = {"count": 0} |
| 166 | + |
| 167 | + def get_status() -> str: |
| 168 | + attempts["count"] += 1 |
| 169 | + raise ConcurrentCancelledError() |
| 170 | + |
| 171 | + with pytest.raises(ConcurrentCancelledError): |
| 172 | + poll_until_terminal_status( |
| 173 | + operation_name="sync poll concurrent-cancelled passthrough", |
| 174 | + get_status=get_status, |
| 175 | + is_terminal_status=lambda value: value == "completed", |
| 176 | + poll_interval_seconds=0.0001, |
| 177 | + max_wait_seconds=1.0, |
| 178 | + max_status_failures=5, |
| 179 | + ) |
| 180 | + |
| 181 | + assert attempts["count"] == 1 |
| 182 | + |
| 183 | + |
163 | 184 | def test_poll_until_terminal_status_retries_rate_limit_errors(): |
164 | 185 | attempts = {"count": 0} |
165 | 186 |
|
@@ -489,6 +510,24 @@ def polling_error_operation() -> str: |
489 | 510 | assert polling_attempts["count"] == 1 |
490 | 511 |
|
491 | 512 |
|
| 513 | +def test_retry_operation_does_not_retry_concurrent_cancelled_errors(): |
| 514 | + attempts = {"count": 0} |
| 515 | + |
| 516 | + def operation() -> str: |
| 517 | + attempts["count"] += 1 |
| 518 | + raise ConcurrentCancelledError() |
| 519 | + |
| 520 | + with pytest.raises(ConcurrentCancelledError): |
| 521 | + retry_operation( |
| 522 | + operation_name="sync retry concurrent-cancelled passthrough", |
| 523 | + operation=operation, |
| 524 | + max_attempts=5, |
| 525 | + retry_delay_seconds=0.0001, |
| 526 | + ) |
| 527 | + |
| 528 | + assert attempts["count"] == 1 |
| 529 | + |
| 530 | + |
492 | 531 | def test_retry_operation_retries_server_errors(): |
493 | 532 | attempts = {"count": 0} |
494 | 533 |
|
@@ -726,6 +765,29 @@ async def get_status_polling_error() -> str: |
726 | 765 | asyncio.run(run()) |
727 | 766 |
|
728 | 767 |
|
| 768 | +def test_poll_until_terminal_status_async_does_not_retry_concurrent_cancelled_errors(): |
| 769 | + async def run() -> None: |
| 770 | + attempts = {"count": 0} |
| 771 | + |
| 772 | + async def get_status() -> str: |
| 773 | + attempts["count"] += 1 |
| 774 | + raise ConcurrentCancelledError() |
| 775 | + |
| 776 | + with pytest.raises(ConcurrentCancelledError): |
| 777 | + await poll_until_terminal_status_async( |
| 778 | + operation_name="async poll concurrent-cancelled passthrough", |
| 779 | + get_status=get_status, |
| 780 | + is_terminal_status=lambda value: value == "completed", |
| 781 | + poll_interval_seconds=0.0001, |
| 782 | + max_wait_seconds=1.0, |
| 783 | + max_status_failures=5, |
| 784 | + ) |
| 785 | + |
| 786 | + assert attempts["count"] == 1 |
| 787 | + |
| 788 | + asyncio.run(run()) |
| 789 | + |
| 790 | + |
729 | 791 | def test_poll_until_terminal_status_async_retries_server_errors(): |
730 | 792 | async def run() -> None: |
731 | 793 | attempts = {"count": 0} |
@@ -834,6 +896,27 @@ async def polling_error_operation() -> str: |
834 | 896 | asyncio.run(run()) |
835 | 897 |
|
836 | 898 |
|
| 899 | +def test_retry_operation_async_does_not_retry_concurrent_cancelled_errors(): |
| 900 | + async def run() -> None: |
| 901 | + attempts = {"count": 0} |
| 902 | + |
| 903 | + async def operation() -> str: |
| 904 | + attempts["count"] += 1 |
| 905 | + raise ConcurrentCancelledError() |
| 906 | + |
| 907 | + with pytest.raises(ConcurrentCancelledError): |
| 908 | + await retry_operation_async( |
| 909 | + operation_name="async retry concurrent-cancelled passthrough", |
| 910 | + operation=operation, |
| 911 | + max_attempts=5, |
| 912 | + retry_delay_seconds=0.0001, |
| 913 | + ) |
| 914 | + |
| 915 | + assert attempts["count"] == 1 |
| 916 | + |
| 917 | + asyncio.run(run()) |
| 918 | + |
| 919 | + |
837 | 920 | def test_retry_operation_async_retries_server_errors(): |
838 | 921 | async def run() -> None: |
839 | 922 | attempts = {"count": 0} |
@@ -1530,6 +1613,28 @@ def get_next_page(page: int) -> dict: |
1530 | 1613 | assert attempts["count"] == 1 |
1531 | 1614 |
|
1532 | 1615 |
|
| 1616 | +def test_collect_paginated_results_does_not_retry_concurrent_cancelled_errors(): |
| 1617 | + attempts = {"count": 0} |
| 1618 | + |
| 1619 | + def get_next_page(page: int) -> dict: |
| 1620 | + attempts["count"] += 1 |
| 1621 | + raise ConcurrentCancelledError() |
| 1622 | + |
| 1623 | + with pytest.raises(ConcurrentCancelledError): |
| 1624 | + collect_paginated_results( |
| 1625 | + operation_name="sync paginated concurrent-cancelled passthrough", |
| 1626 | + get_next_page=get_next_page, |
| 1627 | + get_current_page_batch=lambda response: response["current"], |
| 1628 | + get_total_page_batches=lambda response: response["total"], |
| 1629 | + on_page_success=lambda response: None, |
| 1630 | + max_wait_seconds=1.0, |
| 1631 | + max_attempts=5, |
| 1632 | + retry_delay_seconds=0.0001, |
| 1633 | + ) |
| 1634 | + |
| 1635 | + assert attempts["count"] == 1 |
| 1636 | + |
| 1637 | + |
1533 | 1638 | def test_collect_paginated_results_retries_server_errors(): |
1534 | 1639 | attempts = {"count": 0} |
1535 | 1640 | collected = [] |
@@ -1821,6 +1926,31 @@ async def get_next_page(page: int) -> dict: |
1821 | 1926 | asyncio.run(run()) |
1822 | 1927 |
|
1823 | 1928 |
|
| 1929 | +def test_collect_paginated_results_async_does_not_retry_concurrent_cancelled_errors(): |
| 1930 | + async def run() -> None: |
| 1931 | + attempts = {"count": 0} |
| 1932 | + |
| 1933 | + async def get_next_page(page: int) -> dict: |
| 1934 | + attempts["count"] += 1 |
| 1935 | + raise ConcurrentCancelledError() |
| 1936 | + |
| 1937 | + with pytest.raises(ConcurrentCancelledError): |
| 1938 | + await collect_paginated_results_async( |
| 1939 | + operation_name="async paginated concurrent-cancelled passthrough", |
| 1940 | + get_next_page=get_next_page, |
| 1941 | + get_current_page_batch=lambda response: response["current"], |
| 1942 | + get_total_page_batches=lambda response: response["total"], |
| 1943 | + on_page_success=lambda response: None, |
| 1944 | + max_wait_seconds=1.0, |
| 1945 | + max_attempts=5, |
| 1946 | + retry_delay_seconds=0.0001, |
| 1947 | + ) |
| 1948 | + |
| 1949 | + assert attempts["count"] == 1 |
| 1950 | + |
| 1951 | + asyncio.run(run()) |
| 1952 | + |
| 1953 | + |
1824 | 1954 | def test_collect_paginated_results_async_retries_server_errors(): |
1825 | 1955 | async def run() -> None: |
1826 | 1956 | attempts = {"count": 0} |
|
0 commit comments