
    h78j"                         U d Z ddlZddlZddlZddlmZ ddlZddlmZm	Z	m
Z
mZ ddlmZ ddlmZ  ej        e          Z G d d          Zdaedz  ed	<    ej                    Zd
efdZdS )zHDHT service for distributed cache - runs in background thread with Trio.    N)Any)Libp2pClientResultCachecompute_query_hashnormalize_query)DEFAULT_TTL)DEFAULT_MAX_HOP_CONNECTIONSc            
       `   e Zd ZdZdeeddedededdfd	Zdd
Zdde	de
fdZddZdededefdZddededeeeef                  dz  fdZddedeeeef                  deddfdZdeeef         fdZdee         fdZede
fd            Zedefd            Zedefd            ZdS ) 
DhtServicezBackground service running Trio event loop with Libp2pClient and ResultCache.

    Provides thread-safe access to distributed cache DHT from FastAPI.
    r   )listen_port	cache_ttlmax_hop_connectionsr   r   r   returnNc                    || _         || _        || _        d | _        d | _        d | _        d| _        t          j                    | _	        t          j                    | _
        d | _        d S )NF)r   r   r   _dht_cache_thread_started	threadingEvent_start_event_stop_event_trio_token)selfr   r   r   s       c/home/rurouni/.hermes/hermes-agent/venv/lib/python3.11/site-packages/ddgs/api_server/dht_service.py__init__zDhtService.__init__   se     '"#6 )-	*.04%O--$?,,;?    c                 v    d fd}	 t          j        |           n2# t          $ r%}t                              d|           Y d}~nd}~ww xY w j                                          j                                         dS #  j                                          j                                         w xY w)z)Run Trio event loop in background thread.r   Nc                  ,  K   t           j                                         _        t          j                     _        t           j        d j                   _	        t                       _         j	                                         d {V  t                              d j	        j         j	        j                    j                                          j        5  t          j                     d {V  d d d            d S # 1 swxY w Y   d S )NT)r   	bootstrapr   z.Network service started: connected=%s, port=%d)triolowlevelcurrent_trio_tokenr   CancelScope_cancel_scoper   r   r   r   r   r   astartloggerinfo
is_runningportr   setsleep_foreverr   s   r   _mainz#DhtService._run_trio.<locals>._main-   sU     #}??AAD!%!1!3!3D$ ,$($<  DI
 &--DK )""$$$$$$$$$KK@	$	  
 !!#### + +(*********+ + + + + + + + + + + + + + + + + +s   "D		DDzNetwork service loop exited: %rr   N)r!   run	Exceptionr'   warningr   r+   r   )r   r.   exs   `  r   	_run_triozDhtService._run_trio*   s    	+ 	+ 	+ 	+ 	+ 	+,	#HUOOOO 	B 	B 	BNN<bAAAAAAAA	B !!###  """"" !!###  """"s+    B 
AAB AB 4B8      $@timeoutc                    | j         rdS t          j        | j        d          | _        | j                                         | j                            |          r	d| _         dS t          	                    d|           dS )zStart the DHT service in background thread.

        Args:
            timeout: Maximum time to wait for service to start.

        Returns:
            True if service started successfully.

        T)targetdaemonr6   z*Network service failed to start within %dsF)
r   r   Threadr4   r   startr   waitr'   r2   )r   r6   s     r   r<   zDhtService.startK   s     = 	4 't~dKKK!!'!22 	 DM4CWMMMur   c                 d   | j         r| j        dS t          | d          r| j                                         	 | j                                         n2# t          $ r%}t                              d|           Y d}~nd}~ww xY w| j	        r| j	        
                    d           d| _         dS )zStop the DHT service.Nr%   zError stopping DHT service: %rg      @r:   F)r   r   hasattrr%   cancelstopr1   r'   r2   r   join)r   r3   s     r   rA   zDhtService.stopa   s    } 		 1F 4)) 	(%%'''	AINN 	A 	A 	ANN;R@@@@@@@@	A < 	+Lc***s   A 
BA??Bfuncargsc                     | j         r| j        dS dt          ffd}t          j                            || j                  S )zARun an async function in the Trio event loop from another thread.Nr   c                  z   K   t          j        d          5      d {V cd d d            S # 1 swxY w Y   d S )N   )r!   
fail_after)rD   rC   s   r   _wrappedz)DhtService._run_in_trio.<locals>._wrappedy   s      $$ ) )!T4[(((((() ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )s   044)
trio_token)r   r   r   r!   from_threadr0   )r   rC   rD   rI   s    `` r   _run_in_triozDhtService._run_in_triot   sf    } 	 0 84	) 	) 	) 	) 	) 	) 	) 	) ##H9I#JJJr   textquerycategoryc                 ^   | j         r| j        | j        dS t          ||          }t	          |          }| j                            |          }|rt                              d|           |S | j        j        r	 | 	                    | j        j
        |          }|r@t                              d|           | j                            ||||| j                   |S | j                            |           n3# t          $ r&}t                              d||           Y d}~nd}~ww xY wdS )zGet cached results synchronously (for use from FastAPI).

        Args:
            query: The search query.
            category: The search category.

        Returns:
            Cached results or None.

        NzCache hit (local): %szCache hit (network): %szDHT get failed for %s: %r)r   r   r   r   r   getr'   debugr)   rL   agetr+   r   add_negativer1   )r   rN   rO   
