
    j                     T   d Z ddlZddlZddl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Zddl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 ddlmZ e	r*ddl m!Z" ddl#m$Z$m%Z% ddl&m'Z' ddl(m)Z) e'Z*e)Z+e$Z,e%Z-ee"e
f   Z!n
e
Z*e
Z+e
Z,e
Z-e
Z!dde.de/fdZ0 G d de      Z1y)z
Redis Cache implementation

Has 4 primary methods:
    - set_cache
    - get_cache
    - async_set_cache
    - async_get_cache
    N)	timedelta)TYPE_CHECKINGAnyListOptionalTupleUnioncast)print_verboseverbose_logger)DEFAULT_REDIS_MAJOR_VERSION)!_get_parent_otel_span_from_kwargs)coroutine_checker)RedisPipelineIncrementOperation)ServiceTypes   )	BaseCache)Span)RedisRedisCluster)Pipeline)ClusterPipeline
num_framesreturnc                 F   	 t        j                         }|y|j                  }|y|j                  }|yg }t        |       D ]9  }| n5|j                  j
                  }|j                  |       |j                  }; |sydj                  |      S # t        $ r Y yw xY w)a  
    Get the function names from the previous 1-2 functions in the call stack.

    Args:
        num_frames: Number of previous frames to include (default: 2)

    Returns:
        A string with format "current_function <- caller_function [<- grandparent_function]"
    unknownz <- )	inspectcurrentframef_backrangef_codeco_nameappendjoin	Exception)r   current_framer   framefunction_names_	func_names          t/Users/manta/Documents/Projects/TheRoad-I1/backend/.venv/lib/python3.12/site-packages/litellm/caching/redis_cache.py_get_call_stack_infor,   0   s    ,,.  %%>=z"A},,I!!),LLE # {{>** s'   B B B AB B 	B B c                       e Zd Z	 	 	 	 	 	 	 d>dee   dee   dee   dee   f fdZde	e
ef   fdZd	edefd
ZdefdZd Z	 d?dedee   defdZd@dededefdZdedefdZd Zde	eef   deeeef      dee   defdZ	 d?deeeef      dee   fdZde
d	ededee   ddf
dZdedee   fdZd Z	 	 dAdedee   dee   defdZd  Z d!efd"Z!d?dee   fd#Z"d$ee   dee   fd%Z#d$ee   dee   fd&Z$	 d?d'e	ee   eee      f   dee   de%fd(Z&	 d?dee   fd)Z'	 d?d'e	ee   eee      f   dee   de%fd*Z(de)fd+Z*de)fd,Z+d- Z,defd.Z-d/ Z.d0 Z/d1 Z0d2 Z1de%fd3Z2d	efd4Z3d5 Z4ded6ee5   deee      fd7Z6d6ee5   deee      fd8Z7d	edee   fd9Z8	 d?d	ed:ee   dee   defd;Z9ded	ededee:   fd<Z;	 	 dAd	edee   dee   de	eee   f   fd=Z< xZ=S )B
RedisCacheNredis_flush_size	namespacestartup_nodessocket_timeoutc                    ddl m}	 ddlm}
m} i }|||d<   |||d<   |||d<   |||d<   |||d	<   |j                  d
d       &t        |d
   |	      r|j                  d
      | _        n |	       | _        |j                  |        |
di || _
        d | _        || _         |di || _        || _        g | _        |d| _        n|| _        d| _        	 t%        j&                  | j                        s"| j                  j)                         d   | _        	 t-        j.                         j1                  | j3                               }	 t?        | j                  d      r| j                  j3                          t@        jB                  (tD        |   tI        t@        jB                               y tD        |           y # t*        $ r Y w xY w# t*        $ rg}dt5        |      v rt7        j8                  d       n:t7        j:                  dj=                  t5        |            dt5        |      i       Y d }~d }~ww xY w# t*        $ r,}t7        j:                  ddt5        |      i       Y d }~d }~ww xY w)Nr   )ServiceLogging   )get_redis_clientget_redis_connection_poolhostportpasswordr1   r2   service_logger_objd   Unknownredis_versionzno running event loopz1Ignoring async redis ping. No running event loop.z+Error connecting to Async Redis client - {}error)extrapingz%Error connecting to Sync Redis client)default_ttl )%litellm._service_loggerr4   _redisr6   r7   get
