From 6873229bbfca95ec6a05dff88e313e2a5598446f Mon Sep 17 00:00:00 2001 From: Itay Etelis Date: Wed, 18 Sep 2024 13:39:04 +0300 Subject: [PATCH 1/5] Support lists in `retry_on` for RetryPolicy Previously, `retry_on` in `RetryPolicy` accepted only exception classes, tuples of exception classes, or callables. Update the `retry_on` type annotation to include `List[Type[Exception]]` Changes: - Updated `retry_on` in `RetryPolicy` to accept `List[Type[Exception]]`. --- libs/langgraph/langgraph/pregel/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/types.py b/libs/langgraph/langgraph/pregel/types.py index 589ed43ab..ca548ba64 100644 --- a/libs/langgraph/langgraph/pregel/types.py +++ b/libs/langgraph/langgraph/pregel/types.py @@ -1,5 +1,5 @@ from collections import deque -from typing import Any, Callable, Literal, NamedTuple, Optional, Type, Union +from typing import Any, Callable, Literal, NamedTuple, Optional, Type, Union, List from langchain_core.runnables import Runnable, RunnableConfig @@ -52,7 +52,7 @@ class RetryPolicy(NamedTuple): jitter: bool = True """Whether to add random jitter to the interval between retries.""" retry_on: Union[ - Type[Exception], tuple[Type[Exception], ...], Callable[[Exception], bool] + Type[Exception], List[Type[Exception]], tuple[Type[Exception], ...], Callable[[Exception], bool] ] = default_retry_on """List of exception classes that should trigger a retry, or a callable that returns True for exceptions that should trigger a retry.""" From adf5cb0ff1666405e9fc51d144f64c1d9d979f37 Mon Sep 17 00:00:00 2001 From: Itay Etelis Date: Wed, 18 Sep 2024 13:41:22 +0300 Subject: [PATCH 2/5] Fix `retry_on` handling in `run_with_retry` - Correctly distinguish between exception classes, lists/tuples of exception classes, and callables. - Add support for lists in `retry_on`, alongside tuples. - Prevent exception classes from being incorrectly treated as callables. - Raise a `TypeError` if `retry_on` is of an unsupported type. --- libs/langgraph/langgraph/pregel/retry.py | 28 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/retry.py b/libs/langgraph/langgraph/pregel/retry.py index cdf7b33d3..34374962a 100644 --- a/libs/langgraph/langgraph/pregel/retry.py +++ b/libs/langgraph/langgraph/pregel/retry.py @@ -38,11 +38,19 @@ def run_with_retry( # increment attempts attempts += 1 # check if we should retry - if callable(retry_policy.retry_on): + if isinstance(retry_policy.retry_on, (list, tuple)): + if not isinstance(exc, tuple(retry_policy.retry_on)): + raise + elif isinstance(retry_policy.retry_on, type) and issubclass(retry_policy.retry_on, Exception): + if not isinstance(exc, retry_policy.retry_on): + raise + elif callable(retry_policy.retry_on): if not retry_policy.retry_on(exc): raise - elif not isinstance(exc, retry_policy.retry_on): - raise + else: + raise TypeError( + "retry_on must be an Exception class, a list or tuple of Exception classes, or a callable" + ) # check if we should give up if attempts >= retry_policy.max_attempts: raise @@ -94,11 +102,19 @@ async def arun_with_retry( # increment attempts attempts += 1 # check if we should retry - if callable(retry_policy.retry_on): + if isinstance(retry_policy.retry_on, (list, tuple)): + if not isinstance(exc, tuple(retry_policy.retry_on)): + raise + elif isinstance(retry_policy.retry_on, type) and issubclass(retry_policy.retry_on, Exception): + if not isinstance(exc, retry_policy.retry_on): + raise + elif callable(retry_policy.retry_on): if not retry_policy.retry_on(exc): raise - elif not isinstance(exc, retry_policy.retry_on): - raise + else: + raise TypeError( + "retry_on must be an Exception class, a list or tuple of Exception classes, or a callable" + ) # check if we should give up if attempts >= retry_policy.max_attempts: raise From fd0b52f4fff114930d1b3f677c6aa3cb2b0858d8 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 18 Sep 2024 10:23:52 -0700 Subject: [PATCH 3/5] Update retry.py --- libs/langgraph/langgraph/pregel/retry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/retry.py b/libs/langgraph/langgraph/pregel/retry.py index 34374962a..27ff67169 100644 --- a/libs/langgraph/langgraph/pregel/retry.py +++ b/libs/langgraph/langgraph/pregel/retry.py @@ -2,7 +2,7 @@ import asyncio import logging import random import time -from typing import Optional +from typing import Optional, Sequence from langgraph.constants import CONFIG_KEY_RESUMING from langgraph.errors import GraphInterrupt @@ -38,7 +38,7 @@ def run_with_retry( # increment attempts attempts += 1 # check if we should retry - if isinstance(retry_policy.retry_on, (list, tuple)): + if isinstance(retry_policy.retry_on, Sequence): if not isinstance(exc, tuple(retry_policy.retry_on)): raise elif isinstance(retry_policy.retry_on, type) and issubclass(retry_policy.retry_on, Exception): @@ -102,7 +102,7 @@ async def arun_with_retry( # increment attempts attempts += 1 # check if we should retry - if isinstance(retry_policy.retry_on, (list, tuple)): + if isinstance(retry_policy.retry_on, Sequence): if not isinstance(exc, tuple(retry_policy.retry_on)): raise elif isinstance(retry_policy.retry_on, type) and issubclass(retry_policy.retry_on, Exception): From 0bfeb7f4e15610d481148f993e4f76521e4f0ae5 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 18 Sep 2024 10:24:28 -0700 Subject: [PATCH 4/5] Update types.py --- libs/langgraph/langgraph/pregel/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/types.py b/libs/langgraph/langgraph/pregel/types.py index ca548ba64..f8682d50b 100644 --- a/libs/langgraph/langgraph/pregel/types.py +++ b/libs/langgraph/langgraph/pregel/types.py @@ -1,5 +1,5 @@ from collections import deque -from typing import Any, Callable, Literal, NamedTuple, Optional, Type, Union, List +from typing import Any, Callable, Literal, NamedTuple, Optional, Sequence, Type, Union from langchain_core.runnables import Runnable, RunnableConfig @@ -52,7 +52,7 @@ class RetryPolicy(NamedTuple): jitter: bool = True """Whether to add random jitter to the interval between retries.""" retry_on: Union[ - Type[Exception], List[Type[Exception]], tuple[Type[Exception], ...], Callable[[Exception], bool] + Type[Exception], Sequence[Type[Exception]], Callable[[Exception], bool] ] = default_retry_on """List of exception classes that should trigger a retry, or a callable that returns True for exceptions that should trigger a retry.""" From e40aabb1c1c812b878f16af2e98cefb5e4d29d28 Mon Sep 17 00:00:00 2001 From: Nuno Campos Date: Wed, 18 Sep 2024 10:36:40 -0700 Subject: [PATCH 5/5] Update retry.py --- libs/langgraph/langgraph/pregel/retry.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/langgraph/langgraph/pregel/retry.py b/libs/langgraph/langgraph/pregel/retry.py index 27ff67169..553b25468 100644 --- a/libs/langgraph/langgraph/pregel/retry.py +++ b/libs/langgraph/langgraph/pregel/retry.py @@ -41,7 +41,9 @@ def run_with_retry( if isinstance(retry_policy.retry_on, Sequence): if not isinstance(exc, tuple(retry_policy.retry_on)): raise - elif isinstance(retry_policy.retry_on, type) and issubclass(retry_policy.retry_on, Exception): + elif isinstance(retry_policy.retry_on, type) and issubclass( + retry_policy.retry_on, Exception + ): if not isinstance(exc, retry_policy.retry_on): raise elif callable(retry_policy.retry_on): @@ -105,7 +107,9 @@ async def arun_with_retry( if isinstance(retry_policy.retry_on, Sequence): if not isinstance(exc, tuple(retry_policy.retry_on)): raise - elif isinstance(retry_policy.retry_on, type) and issubclass(retry_policy.retry_on, Exception): + elif isinstance(retry_policy.retry_on, type) and issubclass( + retry_policy.retry_on, Exception + ): if not isinstance(exc, retry_policy.retry_on): raise elif callable(retry_policy.retry_on):