
    hQ@                         d 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 erddl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 erddlmZ eeef   ZneZddlmZ  G d de      Z G d de      Zy)z
Dual Cache implementation - Class to update both Redis and an in-memory cache simultaneously.

Has 4 primary methods:
    - set_cache
    - get_cache
    - async_set_cache
    - async_get_cache
    N)ThreadPoolExecutor)TYPE_CHECKINGAnyListOptionalUnion)RedisPipelineIncrementOperation)print_verboseverbose_logger   )	BaseCache)InMemoryCache)
RedisCache)Span)OrderedDictc                   .     e Zd Zdd fd
Z fdZ xZS )LimitedSizeOrderedDictd   max_sizec                2    t        |   |i | || _        y N)super__init__r   )selfr   argskwargs	__class__s       V/var/www/Befach/backend/env/lib/python3.12/site-packages/litellm/caching/dual_cache.pyr   zLimitedSizeOrderedDict.__init__&   s    $)&)     c                 z    t        |       | j                  k\  r| j                  d       t        |   ||       y )NF)last)lenr   popitemr   __setitem__)r   keyvaluer   s      r   r%   z"LimitedSizeOrderedDict.__setitem__*   s0    t9%LLeL$C'r    )__name__
__module____qualname__r   r%   __classcell__r   s   @r   r   r   %   s    '* !( (r    r   c                       e Zd ZdZ	 	 	 	 	 	 d&dee   dee   dee   dee   dee   ded	df fd
Z	dee   dee   fdZ
d'defdZ	 d'deded	efdZ	 	 d(dee   defdZ	 	 d(dedee   defdZ	 	 d(dee   defdZdedee   dee   d	ee   fdZ	 	 d(dedee   defdZd'defdZ	 d'dedefdZ	 	 d(dedee   ded	efdZ	 	 d)ded   dedee   d	eee      fdZ	 d'deded	dfd Zd! Zd" Zd#efd$Zd#ed	ee   fd%Z  xZ!S )*	DualCachea5  
    DualCache is a cache implementation that updates both Redis and an in-memory cache simultaneously.
    When data is updated or inserted, it is written to both the in-memory cache + Redis.
    This ensures that even if Redis hasn't been updated yet, the in-memory cache reflects the most recent data.
    Nin_memory_cacheredis_cachedefault_in_memory_ttldefault_redis_ttl default_redis_batch_cache_expiry"default_max_redis_batch_cache_sizereturnc                    t         |           |xs
 t               | _        || _        t        |      | _        |xs t        j                  xs d| _	        |xs t        j                  | _
        |xs t        j                  | _        y )Nr   
   )r   r   r   r/   r0   r   last_redis_batch_access_timelitellmr3   redis_batch_cache_expiryr1   r2   )r   r/   r0   r1   r2   r3   r4   r   s          r   r   zDualCache.__init__8   s     	.A-/&,B7-
) - 77 	% "BW%B%B 	" "3!Og6O6Or    c                 *    ||| _         ||| _        y y r   )r1   r2   )r   r1   r2   s      r   update_cache_ttlzDualCache.update_cache_ttlS   s%     !,)>D&(%6D" )r    
local_onlyc                 :   	 | j                   =d|vr| j                  | j                  |d<    | j                   j                  ||fi | | j                  $|du r | j                  j                  ||fi | y y y # t        $ r}t        |       Y d }~y d }~ww xY w)NttlF)r/   r1   	set_cacher0   	Exceptionr
   r   r&   r'   r=   r   es         r   r@   zDualCache.set_cache\   s    
	##/&4+E+E+Q$($>$>F5M.$$..sEDVD+
e0C*  **3@@ 1D+ 	!	s   A7A< <	BBBr'   c                 $   	 |}| j                    | j                   j                  ||fi |}| j                  "|du r | j                  j                  ||fi |}|S # t        $ r(}t	        j
                  dt        |              |d}~ww xY w)z
        Key - the key in cache

        Value - int - the value you want to increment by

        Returns - int - the incremented value
        NF)LiteLLM Cache: Excepton async add_cache: )r/   increment_cacher0   rA   r   errorstr)r   r&   r'   r=   r   resultrC   s          r   rF   zDualCache.increment_cachej   s    	F##/=--==c5SFS+
e0C9))99#uOOM 	  #LSQRVH!UVG	s   AA 	B'#B

Bparent_otel_spanc                    	 d }| j                   ! | j                   j                  |fi |}||}|O| j                  C|du r?| j                  j                  ||      }| | j                   j                  ||fi | |}t	        d|        |S # t
        $ r* t        j                  t        j                                Y y w xY w)NFrJ   get cache: cache result: )
r/   	get_cacher0   r@   r
   rA   r   rG   	traceback