isinstancepopr;   updateredis_clientredis_async_clientredis_kwargsasync_redis_conn_poolr0   redis_batch_writing_bufferr/   r>   r   is_async_callableinfor%   asyncioget_running_loopcreate_taskrA   strr   debugr?   formathasattrlitellmdefault_redis_ttlsuper__init__int)selfr8   r9   r:   r/   r0   r1   r2   kwargsr4   r6   r7   rL   r)   e	__class__s                  r+   r[   zRedisCache.__init__Z   sr    	;H#'L #'L '/L$$,9L)%-;L)* ::*D1=*'(.C
 '-jj1E&FD#&4&6D#F#,<|<  	 )%>%N%N" #02'#),D!$4D!&	$66t7H7HI%)%6%6%;%;%=o%N"
	((*66tyy{CA	t((&1!!&&( $$0GW-F-F)GHG=  		  		&#a&0$$G $$AHHQP"CF+		  	  7Q?P 	sD   AG 1G 0I 	GG	IAH>>I	I;"I66I;r   c                 8   ddl m} ddlm}m} |j                  d      }|t        t        t        t        f   |      }nR |d	i | j                  | _         |d	d| j                  i| j                  }|j                  d| j                         || _        |S )
Nr   )in_memory_llm_clients_cacher5   )get_redis_async_clientr7   zasync-redis-clientkeyconnection_pool)re   valuerC   )rX   rb   rE   rc   r7   	get_cacher
   r	   async_redis_clientasync_redis_cluster_clientrL   rM   	set_cacherK   )r]   rb   rc   r7   cached_clientrK   s         r+   init_async_clientzRedisCache.init_async_client   s     	8N3==BV=W$!%(*DDE}"
 *C)WTEVEV)WD&!7 " $ : :">B>O>O" (11(0G0G 2  #5!!    re   c                 x    | j                   -|j                  | j                         s| j                   dz   |z   }|S )zD
        Make sure each key starts with the given namespace
        :)r0   
startswithr]   re   s     r+   check_and_fix_namespacez"RedisCache.check_and_fix_namespace   s5     >>%cnnT^^.L..3&,C
rn   c                    | j                   dk(  rt        S 	 t        | j                         j                         }d|v rt	        |j                  d      d         }|S t	        t        |            }|S # t        t        f$ r	 t        cY S w xY w)a  
        Parse Redis version to extract the major version number.
        
        Handles multiple version formats:
        - Strings: "7.0.0", "6", "7.0.0-rc1", " 7.0.0 "
        - Floats: 7.0 (e.g., from AWS ElastiCache Valkey)
        - Integers: 7
        - Malformed: "latest", "", "Unknown" (defaults to DEFAULT_REDIS_MAJOR_VERSION)
        
        Returns:
            int: The major version number (defaults to DEFAULT_REDIS_MAJOR_VERSION if unparseable)
        r=   .r   )	r>   r   rT   stripr\   splitfloat
ValueErrorAttributeError)r]   version_strmajor_versions      r+   _parse_redis_major_versionz%RedisCache._parse_redis_major_version   s     *..	/d001779Kk! #K$5$5c$:1$= > !  !$E+$6 7  N+ 	/..	/s   AA3 A3 3B
Bc           
          | j                   d
i |}t        d| d| d| d| j                          | j                  |      }	 t	        j                         }| j
                  j                  |t        |      |       t	        j                         }||z
  }| j                  j                  t        j                  |dt                ||       y # t        $ r!}t        d	t        |              Y d }~y d }~ww xY w)NzSet Redis Cache: key: 
Value 
ttl=, redis_version=rd   namerg   exzset_cache <- serviceduration	call_type
start_timeend_timez<litellm.caching.caching: set() - Got exception from REDIS : rC   )get_ttlr   r>   rs   timerJ   setrT   r;   service_success_hookr   REDISr,   r%   )	r]   re   rg   r^   ttlr   r   	_durationr_   s	            r+   rk   zRedisCache.set_cache   s   dll$V$$SE%seCSTXTfTfSgh	
 **s*3	J!!s#e*!Eyy{H :-I##88$**")*>*@)AB%! 9   	NsSTvhW 	s   BC 	C?C::C?rg   r   c                    | j                   }t        j                         }| j                  |      }	 t        j                         }|j                  ||      }t        j                         }	|	|z
  }
| j                  j                  t        j                  |
dt                ||	       |t        j                         }|j                  |      }t        j                         }	|	|z
  }
| j                  j                  t        j                  |
dt                ||	       |dk(  rxt        j                         }|j                  ||       t        j                         }	|	|z
  }
| j                  j                  t        j                  |
dt                ||	       |S # t        $ r@}t        j                         }	|	|z
  }
t        j                  dt        |      |       |d }~ww xY w)	Nr   r   amountzincrement_cache <- r   zincrement_cache_ttl <- zincrement_cache_expire <- zXLiteLLM Redis Caching: increment_cache() - Got exception from REDIS %s, Writing value=%s)rJ   r   r   incrr;   r   r   r   r,   r   expirer%   r   r?   rT   )r]   re   rg   r   r^   _redis_clientr   set_ttlresultr   r   current_ttlr_   s                r+   increment_cachezRedisCache.increment_cache  s    ))YY[
,,3,'1	J',,#e,DFyy{H :-I##88$**"/0D0F/GH%! 9  "!YY[
+//499;$z1	''<<(..& 78L8N7OP)% =  "$!%J!((g6#yy{H (: 5I++@@ , 2 2!*$>?S?U>V"W#-!) A  M 		yy{H :-I  jA
 G		s   E0F% %	G..;G))G.patterncountc                   K   t        j                          }	 g }| j                         }t        |d      st        j                  d       g S |j                  |dz   |      2 3 d {   }|j                  |       t        |      |k\  s) t        j                          }||z
  }t        j                  | j                  j                  t        j                  |dt                ||             |S 7 6 k# t        $ rm}	t        j                          }||z
  }t        j                  | j                  j!                  t        j                  ||	dt                ||             |	d }	~	ww xY ww)N	scan_iterz_Redis client does not support scan_iter, potentially using Redis Cluster. Returning empty list.*)matchr   zasync_scan_iter <- r   )r   r   r?   r   r   r   )r   rm   rW   r   rU   r   r#   lenrQ   rS   r;   async_service_success_hookr   r   r,   r%   async_service_failure_hook)
