
    AHj                        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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mZmZ ddl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% 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-Z0e/Z1e*Z2e+Z3ee(ef   Z'n
eZ0eZ1eZ2eZ3eZ'dde4de5fdZ6 G d d      Z7d Z8 G d de%      Z9y)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'REDIS_CIRCUIT_BREAKER_FAILURE_THRESHOLD&REDIS_CIRCUIT_BREAKER_RECOVERY_TIMEOUT)!_get_parent_otel_span_from_kwargs)coroutine_checker)RedisPipelineIncrementOperationRedisPipelineLpopOperationRedisPipelineRpushOperation)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          S/root/tools/cai/cai_env/lib/python3.12/site-packages/litellm/caching/redis_cache.py_get_call_stack_infor0   :   s    ,,.  %%>=z" 	!A},,I!!),LLE	! {{>** s'   B B B AB B 	B B c                   L    e Zd ZdZdZdZdZdededdfd	Zde	fd
Z
ddZddZy)RedisCircuitBreakera  
    Tracks Redis health for a RedisCache instance.

    States:
      CLOSED    - normal, Redis is called
      OPEN      - Redis is down, raise immediately (no network call)
      HALF_OPEN - recovery probe: allow one request through

    Transitions:
      CLOSED    -> OPEN      after failure_threshold consecutive failures
      OPEN      -> HALF_OPEN after recovery_timeout seconds
      HALF_OPEN -> CLOSED    on success
      HALF_OPEN -> OPEN      on failure (resets timer)
    closedopen	half_openfailure_thresholdrecovery_timeoutr   Nc                 ^    || _         || _        d| _        d | _        | j                  | _        y )Nr   )r6   r7   _failure_count
_opened_atCLOSED_state)selfr6   r7   s      r/   __init__zRedisCircuitBreaker.__init__u   s,    !2 0+/kk    c                     | j                   | j                  k(  ry| j                   | j                  k(  rEt        j                         | j                  xs dz
  | j
                  kD  r| j                  | _         yyy)z.Returns True if Redis calls should be skipped.Tr   F)r<   	HALF_OPENOPENtimer:   r7   r=   s    r/   is_openzRedisCircuitBreaker.is_open|   s]    ;;$..( ;;$))#yy{doo23d6K6KK"nnr?   c                 >   | xj                   dz  c_         t        j                         | _        | j                   | j                  k\  rV| j                  | j
                  k7  r+t        j                  d| j                   | j                         | j
                  | _        y y )Nr   u_   Redis circuit breaker OPENED after %d consecutive failures — fast-failing Redis calls for %ds)	r9   rC   r:   r6   r<   rB   r   warningr7   rD   s    r/   record_failurez"RedisCircuitBreaker.record_failure   s{    q ))+$"8"88{{dii'&&7''))	 ))DK 9r?   c                     | j                   | j                  k(  rt        j                  d       d| _        | j
                  | _         y )Nu0   Redis circuit breaker CLOSED — Redis recoveredr   )r<   rA   r   infor9   r;   rD   s    r/   record_successz"RedisCircuitBreaker.record_success   s4    ;;$..( RSkkr?   )r   N)__name__
__module____qualname____doc__r;   rB   rA   intr>   boolrE   rH   rK    r?   r/   r2   r2   a   sH     FDI"# " " " $"r?   r2   c                 B     t        j                          fd       }|S )z
    Decorator for RedisCache async methods.
    Checks the circuit breaker before each call; records success/failure after.
    Does not apply to ping/disconnect/test_connection (health/teardown must always run).
    c                 &  K   | j                   j                         rt        dj                         	  | g|i | d {   }| j                   j	                          |S 7  # t        $ r | j                   j                           w xY ww)Nu+   Redis circuit breaker is open — skipping )_circuit_breakerrE   r)   rL   rK   rH   )r=   argskwargsresultmethods       r/   wrapperz-_redis_circuit_breaker_guard.<locals>.wrapper   s       ((*=foo=NO 	!$8888F!!002M 9  	!!002	s.   3BA) A'A) &B'A) )%BB)	functoolswraps)rY   rZ   s   ` r/   _redis_circuit_breaker_guardr]      s'     __V  Nr?   c                   $    e Zd Z	 	 	 	 	 	 	 dIdee   dee   dee   dee   f fdZd Z	de