format_excr   r&   rJ   r=   r   rI   in_memory_resultredis_results           r   rN   zDualCache.get_cache   s    	9F##/#A4#7#7#A#A##P#P #/-F~$"2"2">:QVCV#//99*:  :    +2D((223OO%5fX>?M 	9  !5!5!78	9s   BB 0CCkeysc                 $   	 t               		j                  d       	 fd}	 t        j                         }t	        d      5 }|j                  |      }|j                         cd d d        S # 1 sw Y   y xY w# t        $ r
  |       cY S w xY w)Nr   c                  8   t        j                         } 	 t        j                  |        | j                   j                  di       | j                          t        j                  d       S # | j                          t        j                  d       w xY w)z9Run the coroutine in a new event loop within this thread.N )asyncionew_event_loopset_event_looprun_until_completeasync_batch_get_cacheclose)new_loopreceived_argsr   s    r   run_in_new_loopz2DualCache.batch_get_cache.<locals>.run_in_new_loop   s{    --/H-&&x022.D..??  &&t,  &&t,s   5A2 2'Br   )max_workers)localspoprX   get_running_loopr   submitrI   RuntimeError)
r   rT   rJ   r=   r   r`   _executorfuturer_   s
   `        @r   batch_get_cachezDualCache.batch_get_cache   s     &!
	-	%((*A $2 'h!9}}' ' '  	%"$$	%s/    A< !A0&	A< 0A95A< 9A< <BBc                   K   	 t        d| d|        d }| j                  7 | j                  j                  |fi | d {   }t        d|        ||}|_| j                  S|du rO| j                  j                  ||       d {   }|& | j                  j                  ||fi | d {    |}t        d|        |S 7 7 @7 # t
        $ r* t        j                  t        j                                Y y w xY ww)Nzasync get cache: cache key: ; local_only: zin_memory_result: FrL   rM   )
r
   r/   async_get_cacher0   async_set_cacherA   r   rG   rO   rP   rQ   s           r   rm   zDualCache.async_get_cache   sF    	9.se>*N F##/)M)=)=)M)M*!* $   23C2DEF#/-F~$"2"2">:QVCV%)%5%5%E%E*: &F &    +>$..>>\-3   &5fX>?M/$   	9  !5!5!78	9s_   D?C CAC C'C 4C5C 
DC C C 0DDDDcurrent_timerI   c                     g }t        ||      D ]G  \  }}|	|| j                  vs || j                  |   z
  | j                  k\  s7|j                  |       I |S r   )zipr8   r:   append)r   ro   rT   rI   sublist_keysr&   r'   s          r   get_redis_batch_keyszDualCache.get_redis_batch_keys   sj     dF+JC}t@@@#d&G&G&LL445 !'', , r    c                 "  K   	 t        t        |            D cg c]  }d  }}| j                  ) | j                  j                  |fi | d {   }||}d |v r| j                  |du r	 t        j
                         }| j                  |||      }	t        |	      dkD  r| j                  j                  |	|       d {   }
|
R|
j                         D ]?  \  }}|) | j                  j                  ||
|   fi | d {    || j                  |<   A |
j                         D ]  \  }}|j                  |      }|||<    |S c c}w 7 7 7 O# t        $ r* t        j                  t        j                                Y y w xY ww)NFr   rL   )ranger#   r/   r\   r0   timert   itemsrn   r8   indexrA   r   rG   rO   rP   )r   rT   rJ   r=   r   rg   rI   rR   ro   rs   rS   r&   r'   ry   s                 r   r\   zDualCache.async_batch_get_cache   s    )	9$)#d)$45qd5F5##/)S)=)=)S)S*"* $  $/-Fv~$"2"2">:QVCV  $yy{#88tVT |$q()-)9)9)O)O$7G *P * $L $/*6*<*<*>JC$0&Jd&:&:&J&J$'c):'">D'" !" !" FRD==cB +? '3&8&8&:
U $

3(-u '; MM 6$$$!"  	9  !5!5!78	9sk   FE 	E.E EA2E EAE EAE FE E E 0F	FFFc                   K   t        d| d| d|        	 | j                  & | j                  j                  ||fi | d {    | j                  ,|du r' | j                  j                  ||fi | d {    y y y 7 =7 	# t        $ r+}t        j                  dt        |              Y d }~y d }~ww xY ww)Nzasync set cache: cache key: rl   z	; value: FrE   )r
   r/   rn   r0   rA   r   	exceptionrH   rB   s         r   rn   zDualCache.async_set_cache1  s     *3%~j\SXRYZ	
		##/:d**::3PPPP+
e0C6d&&66sELVLLL 1D+ Q M 	$$;CF8D 	sR   B>-B B5B ;B<B  B>B B 	B;!B61B>6B;;B>
cache_listc                   K   t        d| d|        	 | j                  & | j                  j                  d	d|i| d{    | j                  =|du r8 | j                  j                  d	||j	                  dd      d| d{    yyy7 N7 	# t
        $ r+}t        j                  dt        |              Y d}~yd}~ww xY ww)
