
    yj!%                     >   d dl mZ d dlmZ d dlm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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 d dlmZ d dlm Z  d dl!m"Z"  ee#          Z$dZ% e             dZ&de'de'de'fdZ(dddede'de)ej*                 de+de"e)ej                          f
dZ, ee%ej-        j.         d e            e           ej/        e%ej-        j0         de&          dede'de'de1e'ef         dz  fd                         Z2dede'd!ej*        dej        fd"Z3	 d'de'd#e1e'e'f         dz  dee4ej                          fd$Z5dede'de'd!ej6        dej        f
d%Z7	 d'de'de'd#e1e'ef         dz  dee4ej8                          fd&Z9dS )(    )	getLogger)Any)NOT_NONE)Selectselect)IntegrityError)AsyncSession)make_transient_to_detached)modelsschemas)cacheget_cache_namespacesafe_cache_delete)settings)get_or_create_workspace)ConflictExceptionResourceNotFoundException)Peer)apply_filter)GetOrCreateResultz.v2:workspace:{workspace_name}:peer:{peer_name}z:lock:v2workspace_name	peer_namereturnc                 ^    t                      dz   t                              | |          z   S )zGenerate cache key for peer.:r   r   )r   PEER_CACHE_KEY_TEMPLATEformatr   s     5/DATA/AppData/hermes/projects/honcho/src/crud/peer.pypeer_cache_keyr       s=     	
	
!
(
() ) 
 
	
    F_retrydbpeersr#   c                  K   t          | t          j                             d{V  d |D             }t          t          j                                      t          j        j        k                                  t          j        j        	                    |                    }| 
                    |           d{V }t          |                                                                          }d |D             }g }	|D ]r}
||
j                 }d}|j        |
j        |j        k    r|j        |
_        d}|j        |
j        |j        k    r|j        |
_        d}|r|	                    |
           sd |D             fd|D             }fd	|D             }	 |                                 4 d{V  |                     |           ddd          d{V  n# 1 d{V swxY w Y   n># t(          $ r1 |rt+          d
|           dt-          | |d           d{V cY S w xY wfd|	|z   D             fd}t/          ||z   t1          |          dk    r|nd          S )a  
    Get an existing list of peers or create new peers if they don't exist.
    Updates existing peers with metadata and configuration if provided.

    Args:
        db: Database session
        workspace_name: Name of the workspace
        peers: List of peer creation schemas
        _retry: Whether to retry the operation

    Returns:
        GetOrCreateResult containing the list of peers and whether any were created

    Raises:
        ConflictException: If we fail to get or create the peers
    nameNc                     g | ]	}|j         
S  r'   .0ps     r   
<listcomp>z'get_or_create_peers.<locals>.<listcomp>>   s    (((Q!&(((r!   c                     i | ]
}|j         |S r*   r'   r+   s     r   
<dictcomp>z'get_or_create_peers.<locals>.<dictcomp>H   s    000Qqvq000r!   FTc                     h | ]	}|j         
S r*   r'   r+   s     r   	<setcomp>z&get_or_create_peers.<locals>.<setcomp>f   s    555af555r!   c                 &    g | ]}|j         v|S r*   r'   )r,   r-   existing_namess     r   r.   z'get_or_create_peers.<locals>.<listcomp>g   s%    HHHQ16+G+Gq+G+G+Gr!   c                 f    g | ]-}t          j        |j        |j        pi |j        pi            .S ))r   r(   
h_metadataconfiguration)r   r   r(   metadatar7   r,   r-   r   s     r   r.   z'get_or_create_peers.<locals>.<listcomp>j   sX         	)z'R//R		
 	
 	
  r!   zUnable to create or get peers: r"   c                 :    g | ]}t          |j                  S r*   )r    r(   r9   s     r   r.   z'get_or_create_peers.<locals>.<listcomp>~   s2     ! ! !34~qv..! ! !r!   c                  @   K   D ]} t          |            d {V  d S N)r   )	cache_key_cache_keys_to_invalidates    r   _invalidate_peer_cachez3get_or_create_peers.<locals>._invalidate_peer_cache   sC      2 	/ 	/I#I..........	/ 	/r!   r   )created	on_commit)r   r   WorkspaceCreater   r   r   wherer   r(   in_executelistscalarsallr8   r6   r7   appendbegin_nestedadd_allr   r   get_or_create_peersr   len)r$   r   r%   r#   
peer_namesstmtresultexisting_peerspeer_schema_mapchanged_peersexisting_peerpeer_schemachangedpeers_to_create	new_peersr?   r>   r4   s    `              @@r   rL   rL   %   s     0 ""g&=>&R&R&R
S
SSSSSSSS((%(((Jv{	v{)^;	<	<	v{##J//	0	0 	
 ::d########F!%fnn&6&6&:&:&<&<!=!=N 10%000O !#M ( 0 0%m&89  ,(K,@@@'2';M$G %1+{/HHH*5*CM'G 	0  /// 65n555NHHHH%HHHO    !  IQ??$$ 	" 	" 	" 	" 	" 	" 	" 	"JJy!!!	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" 	" Q Q Q 	#>*>>  )^U4PPPPPPPPPPPPQ! ! ! !8E	8Q! ! !/ / / / / "I",EO((4   s6   )G= G+G= +
G55G= 8G59G= =8H87H8s)keyttlprefix	condition)rZ   r[   r\   Nc                 d  K   |                      t          t          j                                      t          j        j        |k                                  t          j        j        |k                         d{V }|dS |j        |j        |j        |j        |j	        |j
        |j        dS )zKFetch a peer from the database and return as a plain dict for safe caching.N)idr(   r   r6   internal_metadatar7   
created_at)scalarr   r   r   rC   r   r(   r_   r6   r`   r7   ra   )r$   r   r   objs       r   _fetch_peerrd      s      " 		v{	v{)^;	<	<	v{9,	-	-       C
 {tf,n 2*n  r!   peerc                    K   t          | ||j                   d{V }|t          d|j         d|           t          j        di |}t          |           |                     |d           d{V }|S )a  
    Get an existing peer.

    Args:
        db: Database session
        workspace_name: Name of the workspace
        peer: Peer creation schema

    Returns:
        The peer if found

    Raises:
        ResourceNotFoundException: If the peer does not exist
    NzPeer z not found in workspace F)loadr*   )rd   r(   r   r   r   r
   merge)r$   r   re   datarc   rT   s         r   get_peerrj      s      & R;;;;;;;;D|'GDIGG~GG
 
 	

 +