fd	Zde
fd
Zde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	 dJdedee   defdZedKdededefd       ZdedefdZed        Zdeeef   deeeef      dee   defdZe	 dJd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!ededee   fd!       Z"ed"        Z#e	 	 dLdedee   d#ee$   defd$       Z%d% Z&d&efd'Z'dJd#ee$   fd(Z(d)ee   dee   fd*Z)d)ee   dee   fd+Z*	 dJd,eee   eee      f   d#ee$   de+fd-Z,e	 dJd#ee$   fd.       Z-e	 dJd,eee   eee      f   d#ee$   de+fd/       Z.de/fd0Z0de/fd1Z1ed2        Z2defd3Z3d4 Z4d5 Z5d6 Z6d7 Z7de+fd8Z8edefd9       Z9d: Z:ded;ee;   deee      fd<Z<ed;ee;   deee      fd=       Z=ededee   fd>       Z>e	 dJded?ee   d#ee$   defd@       Z?dedAee@   dee   fdBZAedAee@   dee   fdC       ZBdedededeeC   fdDZDe	 	 dLdedee   d#ee$   deeee   f   fdE       ZEdedFeeF   deeee         fdGZGedFeeF   deeee         fdH       ZH xZIS )M
RedisCacheNredis_flush_size	namespacestartup_nodessocket_timeoutc                 4   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-        t.        t0              | _        | j5                          t6        j8                  (t:        | y  t?        t6        j8                               y t:        | y          y # t*        $ r Y |w xY w)Nr   )ServiceLogging   )get_redis_clientget_redis_connection_poolhostportpasswordrb   rc   service_logger_objd   Unknownredis_version)r6   r7   )default_ttlrR   ) litellm._service_loggerre   _redisrg   rh   get
isinstancepoprl   updateredis_clientredis_async_clientredis_kwargsasync_redis_conn_poolra   redis_batch_writing_bufferr`   ro   r   is_async_callablerJ   r)   r2   r   r   rU   _setup_health_pingslitellmdefault_redis_ttlsuperr>   rP   )r=   ri   rj   rk   r`   ra   rb   rc   rW   re   rg   rh   ry   	__class__s                r/   r>   zRedisCache.__init__   s    	;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" !4EC!

 	  "$$0GW-F-F)GHG  		s   AF 	FFc                 f   	 t        j                         j                  | j                               }	 t        | j                  d      r| j                  j                          yy# t        $ rx}dt        |      v rt        j                  d       nKt        j                  dj                  t        |            dt        |      i       | j                  |       Y d}~d}~ww xY w# t        $ r=}t        j                  ddt        |      i       | j                  |       Y d}~yd}~ww xY w)	z,Setup async and sync health pings for Redis.zno running event loopz1Ignoring async redis ping. No running event loop.z+Error connecting to Async Redis client - {}error)extraNpingz%Error connecting to Sync Redis client)asyncioget_running_loopcreate_taskr   r)   strr   debugr   format_handle_async_ping_errorhasattrrw   _handle_sync_ping_error)r=   r-   es      r/   r}   zRedisCache._setup_health_pings   s    	1((*66tyy{CA	,t((&1!!&&( 2  
	1&#a&0$$G $$AHHQP"CF+ --a0
	1   	,  7Q?P ((++		,s/   1A& 0C* &	C'/A.C""C'*	D033D++D0r   c                     	 t        j                         }t        j                         }|}|j                  | j                  j                  t        j                  ||z
  |d             y# t        $ r Y yw xY w)z2Handle async ping error with service failure hook.redis_async_pingservicedurationr   	call_typeN	r   r   rC   r   rl   async_service_failure_hookr   REDISr)   r=   r   loop