z1
        Batch write values to the cache
        z#async batch set cache: cache keys: rl   Nr|   Fr?   )r|   r?   rE   rW   )	r
   r/   async_set_cache_pipeliner0   rc   rA   r   r{   rH   )r   r|   r=   r   rC   s        r   r~   z"DualCache.async_set_cache_pipelineA  s      	1*^J<X	
	##/Cd**CC )-3   +
e0C?d&&?? )vzz%/FJP   1D+	
  	$$;CF8D 	sS   C-B BAB 	B
B CB B 	C	!C?CC		Cc           	      4  K   	 |}| j                   & | j                   j                  ||fi | d{   }| j                  ;|du r7| j                  j                  ||||j                  dd             d{   }|S 7 M7 # t        $ r}|d}~ww xY ww)z
        Key - the key in cache

        Value - float - the value you want to increment by

        Returns - float - the incremented value
        NFr?   )rJ   r?   )r/   async_incrementr0   getrA   )r   r&   r'   rJ   r=   r   rI   rC   s           r   async_increment_cachezDualCache.async_increment_cacheY  s     	!F##/Ct33CC "(   +
e0C#//??%5

5$/	  @    M
  	G	sK   B/B BAB :B;B  BB B 	BBBBincrement_listr	   c                   K   	 d }| j                   %| j                   j                  ||       d {   }| j                  )|du r%| j                  j                  ||       d {   }|S 7 ;7 # t        $ r}|d }~ww xY ww)N)r   rJ   F)r/   async_increment_pipeliner0   rA   )r   r   r=   rJ   r   rI   rC   s          r   async_increment_cache_pipelinez(DualCache.async_increment_cache_pipeline{  s     	,0F##/#33LL#1%5  M   
 +
e0C#//HH#1%5  I   
 M  	G	sJ   B.A2 A.4A2 'A0(A2 -B.A2 0A2 2	B;A==BBc                 L  K   	 | j                   6| j                   j                  |||j                  dd             d{   }| j                  :|du r6| j                  j                  |||j                  dd             d{   }y7 K7 # t        $ r}|d}~ww xY ww)z
        Add value to a set

        Key - the key in cache

        Value - str - the value you want to add to the set

        Returns - None
        Nr?   )r?   F)r/   async_set_cache_saddr   r0   rA   )r   r&   r'   r=   r   rg   rC   s          r   r   zDualCache.async_set_cache_sadd  s     	##/..CCFJJud$; D   +
e0C**??FJJud$; @   

  	G	sM   B$=B BAB BB B$B B 	B!BB!!B$c                     | j                   | j                   j                          | j                  | j                  j                          y y r   )r/   flush_cacher0   )r   s    r   r   zDualCache.flush_cache  sC    +  ,,.'((* (r    c                     | j                   | j                   j                  |       | j                  | j                  j                  |       yyz-
        Delete a key from the cache
        N)r/   delete_cacher0   r   r&   s     r   r   zDualCache.delete_cache  sI     +  --c2'))#. (r    r&   c                    K   | j                   | j                   j                  |       | j                  $| j                  j                  |       d{    yy7 wr   )r/   r   r0   async_delete_cacher   s     r   r   zDualCache.async_delete_cache  sV      +  --c2'""55c::: (:s   AAAAc                    K   | j                   j                  |       d{   }|/| j                  #| j                  j                  |       d{   }|S 7 77 w)zL
        Get the remaining TTL of a key in in-memory cache or redis
        N)r/   async_get_ttlr0   )r   r&   r?   s      r   r   zDualCache.async_get_ttl  sX      ((66s;;;4++7((66s;;C
 <;s!   AA0AAAA)NNNNNr   )F)NF)FN)"r(   r)   r*   __doc__r   r   r   floatintr   r<   boolr@   rF   r   rN   listrj   rm   r   rH   r   rt   r\   rn   r~   r   r   r   r   r   r   r   r+   r,   s   @r   r.   r.   1   s    48,015-1<@25P!-0P j)P  (	P
 $E?P +35/P -0P 
P67%-e_7IQRW7  38+/	4 ,0 	9 #4.9 	9H ,0 	!%!% #4.!% 	!%L ,0 	'9 #4.'9 	'9R 3i S		
 
c( ,0 	0909 #4.09 	09dD " 49,08 ,0     #4.	 
   
 J !+/	>?  #4.	 
$u+	4 49,0	6+/;C ;s x} r    r.   )r   rX   rw   rO   concurrent.futuresr   typingr   r   r   r   r   litellm.types.cachingr	   r9   litellm._loggingr
   r   
base_cacher   r/   r   r0   r   opentelemetry.tracer   _Spancollectionsr   r   r.   rW   r    r   <module>r      si       1 < <E  : ! * #1DD #	([ 	(]	 ]r    