r]   r   r   r   keysr   re   r   r   r_   s
             r+   async_scan_iterzRedisCache.async_scan_iterA  sp    YY[
*	D 224M=+6$$u 	*447S=PU4V cC t9% yy{H :-I''BB(..& 34H4J3KL)% C  K#V$  	 yy{H :-I''BB(..& 34H4J3KL)% C 	 G	s`   E14C8 E1C8 #C6'C4(C6+ C8 A'C8 3E14C66C8 8	E.A(E))E..E1scriptc                 X   	 | j                         t        d      rj                  |      S t        d      r:j                  |      dt        t
           dt        t           dt        ffd}|S y# t        $ r(}t        j                  dt        |              |d}~ww xY w)	a  
        Register a Lua script with Redis asynchronously.
        Works with both standalone Redis and Redis Cluster.

        Args:
            script (str): The Lua script to register

        Returns:
            Any: A script object that can be called with keys and args
        register_scriptscript_loadr   argsr   c                 J   K    j                   t        |       g| | S wN)evalshar   )r   r   r   
script_shas     r+   script_callablez9RedisCache.async_register_script.<locals>.script_callable  s+     0=00SYUUPTUUs    #z Error registering Redis script: N)
rm   rW   r   r   r   rT   r   r%   r   r?   )r]   r   r   r_   r   r   s       @@r+   async_register_scriptz RedisCache.async_register_scripto  s    	 224M}&78$44V<<6*66v>
VS	 Vc Vs V '& 7  	  #CCF8!LMG	s   ,A8 AA8 8	B)#B$$B)c                 2  K   ddl m} t        j                         }	 | j                         }| j!                  |      } | j"                  di |}
|j%                  dd      }t'        d	| d
| d|
        	 t)        |d      st	        d      |j+                  |t-        j.                  |      ||
       d {   }t'        d| d
| d|
        t        j                         }||z
  }	t        j                  | j                  j1                  t        j                  |	dt                ||t        |      d|i             |S # t        $ r}t        j                         }||z
  }	t        j                  | j                  j                  t        j                  |	|||t        |      dt                             t        j                  dt        |      |       |d }~ww xY w7 0# t        $ r}t        j                         }||z
  }	t        j                  | j                  j                  t        j                  |	|dt                ||t        |      d|i             t        j                  dt        |      |       Y d }~y d }~ww xY ww)Nr   r   zasync_set_cache <- r   r   r?   r   r   parent_otel_spanr   RLiteLLM Redis Caching: async set() - Got exception from REDIS %s, Writing value=%srd   nxFSet ASYNC Redis Cache: key: r   r   r   z3Redis client cannot set cache. Attribute not found.)r   rg   r   r   z)Successfully Set ASYNC Redis Cache: key: re   r   r   r   r   r   r   event_metadatar   r   r?   r   r   r   r   r   rC   )redis.asyncior   r   rm   r%   rQ   rS   r;   r   r   r   r   r,   r   r?   rT   rs   r   rF   r   rW   r   jsondumpsr   )r]   re   rg   r^   r   r   r   r_   r   r   r   r   r   s                r+   async_set_cachezRedisCache.async_set_cache  s    'YY[
	#'#9#9#;M, **s*3dll$V$ZZe$4SE%seTU-	=%0 UVV(,,jj'	 -  F ;C5vVYUZ[ yy{H :-I''BB(..& 34H4J3KL)%%Fv%N$)3< C 
 Mg  	yy{H :-I''BB(..&)%%Fv%N 34H4J3KL C 
   dA
 G'	:.  	yy{H :-I''BB(..& 34H4J3KL)%%Fv%N$)3< C 	   dA 	sh   JE A
J9AG. ;G+<BG. J	G(BG##G((J+G. .	J7BJ
JJJpipe
cache_listc           	      8  K   | j                  |      }|D ]d  \  }}| j                  |      }t        d| d| d|        t        j                  |      }d}|t        |      }|j                  |||       f |j                          d{   }|S 7 w)	zU
        Helper function for executing a pipeline of set operations on Redis
        r   rd   z%Set ASYNC Redis Cache PIPELINE: key: r   r   Nsecondsr   )r   rs   r   r   r   r   r   execute)	r]   r   r   r   	cache_keycache_valuejson_cache_value_tdresultss	            r+   _pipeline_helperzRedisCache._pipeline_helper  s      llsl#&0"I{444CI7	{(;-W]^a]bc  $zz+6'+C,HH&   '1  & 's   BBBBc                   K   t        |      dk(  ry| j                         }t        j                         }t        d| d| d| j                          d}	 |j                  d      4 d{   }| j                  |||       d{   }ddd      d{    t        d        t        j                         }	|	|z
  }
t        j                  | j                  j                  t        j                  |
d	t                ||	t        |      
             y7 7 7 # 1 d{  7  sw Y   xY w# t        $ r}t        j                         }	|	|z
  }