start_timeend_times        r/   r   z#RedisCache._handle_async_ping_error  sx    	++-DJ!H''BB(..%
20	 C   		   A)A, ,	A87A8c                     	 t        j                         }t        j                         }|}|j                  | j                  j                  t        j                  ||z
  |d             y# t        $ r Y yw xY w)z1Handle sync ping error with service failure hook.redis_sync_pingr   Nr   r   s        r/   r   z"RedisCache._handle_sync_ping_error+  sx    	++-DJ!H''BB(..%
2/	 C   		r   r   c                     t        | j                  j                               }t        j                  |d      }t        j                  |j                               j                         dd }d| S )z
        Generate a cache key for the async Redis client based on connection parameters.
        This ensures different Redis configurations use different cached clients.
        T)	sort_keysN   zasync-redis-client-)	sortedry   itemsjsondumpshashlibsha256encode	hexdigest)r=   sorted_kwargs
kwargs_strkwargs_hashs       r/   _get_async_client_cache_keyz&RedisCache._get_async_client_cache_key<  sa     t006689ZZ>
nnZ%6%6%89CCEcrJ$[M22r?   c                 D   ddl m} ddlm}m} | j                         }|j                  |      }|t        t        t        t        f   |      }nH |di | j                  | _         |dd| j                  i| j                  }|j                  ||       || _        |S )	Nr   )in_memory_llm_clients_cacherf   )get_redis_async_clientrh   keyconnection_pool)r   valuerR   )r~   r   rr   r   rh   r   	get_cacher
   r	   async_redis_clientasync_redis_cluster_clientry   rz   	set_cacherx   )r=   r   r   rh   	cache_keycached_clientrx   s          r/   init_async_clientzRedisCache.init_async_clientH  s     	8N446	3==)=L$!%(*DDE}"
 *C)WTEVEV)WD&!7 " $ : :">B>O>O" (11%7 2  #5!!r?   r   c                 x    | j                   -|j                  | j                         s| j                   dz   |z   }|S )zD
        Make sure each key starts with the given namespace
        :)ra   
startswithr=   r   s     r/   check_and_fix_namespacez"RedisCache.check_and_fix_namespaceb  s5     >>%cnnT^^.L..3&,C
r?   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)
        rn   .r   )	ro   r   r   striprP   splitfloat
ValueErrorAttributeError)r=   version_strmajor_versions      r/   _parse_redis_major_versionz%RedisCache._parse_redis_major_versionk  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=r   namer   exzset_cache <- r   r   r   r   r   z<litellm.caching.caching: set() - Got exception from REDIS : rR   )get_ttlr   ro   r   rC   rw   setr   rl   service_success_hookr   r   r0   r)   )	r=   r   r   rW   ttlr   r   	_durationr   s	            r/   r   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?r   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)rw   rC   r   incrrl   r   r   r   r0   r   expirer)   r   r   r   )r=   r   r   r   rW   _redis_clientr   set_ttlrX   r   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   )rC   r   r   r   r   r   r'   lenr   r   rl   async_service_success_hookr   r   r0   r)   r   )
r=   r   r   r   keysr   r   r   r   r   s
             r/   async_scan_iterzRedisCache.async_scan_iter  su    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   rV   r   c                 J   K    j                   t        |       g| | S wN)evalshar   )r   rV   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)
