
    k
i                     
   d Z ddlZddlZddlmZ ddlmZmZmZm	Z	m
Z
mZmZ ddlmZ ddlmZmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ  ej        e           Z! ede          Z" G d dee	e"                   Z#dS )zAsync Redis middleware base class.

This module provides the async base class for Redis middleware that is
compatible with LangChain's AgentMiddleware protocol.
    N)abstractmethod)Any	AwaitableCallableGenericOptionalTypeVarUnion)AgentMiddleware)ModelCallResultModelRequestModelResponse)ToolMessage)ToolCallRequest)Command)Redis   )MiddlewareConfigAsyncRedisClientType)boundc            	       Z   e Zd ZU dZeed<   eed<   eed<   eed<   eed<   ej	        ed<   ded	d
fdZ
edd            ZddZddZddZdee         dee         dee         d	d
fdZdedeegee         f         d	efdZdedeegeeeef                  f         d	eeef         fdZd
S )AsyncRedisMiddlewarea  Abstract base class for async Redis middleware.

    This class provides common functionality for all async Redis-based middleware:
    - Async Redis client lifecycle management
    - Lazy initialization with double-checked locking
    - Graceful degradation on Redis errors
    - Async context manager support
    - Default pass-through implementations for model/tool wrapping

    Subclasses must implement:
    - _setup_async(): Called once during initialization to set up resources

    Example:
        ```python
        class MyAsyncMiddleware(AsyncRedisMiddleware):
            async def _setup_async(self) -> None:
                # Initialize resources
                self._cache = SemanticCache(redis_client=self._redis)

        config = MiddlewareConfig(redis_url="redis://localhost:6379")
        async with MyAsyncMiddleware(config) as middleware:
            result = await middleware.awrap_model_call(request, handler)
        ```
    _redis_config_owns_client_graceful_degradation_initialized
_init_lockconfigreturnNc                 &   || _         |j        | _        d| _        t	          j                    | _        |j        |j        | _        d| _	        dS |j
        .|j        pi }t          j        |j
        fi || _        d| _	        dS t          d          )zInitialize the async middleware.

        Args:
            config: Middleware configuration with Redis connection details.

        Raises:
            ValueError: If neither redis_url nor redis_client is provided.
        FNTz1Either redis_url or redis_client must be provided)r   graceful_degradationr   r   asyncioLockr   redis_clientr   r   	redis_urlconnection_args
AsyncRedisfrom_url
ValueError)selfr   r'   s      C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langgraph/middleware/redis/aio.py__init__zAsyncRedisMiddleware.__init__?   s     %+%@"!!,.. * -DK %D)$4:O$-f.>RR/RRDK $DPQQQ    c                 
   K   dS )zSet up middleware resources asynchronously.

        Called once during lazy initialization. Subclasses should override
        this to initialize caches, indices, or other resources.
        N r+   s    r,   _setup_asyncz!AsyncRedisMiddleware._setup_asyncX   s       	r.   c                    K   | j         rdS | j        4 d{V  | j         s!|                                  d{V  d| _         	 ddd          d{V  dS # 1 d{V swxY w Y   dS )zvEnsure middleware is initialized (async-safe).

        Uses double-checked locking pattern for async safety.
        NT)r   r   r2   r1   s    r,   _ensure_initialized_asyncz.AsyncRedisMiddleware._ensure_initialized_asynca   s     
  	F? 	) 	) 	) 	) 	) 	) 	) 	)$ )'')))))))))$(!(	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	) 	)s   )A
A #A c                    K   | j         rgt          | d          rY	 | j                                         d{V  dS # t          $ r(}t
                              d|            Y d}~dS d}~ww xY wdS dS )z7Close the Redis connection if owned by this middleware.r   Nz"Error closing async Redis client: )r   hasattrr   aclose	Exceptionloggerwarning)r+   es     r,   r7   zAsyncRedisMiddleware.aclosen   s       	Ix!8!8 	IIk((*********** I I IGAGGHHHHHHHHHI	I 	I 	I 	Is   < 
A.A))A.*AsyncRedisMiddleware[AsyncRedisClientType]c                 
   K   | S )zEnter async context manager.r0   r1   s    r,   
__aenter__zAsyncRedisMiddleware.__aenter__v   s      r.   exc_typeexc_valexc_tbc                 >   K   |                                   d{V  dS )z/Exit async context manager and close resources.N)r7   )r+   r?   r@   rA   s       r,   	__aexit__zAsyncRedisMiddleware.__aexit__z   s.       kkmmr.   requesthandlerc                 (   K    ||           d{V S )a  Wrap a model call with middleware logic.

        This method is part of the LangChain AgentMiddleware protocol.
        Default implementation passes through to the handler.
        Subclasses can override to add caching, logging, etc.

        Args:
            request: The model request (typically contains messages).
            handler: The async function to call the model.

        Returns:
            The model response (ModelResponse or AIMessage).
        Nr0   r+   rD   rE   s      r,   awrap_model_callz%AsyncRedisMiddleware.awrap_model_call   s*      $ WW%%%%%%%%%r.   c                 (   K    ||           d{V S )a  Wrap a tool call with middleware logic.

        This method is part of the LangChain AgentMiddleware protocol.
        Default implementation passes through to the handler.
        Subclasses can override to add caching, logging, etc.

        Args:
            request: The tool call request.
            handler: The async function to execute the tool.

        Returns:
            The tool result message or command.
        Nr0   rG   s      r,   awrap_tool_callz$AsyncRedisMiddleware.awrap_tool_call   s*      ( WW%%%%%%%%%r.   )r    N)r    r<   ) __name__
__module____qualname____doc__r   __annotations__r   boolr#   r$   r-   r   r2   r4   r7   r>   r   typeBaseExceptionr   rC   r   r   r   r   r   rH   r   r
   LangChainToolMessager   rJ   r0   r.   r,   r   r      s         2 !   R/ RD R R R R2    ^) ) ) )I I I I   4. -( 	
 
   && <.)M*BBC& 
	& & & &(& & y/CW/L)MNN
& 
#W,	-& & & & & &r.   r   )$rN   r#   loggingabcr   typingr   r   r   r   r   r	   r
   langchain.agents.middlewarer   !langchain.agents.middleware.typesr   r   r   langchain_core.messagesr   rS   langgraph.prebuilt.tool_noder   langgraph.typesr   redis.asyncior   r(   typesr   	getLoggerrK   r9   r   r   r0   r.   r,   <module>r_      sz            N N N N N N N N N N N N N N N N N N 7 7 7 7 7 7         
 H G G G G G 8 8 8 8 8 8 # # # # # # - - - - - - # # # # # #		8	$	$w5ZHHH M& M& M& M& M&?G4H,I M& M& M& M& M&r.   