Cs###((3U(33333333Mr!   filtersc                   K   t          t          j                                      t          j        j        | k              }t          |t          j        |          }|                    t          j        j                  S r<   )r   r   r   rC   r   r   order_byra   )r   rk   rO   s      r   	get_peersrn      sY       &+$$V[%?>%QRRDfk733D==/000r!   c                   K   t          | |t          j        |          g           d{V }|j        d         }d}|j        |j        |j        k    r|j        |_        d}|j        |j        |j        k    r|j        |_        d}|sR|                                  d{V  |                                 d{V  t          
                    d||           |S |                                  d{V  |                                 d{V  t          ||j                  }t          |           d{V  t          
                    d|           |S )a#  
    Get or create a peer, then apply metadata and configuration updates.

    If the peer does not exist, the workspace and peer are created first.
    Provided metadata and configuration replace the existing values when
    present.

    Args:
        db: Database session
        workspace_name: Name of the workspace
        peer_name: Name of the peer
        peer: Peer update schema

    Returns:
        The updated peer

    Raises:
        ConflictException: If concurrent creation prevents fetching or creating
            the peer
    r'   Nr   FTz2Peer %s unchanged in workspace %s, skipping updatezPeer %s updated successfully)rL   r   
PeerCreateresourcer8   r6   r7   commitpost_commitloggerdebugr    r(   r   )r$   r   r   re   peers_resulthoncho_peerneeds_updater=   s           r   update_peerry      s     . -
NW/Y???@       L '*KL} [%;t}%L%L!% 	&%);;;$($6!  iikk&&(((((((((@	
 	
 	

 
))++

"
"
$
$$$$$$$$~{/?@@I
I
&
&&&&&&&&
LL/;;;r!   c                   K   t          t          j                                      t          j        t          j        j        t          j        j        k    t          j        j        t          j        j        k    z                                t          j        j	        |k                                  t          j        j        | k              }t          |t          j        |          }|                    t          j        j                  }|S )a	  
    Get all sessions for a peer through the session_peers relationship.

    Args:
        workspace_name: Name of the workspace
        peer_name: Name of the peer
        filters: Filter sessions by metadata

    Returns:
        SQLAlchemy Select statement
    )r   r   SessionjoinSessionPeerr(   session_namer   rC   r   r   rm   ra   )r   r   rk   rO   s       r   get_sessions_for_peerr     s      " 	v~	^ F$6$CC~,0B0QQS

 


 
v!+y8	9	9	v~,>	?	? 	 fng66D*.--8Q*R*RDKr!   r<   ):loggingr   typingr   cashewsr   
sqlalchemyr   r   sqlalchemy.excr   sqlalchemy.ext.asyncior	   sqlalchemy.ormr
   srcr   r   src.cache.clientr   r   r   
src.configr   src.crud.workspacer   src.exceptionsr   r   
src.modelsr   src.utils.filterr   src.utils.typesr   __name__rt   r   PEER_LOCK_PREFIXstrr    rF   rp   boolrL   CACHEDEFAULT_TTL_SECONDSlockedDEFAULT_LOCK_TTL_SECONDSdictrd   rj   tuplern   
PeerUpdatery   r{   r   r*   r!   r   <module>r      s                     % % % % % % % % ) ) ) ) ) ) / / / / / / 5 5 5 5 5 5         J J J J J J J J J J       6 6 6 6 6 6 G G G G G G G G       ) ) ) ) ) ) - - - - - -	8		J ))++555 	3 	3 	3 	 	 	 	" g g ggg "#g
 g tFK()g g g gT >-000  	   >2555  
  
#s(^d	    0 
 [	   F &*1 11#s(^d"1 E&+1 1 1 1;;&);69;AHAS;[; ; ; ;B &*  #s(^d" E&.!"	     r!   