r   r   r   r   r   r   r   r)   r   r   )r=   r   r   r   r   r   s       @@r/   async_register_scriptz RedisCache.async_register_script  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=%sr   nxFSet ASYNC Redis Cache: key: r   r   r   z3Redis client cannot set cache. Attribute not found.)r   r   r   r   z)Successfully Set ASYNC Redis Cache: key: r   r   r   r   r   r   r   event_metadatar   r   r   r   r   r   r   r   rR   )redis.asyncior   rC   r   r)   r   r   rl   r   r   r   r   r0   r   r   r   r   r   rs   r   r   r   r   r   r   )r=   r   r   rW   r   r   r   r   r   r   r   r   rX   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   r   z%Set ASYNC Redis Cache PIPELINE: key: r   r   Nsecondsr   )r   r   r   r   r   r   r   execute)	r=   r  r  r   r   cache_valuejson_cache_value_tdresultss	            r/   _pipeline_helperzRedisCache._pipeline_helperv  s      llsl#&0 	"I{444CI7	{(;-W]^a]bc  $zz+6'+C,HH&  	  & '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   r   rC   r   ro   pipeliner  r   r   rl   r   r   r   r0   r   r)   r   r   r   r   )r=   r  r   rW   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	
  (	$--%-@ M MD $ 5 5dJ LLM M .wi89 yy{H :-I''BB(..& <=Q=S<TU)%%Fv%N C 	 %MLM M M M&  	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rw   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=   rw   r   r   r   r  s         r/   _set_cache_sadd_helperz!RedisCache._set_cache_sadd_helper  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   r   r   r   r   )rw   r   r   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   rC   r   r)   r   r   rl   r   r   r   r   r0   r   r   r   r   r   r  r   )r=   r   r   r   rW   r   r   r   r   r   r   s              r/   async_set_cache_saddzRedisCache.async_set_cache_sadd  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=r   )r   r   r{   r   r'   r`   flush_cache_buffer)r=   r   r   rW   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   r   r   r   zasync_increment <- r  r  z^LiteLLM Redis Caching: async async_increment() - Got exception from REDIS %s, Writing value=%s)r  r   r   rC   r   r   incrbyfloatr   r   r   r   rl   r   r   r   r0   r)   r   r   r   r   )r=   r   r   r   r   r   r   r   	_used_ttlrX   r   r   r   r   s                 r/   async_incrementzRedisCache.async_increment4  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   r{   r  rD   s    r/   r  zRedisCache.flush_cache_bufferp  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_logicw  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)	Nr   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: )r   r   rC   rw   rs   rl   r   r   r   r0   r*  r)   r   r   )	r=   r   r   rW   r   r#  r   r   r   s	            r/   r   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   )rw   mget)r=   r   s     r/   _run_redis_mget_operationz$RedisCache._run_redis_mget_operation  s       %%4%00r?   c                 b   K   | j                         }|j                  |       d{   S 7 w)r/  r0  N)r   r1  )r=   r   r   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 r   r0  zbatch_get_cache <- r  r%  z$Error occurred in batch get cache - )r   r'   rC   r2  rl   r   r   r   r0   dictzipr   rt   bytesr&  r*  r)   r   r   r   )r=   r5  r   key_value_dictr   	_key_list_keysr   r   r  r   r   decoded_resultskvr   s                   r/   batch_get_cachezRedisCache.batch_get_cache  su    $,@SS@	@ 	"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   r   zGet Async Redis Cache: key: zGot Async Redis Cache: key: r,  r-  zasync_get_cache <- r   r   r  zAlitellm.caching.caching: async get() - Got exception from REDIS: )r  r   r   r   rC   r   rs   r*  r   r   rl   r   r   r   r0   r)   r   r   )r=   r   r   rW   r   r   r   r#  responser   r   r   s               r/   async_get_cachezRedisCache.async_get_cache  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.
        Nr   r0  zasync_batch_get_cache <- r  r%  r  z*Error occurred in async batch get cache - )rC   r   r'   r4  r   r   rl   r   r   r   r0   r8  r9  r   rt   r:  r&  r*  r)   r   r   r   r   )r=   r5  r   r;  r   r   r<  r=  r   r  r   r   r>  r?  r@  r   s                   r/   async_batch_get_cachez RedisCache.async_batch_get_cache  s    & YY[