t        j                  | j                  j!                  t        j                  |
|d	t                ||	t        |                   t#        j$                  dt'        |      |       Y d}~yd}~ww xY ww)z?
        Use Redis Pipelines for bulk write operations
        r   Nz!Set Async Redis Cache: key list: r   r   Ftransactionzpipeline results: zasync_set_cache_pipeline <- r   r   r   r   r   r   r   r   r?   r   r   r   r   zaLiteLLM Redis Caching: async set_cache_pipeline() - Got exception from REDIS %s, Writing value=%s)r   rm   r   r   r>   pipeliner   rQ   rS   r;   r   r   r   r,   r   r%   r   r   r?   rT   )r]   r   r   r^   r   r   r   r   r   r   r   r_   s               r+   async_set_cache_pipelinez#RedisCache.async_set_cache_pipeline  s     z?a..0YY[
/
|6#FVW[WiWiVjk	
  (	$--%-@@D $ 5 5dJ LL A@ .wi89 yy{H :-I''BB(..& <=Q=S<TU)%%Fv%N C 	 % AL A@@@&  	yy{H :-I''BB(..& <=Q=S<TU)%%Fv%N C 
   sA !	s   AGD6 -D.D6 1D!D	D!D6 DBD6 GD6 D!D6 !D3'D*(D3/D6 6	G?BGGGGrJ   c                    K   | j                  |      }	  |j                  |g|  d{    |'t        |      }|j                  ||       d{    yy7 .7 # t        $ r  w xY ww)z@Helper function for async_set_cache_sadd. Separated for testing.r   Nr   )r   saddr   r   r%   )r]   rJ   re   rg   r   r   s         r+   _set_cache_sadd_helperz!RedisCache._set_cache_sadd_helper5  s~      llsl#	#,##C0%000,"))#s333  1 4 		s>   A-A A'A AA A-A A A**A-c                   K   ddl m} t        j                         }	 | j                         }| j!                  |      }t#        d| d| d	|        	 | j%                  ||||
       d {    t#        d| d| d	|        t        j                         }	|	|z
  }
t        j                  | j                  j'                  t        j                  |
dt                ||	t        |                   y # t        $ r}t        j                         }	|	|z
  }
t        j                  | j                  j                  t        j                  |
|||	t        |      dt                             t        j                  dt        |      |       |d }~ww xY w7 ,# t        $ r}t        j                         }	|	|z
  }
t        j                  | j                  j                  t        j                  |
|dt                ||	t        |                   t        j                  dt        |      |       Y d }~y d }~ww xY ww)Nr   r   zasync_set_cache_sadd <- r   r   rd   r   r   r   )rJ   re   rg   r   z.Successfully Set ASYNC Redis Cache SADD: key: r   r   z]LiteLLM Redis Caching: async set_cache_sadd() - Got exception from REDIS %s, Writing value=%s)r   r   r   rm   r%   rQ   rS   r;   r   r   r   r   r,   r   r?   rT   rs   r   r   r   )r]   re   rg   r   r^   r   r   r   r_   r   r   s              r+   async_set_cache_saddzRedisCache.async_set_cache_saddF  sQ     	(YY[
	#'#9#9#;M. **s*34SE%seTU&	--*5c .    @XeWTZ[^Z_` yy{H :-I''BB(..& 89M9O8PQ)%%Fv%N C 	C  	yy{H :-I''BB(..&)%%Fv%N 89M9O8PQ C 
   dA
 G)	2$  	yy{H :-I''BB(..& 89M9O8PQ)%%Fv%N C 
   oA 	sf   IC6 &IF -F.BF 5I6	F?BFFIF 	H?%BH:5I:H??Ic                 &  K   t        dt        | j                                | j                  |      }| j                  j	                  ||f       t        | j                        | j
                  k\  r| j                          d {    y y 7 w)Nz-in batch cache writing for redis buffer size=rd   )r   r   rN   rs   r#   r/   flush_cache_buffer)r]   re   rg   r^   s       r+   batch_cache_writezRedisCache.batch_cache_write  s     ;C@_@_<`;ab	
 **s*3''..U|<t../43H3HH))+++ I+s   BBB	Br   c                 b  K   ddl m} | j                         }t        j                         }| j	                  |      }| j                  |      }	 |j                  ||       d {   }	|8|j                  |       d {   }
|
dk(  r|j                  ||       d {    t        j                         }||z
  }t        j                  | j                  j                  t        j                  |dt                |||             |	S 7 7 7 p# t         $ r}t        j                         }||z
  }t        j                  | j                  j#                  t        j                  ||dt                |||	             t%        j&                  d