query_hash
normalizedlocal_resultsdht_resultsr3   s           r   
get_cachedzDhtService.get_cached   sM    } 		 1T[5H4'x88
$U++

33 	!LL0*===  9 
	J	J;?;L;LTY^]g;h;h 'LL!:JGGGKOOJ
HkSWSabbb&&((4444 J J J8*bIIIIIIIIJ ts   =A!C: C: :
D*D%%D*resultsc                    | j         r| j        | j        dS t          ||          }t	          |          }| j                            ||||| j                   | j        j        ry	 |                     | j        j	        ||| j                   t                              d|           dS # t          $ r'}t                              d||           Y d}~dS d}~ww xY wdS )zCache search results synchronously (for use from FastAPI).

        Args:
            query: The search query.
            results: The search results.
            category: The search category.

        NzCached to network: %szDHT set failed for %s: %r)r   r   r   r   r   r+   r   r)   rL   asetr'   rR   r1   )r   rN   rZ   rO   rU   rV   r3   s          r   cachezDhtService.cache   s    } 		 1T[5HF'x88
$U++

J'4>RRR9 	JJ!!$).*gt~VVV4jAAAAA J J J8*bIIIIIIIIIJ		J 	Js   'AB+ +
C5CCc                    | j         r| j        
ddddddi dS d| j        j        | j        j        | j        j        | j        j        | j        r| j                                        nd| j        r| j                                        ndt          | j        
                                          | j        j        | j        j        | j        j        | j        j        t          j                    | j        j        d         z
  dd
S )	z]Get DHT service status.

        Returns:
            Dict with status information.

        NFr   )running	connectedpeer_idr*   
cache_sizecache_countmetricsT
started_at)query_success_rateaverage_query_latency_mskbucket_distributionuptime_seconds)
r_   r`   ra   r*   listen_addrsrb   rc   
peer_countrouting_table_sizerd   )r   r   r)   ra   r*   rj   r   
size_bytescountlen
find_peersrl   rf   rg   rh   timerd   r-   s    r   
get_statuszDhtService.get_status   s    } 			 1 "    -y(IN I26:kH$+00222q26+D4;,,...1di224455"&)">&*i&B,0I,N(,	(F"&)++	0A,0O"O	 
 
 	
r   c                     | j         r| j        g S 	 |                     | j        j                  }|pg S # t          $ r'}t
                              d|           g cY d}~S d}~ww xY w)zVGet list of connected peers.

        Returns:
            List of peer IDs.

        NzFailed to get peers: %r)r   r   rL   afind_peersr1   r'   rR   )r   peersr3   s      r   	get_peerszDhtService.get_peers   s     } 		 1I	#001FGGE
 ;B	  	 	 	LL2B777IIIIII	s   5 
A&A!A&!A&c                 :    | j         o| j        duo| j        j        S )z Check if DHT service is running.N)r   r   r)   r-   s    r   r)   zDhtService.is_running   s"     }O$!6O49;OOr   c                 F    | j         r| j                                         ndS )zGet number of cached entries.r   )r   rn   r-   s    r   rc   zDhtService.cache_count   s$     '+k8t{  """q8r   c                 F    | j         r| j                                         ndS )zGet cache size in bytes.r   )r   rm   r-   s    r   rb   zDhtService.cache_size   s$     ,0;=t{%%'''A=r   r/   )r5   )rM   )__name__
__module____qualname____doc__r   r	   intr   r4   floatboolr<   rA   r   rL   strlistdictrY   r]   rr   rv   propertyr)   rc   rb    r   r   r   r      sD         $#>@ @ @ @ 	@
 !@ 
@ @ @ @&# # # #B U d    ,   &	K 	KS 	KS 	K 	K 	K 	K" " "s "T#s(^@TW[@[ " " " "HJ J3 Jd38n)= J JZ^ J J J J0"
DcN "
 "
 "
 "
H49    $ PD P P P XP 9S 9 9 9 X9 >C > > > X> > >r   r   _dht_servicer   c                      t           5  t          't                      at                                           ddd           n# 1 swxY w Y   t          S )zVGet the global DHT service instance.

    Returns:
        DhtService singleton.

    N)_dht_service_lockr   r   r<   r   r   r   get_dht_servicer     s     
 ! !%<<L   ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! s   /AA
A)r}   loggingr   rq   typingr   r!   ddgs.dhtr   r   r   r   ddgs.dht.cacher   ddgs.dht.libp2p_clientr	   	getLoggerrz   r'   r   r   __annotations__Lockr   r   r   r   r   <module>r      s   N N N              S S S S S S S S S S S S & & & & & & > > > > > >		8	$	$m> m> m> m> m> m> m> m>` #'j4 & & &"IN$$       r   