
    i+                         d Z ddlZddlZddl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 ddlmZ  ej                   e      Z G d d      Z G d	 d
      Z e       Zy)uy   
Gestor de sesiones basado en Redis para persistencia y escalabilidad.
Reemplaza la implementación anterior en memoria.
    N)DictAnyOptional)datetime)messages_to_dictmessages_from_dict)settingsc                   ,    e Zd ZdZddedeeef   fdZy)SessionDatau   
    Datos de una sesión de cliente (DTO).
    Ahora es puramente datos, la lógica de lock se maneja externamente o en el manager.
    Nuuid_conversationstatec           
      H    || _         |g g d d d d d d d d	| _        y || _        y )N)	messagesmissing_fieldsintentcustomer_id
product_idcategorybrandlast_tool_resulterror)r   r   )selfr   r   s      v/home/jorge/Escritorio/TWS/DESARRROLLO TWS/PROYECTOS/0_PRO_MARCI/LHIA/python/lhiav3-marci-agent/api/session_manager.py__init__zSessionData.__init__   s<    !2="$#" $(
DJ DJ    N)__name__
__module____qualname____doc__strr   r   r    r   r   r   r      s"    # d38n r   r   c                       e Zd ZdZd Zd Zdedej                  fdZ	dede
fdZdede
fd	Zdedefd
ZdefdZd Zy)RedisSessionManagerz6
    Gestor de sesiones persistente usando Redis.
    c                    t        t        j                  t        j                  t        j                  xs d t        j
                  dddddg 
      | _        t        j                  r-d| j                  d<   d| j                  d<   d| j                  d<   t        j                  di | j                  | _
        t        j                  | _        t        j                  d	t        j                   d
t        j                   dt        j
                   dt        j                          i | _        t!        j"                         | _        y )NT   F)
hostportpassworddbdecode_responsessocket_timeoutsocket_connect_timeoutsocket_keepaliveretry_on_timeoutretry_on_errorsslnonessl_cert_reqsssl_check_hostnameu   🔌 Redis configurado: :z db=z ssl=r"   )dictr	   
REDIS_HOST
REDIS_PORTREDIS_PASSWORDREDIS_DB_redis_kwargs	REDIS_SSLredisRedisclientREDIS_SESSION_TTLttlloggerinfo_local_locksasyncioLock_lock_cleaner_lockr   s    r   r   zRedisSessionManager.__init__+   s   -1$$$$,,4  !#$!".
 (,Du%28D/7<D34kk7D$6$67--&x':':&;1X=P=P<Q R##$E(*<*<)=?	
 68"),,.r   c                    	 t        j                         j                  | j                  j	                                t        j                  di | j                  | _        t        j                  d       y# t
        $ r Y Ew xY w)zDRecrea el cliente Redis para limpiar el pool de conexiones corrupto.u.   ♻️  Cliente Redis recreado (pool limpiado)Nr"   )rE   get_event_loopcreate_taskr?   aclose	Exceptionr=   r>   r;   rB   rC   rH   s    r   _recreate_clientz$RedisSessionManager._recreate_clientG   sg    	""$001C1C1EF kk7D$6$67DE  		s   ;A7 7	BBr   returnc                 ~    || j                   vr!t        j                         | j                   |<   | j                   |   S )z&Obtiene el lock local para un cliente.)rD   rE   rF   )r   r   s     r   get_lockzRedisSessionManager.get_lockP   s9    D$5$553:<<>D/0  !233r   c           	        K   	 t        j                  | j                  j                  d|       d       d{   }|rBt	        j
                  |      }d|d   v rt        |d   d         |d   d<   t        ||d         S t        j                  d|        t        |      S 7 k# t         j                  t         j                  f$ r>}t        j                  d| d	       | j                          t        |      cY d}~S d}~wt        $ rF}t        j                  d
| dt        |      j                    d|        t        |      cY d}~S d}~ww xY ww)u/   
        Carga la sesión desde Redis.
        session:      @timeoutNr   r   u*   📝 Creando nueva sesión en Redis para: u#   ❌ Timeout cargando sesión Redis     — recreando clienteu!   ❌ Error cargando sesión Redis : )rE   wait_forr?   getjsonloadsr   r   rB   rC   TimeoutErrorCancelledErrorr   rN   rM   typer   )r   r   datasession_dictes        r   get_sessionzRedisSessionManager.get_sessionV   sQ    	2 ))(+<*= >? D #zz$/g!668J<X_K`akKl8mL)*5"#4l76KLLHIZH[\]"#455 $$g&<&<= 	2LL>?P>QQghi!!#011 	2LL<=N<OrRVWXRYRbRbQccefgehij011	2si   E6B( B&AB( E"B( %E&B( (#E3D>E?EE;EEEEEsessionc           	        K   	 |j                   j                         }d|v r|d   rt        |d         |d<   ||t        j                         j                         d}t        j                  | j                  j                  d| | j                  t        j                  |            d       d{    y7 # t        j                  t        j                  f$ r, t        j!                  d| d       | j#                          Y yt$        $ r;}t        j!                  d	| d
t'        |      j(                   d
|        Y d}~yd}~ww xY ww)u-   
        Guarda la sesión en Redis.
        r   )r   r   
updated_atrS   rT   rU   Nu$   ❌ Timeout guardando sesión Redis rW   u"   ❌ Error guardando sesión Redis rX   )r   copyr   r   now	isoformatrE   rY   r?   setexrA   r[   dumpsr]   r^   rB   r   rN   rM   r_   r   )r   r   rd   state_to_saver`   rb   s         r   save_sessionz RedisSessionManager.save_sessionq   s:    	l#MM..0M]*}Z/H,<]:=V,Wj) &7&&lln668D ""!!012HHJJt$
    $$g&<&<= 	$LL?@Q?RRhij!!# 	lLL=>O=PPRSWXYSZScScRddfghfijkk	lsN   EB/B; 3B94B; 8E9B; ;AEE	E1EEEEc                    K   	 | j                   j                  d|        d{    y7 # t        $ r"}t        j	                  d|        Y d}~yd}~ww xY ww)u   Elimina la sesión de Redis.rS   NTu   Error borrando sesión: F)r?   deleterM   rB   r   )r   r   rb   s      r   remove_sessionz"RedisSessionManager.remove_session   s[     	++$$x0A/B%CDDD E 	LL3A378	s6   A!- +- A- 	AAAAAc                    K   d}	 | j                   j                  d      2 3 d{   }|dz  }7 
6 	 |S #  Y |S xY ww)zDCuenta llaves de sesiones activas (Scan). Costoso, usar con cuidado.r   z	session:*N   )r?   	scan_iter)r   count_s      r   get_active_sessions_countz-RedisSessionManager.get_active_sessions_count   sU     	;;00=  a
= 	s,   >6 2026 26 >;>c                 T   K   | j                   j                          d {    y 7 wr   )r?   closerH   s    r   rx   zRedisSessionManager.close   s     kk!!!s   (&(N)r   r   r   r    r   rN   r!   rE   rF   rQ   r   rc   rm   boolrp   intrv   rx   r"   r   r   r$   r$   '   sv    18F4# 4',, 423 2; 26lC l+ l>c d  "r   r$   )r    r[   loggingrE   typingr   r   r   r   redis.asyncior=   langchain_core.messagesr   r   config.settingsr	   	getLoggerr   rB   r   r$   session_managerr"   r   r   <module>r      sZ       & &   H $			8	$ ,}" }"@ &'r   