t)        |      |       |d }~ww xY ww)Nr   r   r   rd   r   r   zasync_increment <- r   r   z^LiteLLM Redis Caching: async async_increment() - Got exception from REDIS %s, Writing value=%s)r   r   rm   r   r   rs   incrbyfloatr   r   rQ   rS   r;   r   r   r   r,   r%   r   r   r?   rT   )r]   re   rg   r   r   r   r   r   	_used_ttlr   r   r   r   r_   s                 r+   async_incrementzRedisCache.async_increment  s     	(#557YY[
LLSL)	**s*3,	(44#e4LLF$$1$5$5c$::"$'..sI>>> yy{H :-I''BB(..& 34H4J3KL)%%5 C 	 M- M ; ?"  	yy{H :-I''BB(..& 34H4J3KL)%%5 C 
   pA
 G)	sb   AF/D (D)D DD "D#A+D F/D D D 	F,B	F''F,,F/c                    K   t        dt        | j                                | j                  | j                         d {    g | _        y 7 w)Nz,flushing to redis....reached size of buffer )r   r   rN   r   r]   s    r+   r   zRedisCache.flush_cache_buffer  sN     :3t?^?^;_:`a	
 ++D,K,KLLL*,' 	Ms   A AAAcached_responsec                     ||S |j                  d      }	 t        j                  |      }|S # t        $ r t	        j
                  |      }Y |S w xY w)z[
        Common 'get_cache_logic' across sync + async redis client implementations
        utf-8)decoder   loadsr%   astliteral_eval)r]   r   s     r+   _get_cache_logiczRedisCache._get_cache_logic  sh     """)009	@"jjO
   	@!..?O	@s   . AAc                    	 | j                  |      }t        d|        t        j                         }| j                  j	                  |      }t        j                         }||z
  }| j
                  j                  t        j                  |dt                |||       t        d| d|        | j                  |      S # t        $ r }t        j                  d|       Y d }~y d }~ww xY w)	Nrd   zGet Redis Cache: key: zget_cache <- r   zGot Redis Cache: key: , cached_response r   z;litellm.caching.caching: get() - Got exception from REDIS: )rs   r   r   rJ   rF   r;   r   r   r   r,   r   r%   r   r?   )	r]   re   r   r^   r   r   r   r   r_   s	            r+   rh   zRedisCache.get_cache  s    	..3.7C23%89J"//33C8Oyy{H :-I##88$**")*>*@)AB%!!1 9  (-??PQ (((II 	  Mq 	s   CC 	C0C++C0r   c                 :    | j                   j                  |      S )
        Wrapper to call `mget` on the redis client

        We use a wrapper so RedisCluster can override this method
        r   )rJ   mget)r]   r   s     r+   _run_redis_mget_operationz$RedisCache._run_redis_mget_operation  s       %%4%00rn   c                 b   K   | j                         }|j                  |       d{   S 7 w)r   r   N)rm   r   )r]   r   ri   s      r+   _async_run_redis_mget_operationz*RedisCache._async_run_redis_mget_operation  s1      "335',,$,7777s   &/-/key_listc                    i }|D cg c]  }||	 }}	 g }|D ])  }| j                  |xs d      }|j                  |       + t        j                         }| j                  |      }	t        j                         }
|
|z
  }| j                  j                  t        j                  |dt                ||
|       t        t        ||	            }i }|j                         D ]<  \  }}t        |t              r|j                  d      }| j                  |      }|||<   > |S c c}w # t         $ r-}t#        j$                  dt'        |              |cY d}~S d}~ww xY w)	a  
        Use Redis for bulk read operations

        Args:
            key_list: List of keys to get from Redis
            parent_otel_span: Optional parent OpenTelemetry span

        Returns:
            dict: A dictionary mapping keys to their cached values
        N rd   r   zbatch_get_cache <- r   r   z$Error occurred in batch get cache - )rs   r#   r   r   r;   r   r   r   r,   dictzipitemsrG   bytesr   r   r%   r   r?   rT   )r]   r   r   key_value_dictre   	_key_list_keysr   r   r   r   r   decoded_resultskvr_   s                   r+   batch_get_cachezRedisCache.batch_get_cache  sl    $,@HSSH	@ 	"E&	 88Y_"8M	Y' ' J :::FGyy{H :-I##88$**"/0D0F/GH%!!1 9  "#i"9:N O&,,.1a')A))!,%&"	 / #"? A@  	"  #GAx!PQ!!	"s(   D'D'DD, ,	E"5"EE"E"c                    K   ddl m} | j                         }| j                  |      }t	        j                         }	 t        d|        |j                  |       d {   }t        d| d|        | j                  |      }t	        j                         }	|	|z
  }
t        j                  | j                  j                  t        j                  |
dt                ||	|d	|i
             |S 7 # t        $ r}t	        j                         }	|	|z
  }
t        j                  | j                  j!                  t        j                  |
|dt                ||	|d	|i             t        dt#        |              Y d }~y d }~ww xY ww)Nr   r   rd   zGet Async Redis Cache: key: zGot Async Redis Cache: key: r   r   zasync_get_cache <- re   r   r   zAlitellm.caching.caching: async get() - Got exception from REDIS: )r   r   rm   rs   r   r   rF   r   rQ   rS   r;   r   r   r   r,   r%   r   rT   )r]   re   r   r^   r   r   r   r   responser   r   r_   s               r+   async_get_cachezRedisCache.async_get_cacheH  s     	(#557**s*3YY[
'	8>?$1$5$5c$::O.se3EoEVW ,,_,MHyy{H :-I''BB(..& 34H4J3KL)%%5$)3< C 
 O' ;(  	yy{H :-I''BB(..& 34H4J3KL)%%5$)3< C 	 STWXYTZS[\ 	sC   =F "C7 "C5#BC7 4F5C7 7	F BFFFFc                   K   i }t        j                          }|D cg c]  }||	 }}	 g }|D ]%  }| j                  |      }|j                  |       ' | j                  |       d{   }	t        j                          }
|
|z
  }t	        j
                  | j                  j                  t        j                  |dt                ||
|             t        t        ||	            }i }|j                         D ]<  \  }}t        |t              r|j!                  d      }| j#                  |      }|||<   > |S c c}w 7 # t$        $ r}t        j                          }
|
|z
  }t	        j
                  | j                  j'                  t        j                  ||dt                ||
|             t)        j*                  dt-        |              |cY d}~S d}~ww xY ww)	a[  
        Use Redis for bulk read operations

        Args:
            key_list: List of keys to get from Redis
            parent_otel_span: Optional parent OpenTelemetry span

        Returns:
            dict: A dictionary mapping keys to their cached values

        `.mget` does not support None keys. This will filter out None keys.
        Nrd   r   zasync_batch_get_cache <- r   r   r   z*Error occurred in async batch get cache - )r   rs   r#   r   rQ   rS   r;   r   r   r   r,   r   r   r   rG   r   r   r   r%   r   r   r?   rT   )r]   r   r   r   r   re   r   r   r   r   r   r   r   r   r  r_   s                   r+   async_batch_get_cachez RedisCache.async_batch_get_cachez  s    $ YY[
$,@HSSH	@0	"E&	 88Y8G	Y' ' !@@e@LLGyy{H :-I''BB(..& 9:N:P9QR)%%5 C 	 "#i"9:N O&,,.1a')A))!,%&"	 / #"A A M6  	"yy{H :-I''BB(..& 9:N:P9QR)%%5 C 
   #McRSfX!VW!!!	"sX   G'E E G'AE -E.CE ?G'E 	G$B	GG$G'G$$G'c           	      D   t        d       t        j                         }	 | j                  j                         }t        d|        t        j                         }||z
  }| j                  j                  t        j                  |dt                ||       |S # t        $ ry}t        j                         }||z
  }| j                  j                  t        j                  ||dt                       t        j                  dt        |              |d}~ww xY w)zD
        Tests if the sync redis client is correctly setup.
        zPinging Sync Redis CachezRedis Cache PING: zsync_ping <- r   r   r   r?   r   7LiteLLM Redis Cache PING: - Got exception from REDIS : N)r   r   rJ   rA   r;   r   r   r   r,   r%   service_failure_hookr   r?   rT   )r]   r   r  r   r   r_   s         r+   	sync_pingzRedisCache.sync_ping  s    	01YY[
	!..335H.xj9:yy{H :-I##88$**")*>*@)AB%! 9  O 	 yy{H :-I##88$**")*>*@)AB	 9    I#a&R G	s   A;B 	D&A4DDc                   K   | j                         }t        j                         }t        d       	 |j                          d {   }t        j                         }||z
  }t	        j
                  | j                  j                  t        j                  |dt                             |S 7 i# t        $ r}t        j                         }||z
  }t	        j
                  | j                  j                  t        j                  ||dt                             t        j                  dt        |              |d }~ww xY ww)NzPinging Async Redis Cachezasync_ping <- r   r   r   r	  r
  )rm   r   r   rA   rQ   rS   r;   r   r   r   r,   r%   r   r   r?   rT   )r]   r   r   r  r   r   r_   s          r+   rA   zRedisCache.ping  s5    !335YY[
12	*//11Hyy{H :-I''BB(..& ./C/E.FG C  O 2  	 yy{H :-I''BB(..& ./C/E.FG	 C    I#a&R G!	s<   0E
B2 B0A(B2 /E
0B2 2	E;BEEE
c                 ^   K   | j                         } |j                  |  d {    y 7 wr   rm   delete)r]   r   r   s      r+   delete_cache_keyszRedisCache.delete_cache_keys	  s*     !335"m""D)))s   #-+-c                 :    | j                   j                         }|S r   )rJ   client_list)r]   r  s     r+   r  zRedisCache.client_list  s     --99;rn   c                 :    | j                   j                         }|S r   )rJ   rP   )r]   rP   s     r+   rP   zRedisCache.info  s      %%'rn   c                 8    | j                   j                          y r   rJ   flushallr   s    r+   flush_cachezRedisCache.flush_cache      ""$rn   c                 8    | j                   j                          y r   r  r   s    r+   r  zRedisCache.flushall  r  rn   c                 X   K   | j                   j                  d       d {    y 7 w)NT)inuse_connections)rM   
disconnectr   s    r+   r  zRedisCache.disconnect  s#     ((33d3KKKs    *(*c                 t  K   	 ddl m}  |j                  di | j                  }|j	                          d{   }|j                          d{    |rdddS dddS 7 (7 # t        $ rF}t        j                  dt        |              dd	t        |       t        |      d
cY d}~S d}~ww xY ww)aa  
        Test the Redis connection by creating a new client and pinging it.
        
        This creates a fresh connection without using cached clients or connection pools
        to ensure the credentials are actually valid.
        
        Returns:
            dict: {"status": "success" | "failed", "message": str, "error": Optional[str]}
        r   Nsuccessz Redis connection test successful)statusmessagefailedzRedis ping returned FalsezRedis connection test failed: zRedis connection failed: )r!  r"  r?   rC   )
r   rQ   r   rL   rA   acloser%   r   r?   rT   )r]   redis_asyncrJ   ping_resultr_   s        r+   test_connectionzRedisCache.test_connection   s     	/ -;,,At/@/@AL !- 1 1 33K %%''''A  ':  4 (  	  #A#a&!JK"6s1vh?Q 	sb   B85A& A"A& A$
A& B8A& !B8"A& $A& &	B5/;B0*B5+B80B55B8c                 `   K   | j                         }|j                  |       d {   S 7 wr   r  )r]   re   r   s      r+   async_delete_cachezRedisCache.async_delete_cacheH  s+     !335"))#....s   %.,.c                 :    | j                   j                  |       y r   )rJ   r  rr   s     r+   delete_cachezRedisCache.delete_cacheN  s      %rn   increment_listc           
        K   |D ]m  }| j                  |d         }t        d| d|d    d|d           |j                  ||d          |d   Mt        |d   	      }|j	                  ||       o |j                          d{   }t        j                  d
|        |D cg c]  }t        |t              s| c}S 7 =c c}w w)z1Helper function for pipeline increment operationsre   rd   z+Increment ASYNC Redis Cache PIPELINE: key: r   increment_valuer   r   Nr   z/Increment ASYNC Redis Cache PIPELINE: results: )
rs   r   r   r   r   r   r   rU   rG   rx   )r]   r   r,  increment_opr   r   r   rs           r+   _pipeline_increment_helperz%RedisCache._pipeline_increment_helperQ  s      +L44e9L4MI=i[Q]^oQpPqqw  yE  FK  yL  xM  N Y5F(GHE".U(;<Is+ + &=gYG	
 #;7ajE&:7;; '
 <s0   AC6CC	 C)C?CCCc                   K   t        |      dk(  ryddlm} | j                         }t	        j                         }t        d|        	 |j                  d      4 d{   }| j                  ||       d{   }ddd      d{    t	        j                         }||z
  }	t        j                  | j                  j                  t        j                  |	dt                ||t        |                   S 7 7 7 y# 1 d{  7  sw Y   xY w# t         $ r}
t	        j                         }||z
  }	t        j                  | j                  j#                  t        j                  |	|
dt                ||t        |      	             t%        j&                  d
t)        |
             |
d}
~
ww xY ww)a  
        Use Redis Pipelines for bulk increment operations
        Args:
            increment_list: List of RedisPipelineIncrementOperation dicts containing:
                - key: str
                - increment_value: float
                - ttl_seconds: int
        r   Nr   z6Increment Async Redis Cache Pipeline: increment list: Fr   zasync_increment_pipeline <- r   r   zOLiteLLM Redis Caching: async increment_pipeline() - Got exception from REDIS %s)r   r   r   rm   r   r   r   r1  rQ   rS   r;   r   r   r   r,   r   r%   r   r   r?   rT   )r]   r,  r^   r   r   r   r   r   r   r   r_   s              r+   async_increment_pipelinez#RedisCache.async_increment_pipelinei  s     ~!#'#557YY[
D^DTU	
%	$--%-@@D $ ? ?n UU A@ yy{H :-I''BB(..& <=Q=S<TU)%%Fv%N C 	 N! AU A@@@"  	yy{H :-I''BB(..& <=Q=S<TU)%%Fv%N C 
   aA G'	s   AF>D !D"D %D;D<D D DA4D  F>D DD DDDD 	F;%BF66F;;F>c                    K   	 | j                         }|j                  |       d{   }|dk  ry|S 7 # t        $ r"}t        j                  d|        Y d}~yd}~ww xY ww)a  
        Get the remaining TTL of a key in Redis

        Args:
            key (str): The key to get TTL for

        Returns:
            Optional[int]: The remaining TTL in seconds, or None if key doesn't exist

        Redis ref: https://redis.io/docs/latest/commands/ttl/
        Nr   zRedis TTL Error: )rm   r   r%   r   rU   )r]   re   r   r   r_   s        r+   async_get_ttlzRedisCache.async_get_ttl  sj     		!%!7!7!9M%))#..CbyJ /  	  #4QC!89	s@   A%$7 5	7 A%7 A%7 	A" AA%A""A%valuesc                   K   | j                         }t        j                         }	  |j                  |g|  d{   }t        j                         }||z
  }	t        j                  | j
                  j                  t        j                  |	dt                             |S 7 i# t        $ r}
t        j                         }||z
  }	t        j                  | j
                  j                  t        j                  |	|
dt                             t        j                  dt        |
              |
d}
~
ww xY ww)aR  
        Append one or multiple values to a list stored at key

        Args:
            key: The Redis key of the list
            values: One or more values to append to the list
            parent_otel_span: Optional parent OpenTelemetry span

        Returns:
            int: The length of the list after the push operation
        Nzasync_rpush <- r  r	  z8LiteLLM Redis Cache RPUSH: - Got exception from REDIS : )rm   r   rpushrQ   rS   r;   r   r   r   r,   r%   r   r   r?   rT   )r]   re   r6  r   r^   r   r   r  r   r   r_   s              r+   async_rpushzRedisCache.async_rpush  s7    $ "335YY[
	0]00>v>>Hyy{H :-I''BB(..& /0D0F/GH C  O ?  	 yy{H :-I''BB(..& /0D0F/GH	 C    J3q6(S G!	s:   %EB* B(A(B* 'E(B* *	D?3BD::D??Ec                    K   g }t        |      D ]F  }|j                  |       |j                          d {   }|D ]  }||j                  |        H |S 7 #wr   )r    lpopr   r#   )r]   r   re   r   r   r)   r   r0  s           r+   *handle_lpop_count_for_older_redis_versionsz5RedisCache.handle_lpop_count_for_older_redis_versions  s]      !uAIIcN LLN*G =MM!$    +s   5AAAAc                   K   | j                         }t        j                         }t        d| d|        	 | j                         }|L|dk  rG|j	                  d      4 d {   }| j                  |||       d {   }	d d d       d {    n|j                  ||       d {   }	t        j                         }
|
|z
  }t        j                  | j                  j                  t        j                  |dt                             t        	t              r	 |	j!                  d      S t        |	t$              r2t'        d	 |	D              r 	 |	D cg c]  }|j!                  d       c}S |	S 7 7 7 # 1 d {  7  sw Y   xY w7 # t"        $ r |	cY S w xY wc c}w # t"        $ r |	cY S w xY w# t"        $ r}t        j                         }
|
|z
  }t        j                  | j                  j)                  t        j                  ||dt                
             t+        j,                  dt/        |              |d }~ww xY ww)NzLPOP from Redis list: key: z	, count:    Fr   zasync_lpop <- r  r   c              3   <   K   | ]  }t        |t                y wr   )rG   r   ).0items     r+   	<genexpr>z(RedisCache.async_lpop.<locals>.<genexpr>)  s      24:D
4'Fs   r	  z7LiteLLM Redis Cache LPOP: - Got exception from REDIS : )rm   r   r   r}   r   r<  r;  rQ   rS   r;   r   r   r   r,   rG   r   r   r%   listallr   r   r?   rT   )r]   re   r   r   r^   r   r   r|   r   r   r   r   rA  r_   s                 r+   
async_lpopzRedisCache.async_lpop  sU     "335YY[
3C5	%IJ6	 ;;=M ]Q%6(11e1DD#'#R#Rc5$ F EDD  -11#u== yy{H :-I''BB(..& ./C/E.FG C  &%("!==11 FD)c 24:2 /"=CDVTDKK0VDD MA E EDDD >" ! "!M" E  "!M"  	 yy{H :-I''BB(..& ./C/E.FG	 C    I#a&R G!	s  6I-F? &E:'F? *FE=FF? E?F? ,F-A7F? %F 5I6"F? F. F)5F. 7I8F? 9I:F? =F?F? FF
FF? F&#F? $I%F&&F? )F. .F<9F? :I;F<<F? ?	IBIII)NNNr<   NNg      @r   )r<   )NN)>__name__
__module____qualname__r   r\   rT   r   rx   r[   r	   ri   rj   rm   rs   r}   rk   r   rC  r   r   r   r   r   cluster_pipeliner   r   r   r   r   r   r   r   r   r   rh   r   r   r   r  r  r  boolr  rA   r  r  rP   r  r  r  r'  r)  r+  r   r1  r3  r5  r9  r   r<  rE  __classcell__)r`   s   @r+   r.   r.   W   ss   
 *-#'(,*-U
 #3-U C=U  ~U !Un"	!#==	>"23 3 /C /:2 7;77$,UO7	7r,S , ,t ,\C C <M^H../ sCx) e_	
 
> IM9uS#X/96>uo9v(  	
 e_ 
"FF%-e_FP, "+/9 9 c]	9
 #4.9 
9v-  x~ 41d3i 1DI 18$s) 8S	 8 ,02"S	4#6672" #4.2" 
	2"j 7;0%-d^0j ,0E"S	4#667E" #4.E" 
	E"N"4 "H"D "H*T %%L&t &P/C /&<< <=< 
$u+		<0="#BC=	$u+	=~s x} 6 ,0	11 S	1 #4.	1 
1f#&/2	e$  $+/	@@ }@ #4.	@ 
sDI~	@rn   r.   )r5   )2__doc__r   rQ   r   r   r   datetimer   typingr   r   r   r   r   r	   r
   rX   litellm._loggingr   r   litellm.constantsr   'litellm.litellm_core_utils.core_helpersr   ,litellm.litellm_core_utils.coroutine_checkerr   litellm.types.cachingr   litellm.types.servicesr   
base_cacher   opentelemetry.tracer   _Spanr   r   r   redis.asyncio.clientr   redis.asyncio.clusterr   r   rI  ri   rj   r\   rT   r,   r.   rC   rn   r+   <module>rZ     s          I I I  : 9 U J A / !11-5H&!-DH!$D$S $ $Nj jrn   