$,@SS@	@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   7LiteLLM Redis Cache PING: - Got exception from REDIS : N)r   rC   rw   r   rl   r   r   r   r0   r)   service_failure_hookr   r   r   )r=   r   rC  r   r   r   s         r/   	sync_pingzRedisCache.sync_pinga  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   rH  )r   rC   r   r   r   r   rl   r   r   r   r0   r)   r   r   r   r   )r=   r   r   rC  r   r   r   s          r/   r   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   r   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   )rw   client_list)r=   rR  s     r/   rR  zRedisCache.client_list  s     --99;r?   c                 :    | j                   j                         }|S r   )rw   rJ   )r=   rJ   s     r/   rJ   zRedisCache.info  s      %%'r?   c                 8    | j                   j                          y r   rw   flushallrD   s    r/   flush_cachezRedisCache.flush_cache      ""$r?   c                 8    | j                   j                          y r   rU  rD   s    r/   rV  zRedisCache.flushall  rX  r?   c                    K   | j                   j                  d       d {    	 | j                  j                          y 7  # t        $ r }t        j                  d|       Y d }~y d }~ww xY ww)NT)inuse_connectionsz#Error closing sync Redis client: %s)rz   
disconnectrw   closer)   r   r   )r=   r   s     r/   r\  zRedisCache.disconnect  sh     ((33d3KKK	K##% 	L  	K  !FJJ	Ks8    A1AA1A A1	A.A)$A1)A..A1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)aQ  
        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`  ra  r   rR   )
r  r   r   ry   r   acloser)   r   r   r   )r=   redis_asyncrw   ping_resultr   s        r/   test_connectionzRedisCache.test_connection  s     	/ -;,,At/@/@AL !- 1 1 33K %%''''A 
 #+7RSS 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   rN  )r=   r   r   s      r/   async_delete_cachezRedisCache.async_delete_cache  s-      "335"))#....s   %.,.c                 :    | j                   j                  |       y r   )rw   rO  r   s     r/   delete_cachezRedisCache.delete_cache  s      %r?   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 operationsr   r   z+Increment ASYNC Redis Cache PIPELINE: key: r   increment_valuer   r   Nr  z/Increment ASYNC Redis Cache PIPELINE: results: )
r   r   r  r   r   r	  r   r   rt   r   )r=   r  rk  increment_opr   r  r  rs           r/   _pipeline_increment_helperz%RedisCache._pipeline_increment_helper  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	
 #;ajE&:;; '
 <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   r   rC   r   r  rp  r   r   rl   r   r   r   r0   r   r)   r   r   r   r   )r=   rk  rW   r   r   r   r  r  r   r   r   s              r/   async_increment_pipelinez#RedisCache.async_increment_pipeline  s     ~!#'#557YY[
D^DTU	
%	$--%-@ V VD $ ? ?n UUV V yy{H :-I''BB(..& <=Q=S<TU)%%Fv%N C 	 N!VUV V V V"  	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: )r   r   r)   r   r   )r=   r   r   r   r   s        r/   async_get_ttlzRedisCache.async_get_ttlL  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 <- rL  r   z8LiteLLM Redis Cache RPUSH: - Got exception from REDIS : )r   rC   rpushr   r   rl   r   r   r   r0   r)   r   r   r   r   )r=   r   ru  r   rW   r   r   rC  r   r   r   s              r/   async_rpushzRedisCache.async_rpushd  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
rpush_listc                    K   |D ]  } |j                   |d   g|d      |j                          d{   }|D ]  }t        |t              s| |S 7 w)z-Helper function for pipeline rpush operationsr   ru  N)rw  r	  rt   r)   )r=   r  ry  rpush_opr  ro  s         r/   _pipeline_rpush_helperz!RedisCache._pipeline_rpush_helper  sk      # 	=HDJJx<();<	=& 	A!Y'	  's   4AAAAc                 *  K   t        |      dk(  rg S | j                         }t        j                         }	 |j                  d      4 d{   }| j	                  ||       d{   }ddd      d{    t        j                         }||z
  }t        j                  | j                  j                  t        j                  |dt                             S 7 7 {7 m# 1 d{  7  sw Y   }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)	a!  
        Use Redis Pipelines for bulk RPUSH operations

        Args:
            rpush_list: List of RedisPipelineRpushOperation dicts containing:
                - key: str
                - values: List[Any]

        Returns:
            List[int]: List lengths after each push
        r   Fr  Nzasync_rpush_pipeline <- rL  r   zKLiteLLM Redis Caching: async_rpush_pipeline() - Got exception from REDIS %s)r   r   rC   r  r|  r   r   rl   r   r   r   r0   r)   r   r   r   r   )	r=   ry  r   r   r  r  r   r   r   s	            r/   async_rpush_pipelinezRedisCache.async_rpush_pipeline  s      z?aI!335YY[
	$--%-@ N ND $ ; ;D* MMN N yy{H :-I''BB(..& 89M9O8PQ C  NNMN N N N  	yy{H :-I''BB(..& 89M9O8PQ	 C    ]A G!	   5FC= C"C= C((C$)C(-C= 8C&9A(C= !F"C= $C(&C= (C:.C1/C:6C= =	FBFFFc                    K   g }t        |      D ]F  }|j                  |       |j                          d {   }|D ]  }||j                  |        H |S 7 #wr   )r$   lpopr	  r'   )r=   r  r   r   rX   r-   r  ro  s           r/   *handle_lpop_count_for_older_redis_versionsz5RedisCache.handle_lpop_count_for_older_redis_versions  sg      !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 <- rL  r%  c              3   <   K   | ]  }t        |t                y wr   )rt   r:  ).0items     r/   	<genexpr>z(RedisCache.async_lpop.<locals>.<genexpr>  s      2,0
4'2s   r   z7LiteLLM Redis Cache LPOP: - Got exception from REDIS : )r   rC   r   r   r  r  r  r   r   rl   r   r   r   r0   rt   r:  r&  r)   listallr   r   r   r   )r=   r   r   r   rW   r   r   r   r  rX   r   r   r  r   s                 r/   
async_lpopzRedisCache.async_lpop  s_     "335YY[
3C5	%IJ6	 ;;=M ]Q%6(11e1D  #'#R#Rc5$ F    -11#u== yy{H :-I''BB(..& ./C/E.FG C  &%("!==11 FD)c 24:2 /"=CDTDKK0DD MA    >" ! "!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	lpop_listc           
      |  K   | j                         }|dk\  r8|D ]  }|j                  |d   |d           |j                          d{   }ng }|D ]@  }|d   xs d}|j                  |       t	        |      D ]  }|j                  |d           B |j                          d{   }	g }d}
|D ]4  }|	|
|
|z    D cg c]  }||	 }}|j                  |r|nd       |
|z  }
6 |D ]  }t        |t              s| g }|D ]  }||j                  d       t        |t              rH	 |j                  |D cg c]'  }|#t        |t              r|j                  d      n|) c}xs d       o|j                  d        |S 7 C7 c c}w c c}w # t        $ r |j                  |       Y w xY ww)zHelper function for pipeline lpop operations.

        For Redis >= 7, queues one LPOP(key, count) per operation.
        For Redis < 7, queues `count` individual LPOP(key) commands per operation.
        r  r   r   Nr   r   r%  )
r   r  r	  r'   r$   rt   r)   r  r:  r&  )r=   r  r  r   lpop_opraw_resultscountsr   r-   flat_resultsoffsetro  key_resultsr>  r  s                  r/   _pipeline_lpop_helperz RedisCache._pipeline_lpop_helper0  s	     779A$ <		'%.''*:;< $.K !#F$ .(-Ae$u .AIIgen-..
 "&/L KF  +FVe^DA  ""+;4H%   	A!Y'	
 68 	-Ay&&t,At$
.#** )* $#/ 5?tU4KDKK0QUU  
    &&t,!	-" ] / 0& ! .#**1-.sy   AF<
FAF<*F+F<F
F3F<.F<1F ,F
,F7F<F<F<FF96F<8F99F<c                 *  K   t        |      dk(  rg S | j                         }t        j                         }	 |j                  d      4 d{   }| j	                  ||       d{   }ddd      d{    t        j                         }||z
  }t        j                  | j                  j                  t        j                  |dt                             S 7 7 {7 m# 1 d{  7  sw Y   }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)	aC  
        Use Redis Pipelines for bulk LPOP operations

        Args:
            lpop_list: List of RedisPipelineLpopOperation dicts containing:
                - key: str
                - count: Optional[int]

        Returns:
            List[Optional[List[str]]]: Decoded results per key, None if key was empty
        r   Fr  Nzasync_lpop_pipeline <- rL  r   zJLiteLLM Redis Caching: async_lpop_pipeline() - Got exception from REDIS %s)r   r   rC   r  r  r   r   rl   r   r   r   r0   r)   r   r   r   r   )	r=   r  r   r   r  r  r   r   r   s	            r/   async_lpop_pipelinezRedisCache.async_lpop_pipelineo  s      y>QI!335YY[
	$--%-@ L LD $ : :4 KKL L yy{H :-I''BB(..& 78L8N7OP C  NLKL L L L  	yy{H :-I''BB(..& 78L8N7OP	 C    \A G!	r  )NNNrm   NNg      @r   )rm   )NN)JrL   rM   rN   r   rP   r   r   r   r>   r}   r)   r   r   r   r	   r   r   r   r   r   r   r   r]   r  r   r   r   r  r  cluster_pipeliner   r  r  r  r  r  r   r!  r  r*  r   r2  r4  r8  rA  rD  rF  rQ   rJ  r   rP  rR  rJ   rW  rV  r\  rf  rh  rj  r   rp  rr  rt  rx  r   r|  r~  r:  r  r  r   r  r  __classcell__)r   s   @r/   r_   r_      s9   
 *-#'(,*-D
 #3-D C=D  ~D !DL,6) " "
3S 
3"	!#==	>"43 3 /C /:2 7;77$,UO7	7r ",S , ,t , ",\C C < "M "M^H../ sCx) e_	
 
< "HL9uS#X/96>uo9 "9v(  	
 e_ 
" "FF%-e_F "FP ", ", "
 "+/9 9 c]	9
 #4.9 
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"h "6:0%-d^0 "0d " ,0E"S	4#667E" #4.E" 
	E" "E"N"4 "H"D "H "* "*T %%K#t #J "/C / "/&<< <=< 
$u+		<0 "="#BC=	$u+	= "=~ "s x}  ". "
 ,0	11 S	1 #4.	1 
1 "1f 45 
c	 "4454 
c4 "4l#&/2	e "  $+/	@@ }@ #4.	@ 
sDI~	@ "@D== 23= 
htCy!	"	=~ "4234 
htCy!	"4 "4r?   r_   )rf   ):rO   r(  r   r[   r   r!   r   rC   datetimer   typingr   r   r   r   r   r	   r
   r~   litellm._loggingr   r   litellm.constantsr   r   r   'litellm.litellm_core_utils.core_helpersr   ,litellm.litellm_core_utils.coroutine_checkerr   litellm.types.cachingr   r   r   litellm.types.servicesr   
base_cacher   opentelemetry.tracer   _Spanr  r   r   redis.asyncio.clientr   redis.asyncio.clusterr   r  r  r   r   rP   r   r0   r2   r]   r_   rR   r?   r/   <module>r     s            I I I  : 
 V J 
 0 !11-5H&!-DH!$D$S $ $N:" :"z0n nr?   