o
    cia                     @   s  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	 d dl
mZmZmZmZmZmZmZ d dlZd dlZd dlmZ d dlZd dlm  mZ d dlmZ d dlmZ d dlmZ d d	l m!Z!m"Z"m#Z#m$Z$ d d
l%m&Z&m'Z' d dl(m)Z)m*Z* d dl+m,Z, d dl-m.Z. d dl/m0Z0 d dl1m2Z2 d dl3m4Z4m5Z5 d dl6m7Z7m8Z8 dZ9dZ:G dd de0Z;G dd dZ<G dd dZ=G dd dZ>G dd dZ?G dd dZ@G d d! d!ZAG d"d# d#ZBG d$d% d%ZCejDG d&d' d'ZEeEF ZGd(d) ZHd*d+ ZIe&fd,eJd-e#d.eKfd/d0ZLe&fd1eJd2eJd.eMfd3d4ZNe&fd,eJd5eMd2eJd.eMfd6d7ZOe&d8fd,eJd5eMd2eJd9eKd.eMf
d:d;ZPe&fd,eJd5eMd2eJd.eMfd<d=ZQd>efd?d@ZR		ddAedBe"dCeeM dDeeee*eMef   fdEdFZSejTe:e'd dGG dHdI dIZUejDdJd idKG dLdM dMZVeVF ZWdNdO ZXe:fdPe.dQedReJfdSdTZYddUdVZZddWdXZ[ddYdZZ\d[d\ Z]d]d^ Z^d_d` Z_dadb Z`edcefdddeZaG dfdg dgZbG dhdi diZcG djdk dkZdejTdldm Zed5eMfdndoZfe&dfd1eJd2eJdpefdqdrZgejTG dsdt dtZhddveJdweJfdxdyZie$jje&d8d8d8fdzeeJe$f d2eJd{eKd|eKd}eKd.eeJ fd~dZke$jje&d8d8d8fdzeeJe$f d2eJd{eKd|eKd}eKd.eJfddZldS )    N)asynccontextmanager)copydeepcopy)AnyCallableDictListOptionalTupleUnion)Request)serve)ActorHandle)ServeControllerClient)CreatePlacementGroupRequestDeploymentIDDeploymentStatusRequestProtocol)SERVE_DEFAULT_APP_NAMESERVE_NAMESPACE)ALL_REPLICA_STATESReplicaState)DRAINING_MESSAGE)ServeUsageTag)	TimerBase)_get_global_client)	serve_pb2serve_pb2_grpc)ApplicationStatusTargetGroupz
/telemetrystoragec                   @   s^   e Zd Zddee fddZddee fddZdefdd	Zd
efddZdefddZ	dS )	MockTimerN
start_timec                 C   s   t  | _| j|d d S )Nr"   )	threadingLock_lockresetselfr"    r*   Q/home/ubuntu/.local/lib/python3.10/site-packages/ray/serve/_private/test_utils.py__init__+   s   
zMockTimer.__init__c                 C   s   |d u rt   }|| _d S N)time_currr(   r*   r*   r+   r'   /   s   
zMockTimer.resetreturnc                 C      | j S r-   r/   r)   r*   r*   r+   r.   4      zMockTimer.timebyc                 C   s:   | j  |  j|7  _W d    d S 1 sw   Y  d S r-   r&   r/   )r)   r5   r*   r*   r+   advance7   s   "zMockTimer.advanceamtc                 C   s>   | j  |  j|d 7  _W d    d S 1 sw   Y  d S )NgMbP?r6   r)   r8   r*   r*   r+   realistic_sleep;   s   "zMockTimer.realistic_sleepr-   )
__name__
__module____qualname__r	   floatr,   r'   r.   r7   r:   r*   r*   r*   r+   r!   *   s    r!   c                   @   s\   e Zd Zddee fddZdddZdefdd	Zd
efddZd
efddZ	dd Z
dS )MockAsyncTimerr   r"   c                 C   s   | j |d d| _d S )Nr#   r   )r'   _num_sleepersr(   r*   r*   r+   r,   A   s   
zMockAsyncTimer.__init__c                 C   
   || _ d S r-   r2   r(   r*   r*   r+   r'   E      
zMockAsyncTimer.resetr0   c                 C   r1   r-   r2   r3   r*   r*   r+   r.   H   r4   zMockAsyncTimer.timer8   c                    sP   |  j d7  _ | j| }| j|k rtdI d H  | j|k s|  j d8  _ d S )N   r   )r@   r/   asynciosleep)r)   r8   endr*   r*   r+   rE   K   s   


zMockAsyncTimer.sleepc                 C   s   |  j |7  _ d S r-   r2   r9   r*   r*   r+   r7   U      zMockAsyncTimer.advancec                 C   r1   r-   )r@   r3   r*   r*   r+   num_sleepersX   r4   zMockAsyncTimer.num_sleepersN)r   )r"   r   )r;   r<   r=   r	   r>   r,   r'   r.   rE   r7   rH   r*   r*   r*   r+   r?   @   s    

r?   c                   @   sN   e Zd Zdd ZdededefddZdedefdd	Zdedefd
dZ	dS )MockKVStorec                 C   s   t  | _d S r-   )dictstorer3   r*   r*   r+   r,   ]   s   zMockKVStore.__init__keyvalr0   c                 C   s*   t |tstdt||| j|< dS )Nkey must be a string, got: {}.T
isinstancestr	TypeErrorformattyperK   )r)   rL   rM   r*   r*   r+   put`   s   

zMockKVStore.putc                 C   s*   t |tstdt|| j|d S )NrN   )rP   rQ   rR   rS   rT   rK   getr)   rL   r*   r*   r+   rV   f   s   
zMockKVStore.getc                 C   s6   t |tstdt||| jv r| j|= dS dS )NrN   TFrO   rW   r*   r*   r+   deletek   s   

zMockKVStore.deleteN)
r;   r<   r=   r,   rQ   r   boolrU   rV   rX   r*   r*   r*   r+   rI   \   s
    rI   c                   @   sn   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dde
dedefddZde
defddZdS )MockClusterNodeInfoCachec                 C   s,   t  | _t | _t | _t | _t | _d S r-   )setalive_node_idsrJ   total_resources_per_nodeavailable_resources_per_nodedraining_nodesnode_labelsr3   r*   r*   r+   r,   w   s
   z!MockClusterNodeInfoCache.__init__c                 C   r1   r-   )r\   r3   r*   r*   r+   get_alive_node_ids~   r4   z+MockClusterNodeInfoCache.get_alive_node_idsc                 C   r1   r-   )r_   r3   r*   r*   r+   get_draining_nodes   r4   z+MockClusterNodeInfoCache.get_draining_nodesc                 C   s   | j t| j S r-   )r\   r[   r_   r3   r*   r*   r+   get_active_node_ids      z,MockClusterNodeInfoCache.get_active_node_idsc                 C      d S r-   r*   )r)   node_idr*   r*   r+   get_node_az      z$MockClusterNodeInfoCache.get_node_azc                 C   r1   r-   )r^   r3   r*   r*   r+    get_available_resources_per_node   r4   z9MockClusterNodeInfoCache.get_available_resources_per_nodec                 C   r1   r-   )r]   r3   r*   r*   r+   get_total_resources_per_node   r4   z5MockClusterNodeInfoCache.get_total_resources_per_nodeNrf   	resourceslabelsc                 C   sB   | j | t|pi | j|< t|pi | j|< |pi | j|< d S r-   )r\   addr   r]   r^   r`   )r)   rf   rk   rl   r*   r*   r+   add_node   s   z!MockClusterNodeInfoCache.add_nodec                 C   s   t || j|< d S r-   )r   r^   )r)   rf   rk   r*   r*   r+    set_available_resources_per_node   rG   z9MockClusterNodeInfoCache.set_available_resources_per_nodeNN)r;   r<   r=   r,   ra   rb   rc   rg   ri   rj   rQ   r   rn   ro   r*   r*   r*   r+   rZ   v   s    rZ   c                   @      e Zd Zdd ZdS )FakeRemoteFunctionc                 C   re   r-   r*   r3   r*   r*   r+   remote   rh   zFakeRemoteFunction.remoteN)r;   r<   r=   rs   r*   r*   r*   r+   rr      s    rr   c                   @   s,   e Zd Zdd Zedd Zedd ZdS )MockActorHandlec                 K   s   || _ d| _d| _d| _d S )Nfake_idF)_options	_actor_id"initialize_and_get_metadata_calledis_allocated_called)r)   kwargsr*   r*   r+   r,      s   
zMockActorHandle.__init__c                 C      d| _ t S NT)rx   rr   r3   r*   r*   r+   initialize_and_get_metadata   s   z+MockActorHandle.initialize_and_get_metadatac                 C   r{   r|   )ry   rr   r3   r*   r*   r+   is_allocated   s   zMockActorHandle.is_allocatedN)r;   r<   r=   r,   propertyr}   r~   r*   r*   r*   r+   rt      s    
rt   c                   @   s*   e Zd Zdd Zdd ZdefddZdS )	MockActorClassc                 C      d| _ t | _d S Nr*   )
_init_argsrJ   rv   r3   r*   r*   r+   r,         zMockActorClass.__init__c                 K   s(   t | }| D ]	\}}||j|< q|S r-   )r   itemsrv   )r)   rz   reskvr*   r*   r+   options   s   zMockActorClass.optionsr0   c                 G   s   t dd|i| jS )N	init_argsr*   )rt   rv   )r)   argsr*   r*   r+   rs         zMockActorClass.remoteN)r;   r<   r=   r,   r   rt   rs   r*   r*   r*   r+   r      s    r   c                   @   s   e Zd ZdefddZdS )MockPlacementGrouprequestc                 C   s*   |j | _|j| _|j| _|j| _d| _d S )Ndetached)	bundles_bundlesstrategy	_strategytarget_node_id_soft_target_node_idname_name	_lifetime)r)   r   r*   r*   r+   r,      s
   
zMockPlacementGroup.__init__N)r;   r<   r=   r   r,   r*   r*   r*   r+   r      s    r   c                   @   s~   e Zd ZefdedefddZdd Zdd Zd	d
 Zde	e fddZ
defddZdd ZdefddZdefddZdS )MockDeploymentHandledeployment_nameapp_namec                 C   s$   || _ || _tj| _d| _d| _d S )NF)_deployment_name	_app_namer   	UNDEFINED	_protocol_running_replicas_populated_initialized)r)   r   r   r*   r*   r+   r,      s
   
zMockDeploymentHandle.__init__c                 C   r1   r-   )r   r3   r*   r*   r+   is_initialized   r4   z#MockDeploymentHandle.is_initializedc                 C   s   | j rtdd| _ d S )Nzalready initializedT)r   RuntimeErrorr3   r*   r*   r+   _init   s   
zMockDeploymentHandle._initc                 O   s   | S r-   r*   )r)   r   rz   r*   r*   r+   r      rh   zMockDeploymentHandle.optionsdepc                 C   s   |\}}| j |ko| j|kS r-   )r   r   )r)   r   other_deployment_nameother_app_namer*   r*   r+   __eq__   s   
zMockDeploymentHandle.__eq__protocolc                 C   rA   r-   )r   )r)   r   r*   r*   r+   _set_request_protocol   rB   z*MockDeploymentHandle._set_request_protocolc                 C   re   r-   r*   r3   r*   r*   r+   _get_or_create_router   rh   z*MockDeploymentHandle._get_or_create_routerr0   c                 C   r1   r-   r   r3   r*   r*   r+   running_replicas_populated   r4   z/MockDeploymentHandle.running_replicas_populatedrM   c                 C   rA   r-   r   )r)   rM   r*   r*   r+   set_running_replicas_populated   rB   z3MockDeploymentHandle.set_running_replicas_populatedN)r;   r<   r=   r   rQ   r,   r   r   r   r
   r   r   r   r   rY   r   r   r*   r*   r*   r+   r      s    r   c                   @   rq   )GetPIDc                 C   s   t  S r-   )osgetpidr3   r*   r*   r+   __call__   s   zGetPID.__call__N)r;   r<   r=   r   r*   r*   r*   r+   r      s    r   c                   C   s&   zt d W dS  ty   Y dS w )N%http://localhost:8265/api/ray/versionFT)requestsrV   	Exceptionr*   r*   r*   r+   check_ray_stopped   s   
r   c                   C   s   t djdkS )Nr      )r   rV   status_coder*   r*   r*   r+   check_ray_started  rd   r   r   expected_statusr0   c                 C   s&   t  j| }|j|  j|ksJ dS r|   )r   statusapplicationsdeployments)r   r   r   
app_statusr*   r*   r+   check_deployment_status	  s   r   r   r   c                 C   s.   t | |d}tjdd| fdgd}t|S )z<Get the replicas currently running for the given deployment.)r   r   
class_name=)stater   ALIVE)filters)r   	state_apilist_actorsto_replica_actor_class_namelen)r   r   dep_idactorsr*   r*   r+   get_num_alive_replicas  s   r   targetc                 C   s   t | ||ks	J dS )z#Check if num replicas is >= target.Tr   r   r   r   r*   r*   r+   check_num_replicas_gte      r   Fuse_controllerc                 C   sN   |rt  j| j|  }|jtjd}||ksJ dS t| ||ks%J dS )z#Check if num replicas is == target.r   T)	r   r   r   r   replica_statesrV   r   RUNNINGr   )r   r   r   r   r   num_running_replicasr*   r*   r+   check_num_replicas_eq)  s   r   c                 C   s   t | ||ks	J dS )z#Check if num replicas is <= target.Tr   r   r*   r*   r+   check_num_replicas_lte;  r   r   appsc                 C   s,   t  }| D ]}|j| jtjksJ qdS r|   )r   r   r   r   r   )r   r   r   r*   r*   r+   check_apps_runningD  s   r   
controllerdeployment_idtotalby_statec           
         s   t | j||dur fddtD } |ks J ||durn|D ]G\}} t|ts2J t|tr;|dks=J  rR fddj|gdD }t	|}nj|gd}d| d	| d
| d}	||ksmJ |	q&dS )a  Uses _dump_replica_states_for_testing to check replica counts.

    Args:
        controller: A handle to the Serve controller.
        deployment_id: The deployment to check replica counts for.
        total: The total number of expected replicas for the deployment.
        by_state: A list of tuples of the form
            (replica state, number of replicas, filter function).
            Used for more fine grained checks.
    Nc                    s*   i | ]}  |gr|t  |gqS r*   )rV   r   ).0r   )replicasr*   r+   
<dictcomp>b  s    
z(check_replica_counts.<locals>.<dictcomp>r   c                    s   h | ]} |r|qS r*   r*   )r   r)checkr*   r+   	<setcomp>n      z'check_replica_counts.<locals>.<setcomp>)statesz	Expected z for state z	 but got .T)
rayrV    _dump_replica_states_for_testingrs   r   countrP   r   intr   )
r   r   r   r   replica_countsr   r   filtered
curr_countmsgr*   )r   r   r+   check_replica_countsM  s&   


r   )r   	namespacenum_cpusc                   @   sB   e Zd Zdd ZdeddfddZdefdd	Zdefd
dZdS )TelemetryStoragec                 C   r   Nr   )reports_receivedrJ   current_reportr3   r*   r*   r+   r,   z  r   zTelemetryStorage.__init__reportr0   Nc                 C   s   |  j d7  _ || _d S NrC   )r   r   )r)   r   r*   r*   r+   store_report~  s   
zTelemetryStorage.store_reportc                 C   r1   r-   )r   r3   r*   r*   r+   
get_report  r4   zTelemetryStorage.get_reportc                 C   r1   r-   )r   r3   r*   r*   r+   get_reports_received  r4   z%TelemetryStorage.get_reports_received)	r;   r<   r=   r,   r   r   r   r   r   r*   r*   r*   r+   r   x  s
    r   r   )ray_actor_optionsc                   @   s&   e Zd Zdd ZdedefddZdS )TelemetryReceiverc                 C   s   t jttd| _d S )N)r   r   )r   	get_actorSTORAGE_ACTOR_NAMEr   r    r3   r*   r*   r+   r,     r   zTelemetryReceiver.__init__r   r0   c                    s(   |  I d H }t| jj| dS r|   )jsonr   rV   r    r   rs   )r)   r   r   r*   r*   r+   r     s   zTelemetryReceiver.__call__N)r;   r<   r=   r,   r   rY   r   r*   r*   r*   r+   r     s    r   c                  C   s   t  } tjtdtd | S )u  Start a telemetry Serve app.

    Ray should be initialized before calling this method.

    NOTE: If you're running the TelemetryReceiver Serve app to check telemetry,
    remember that the receiver itself is counted in the telemetry. E.g. if you
    deploy a Serve app other than the receiver, the number of apps in the
    cluster is 2- not 1– since the receiver is also running.

    Returns a handle to a TelemetryStorage actor. You can use this actor
    to access the latest telemetry reports.
    	telemetry)r   route_prefix)r   rs   r   runreceiver_appTELEMETRY_ROUTE_PREFIX)r    r*   r*   r+   start_telemetry_app  s   r  tagexpectedstorage_actor_namec                 C   s@   t j|td}t |j }t|d  | ||ksJ dS )N)r   extra_usage_tagsT)r   r   r   rV   r   rs   printget_value_from_report)r  r  r  storage_handler   r*   r*   r+   check_telemetry  s
   r  c                 C   s   dd l }t| }t }|rE|tj}|jj	|d\}}W d    n1 s)w   Y  |j
}| tjjks;J | tksCJ dS |jj	|d\}	}
|
 tjjksXJ |	j|ks_J dS )Nr   r   T)pytestr   RayServeAPIServiceStubr   ListApplicationsRequestraisesgrpcRpcErrorListApplications	with_callvaluecode
StatusCodeUNAVAILABLEdetailsr   OKapplication_names)channel	app_namestest_drainingr  stubr   exception_info_	rpc_errorresponsecallr*   r*   r+   ping_grpc_list_applications  s   
r&  c           
      C   s   dd l }t| }t }|rE|tj}|jj	|d\}}W d    n1 s)w   Y  |j
}| tjjks;J | tksCJ d S |jj	|d\}}	|	 tjjksXJ |jdks_J d S )Nr   r  success)r  r   r  r   HealthzRequestr  r  r  Healthzr  r  r  r  r  r  r   r  message)
r  r  r  r   r   r!  r"  r#  r$  r%  r*   r*   r+   ping_grpc_healthz  s   
r+  c                 C   s   dd l }t| }tjdddd}d|ff}|rW|tj}|jj	||d\}}W d    n1 s3w   Y  |j
}	|	 tjjksIJ |	 d| d	|	 v sUJ d S |jj	||d\}
}| tjjksoJ | |
jd
ksyJ |
jd S )Nr   foo   barr   numr,  applicationr   metadatazApplication 'z' not found.zHello foo from bar)r  r   UserDefinedServiceStubr   UserDefinedMessager  r  r  r   r  r  r  r  	NOT_FOUNDr  r  greeting)r  r   test_not_foundr  r   r   r3  r!  r"  r#  r$  r%  r*   r*   r+   ping_grpc_call_method  s   

r9  c                 C   sD   t | }tjdddd}d|ff}|j||d}|jdks J d S )Nr,  r-  r.  r/  r1  r2  zHello foo from method1)r   r4  r   r5  Method1r7  r  r   r   r   r3  r$  r*   r*   r+   ping_grpc_another_method  s
   

r<  c                 C   sT   t | }tjdddd}d}d|fd|ff}|j||d}|jd	| ks(J d S )
Nr,  r-  r.  r/  999r1  multiplexed_model_idr2  z%Method2 called model, loading model: )r   r4  r   r5  Method2r7  )r  r   r   r   r>  r3  r$  r*   r*   r+   ping_grpc_model_multiplexing  s   
r@  c                 C   s\   t | }tjdddd}d|ff}|j||d}t|D ]\}}|j| dks+J qd S )Nr,  r-  r.  r/  r1  r2  z: Hello foo from bar)r   r4  r   r5  	Streaming	enumerater7  )r  r   r   r   r3  	responsesidxr$  r*   r*   r+   ping_grpc_streaming   s   

rE  c                 C   sB   t | }tjddd}d|ff}|j||d}|jdksJ d S )N      )orangeappler1  r2      )r   FruitServiceStubr   FruitAmounts
FruitStandcostsr;  r*   r*   r+   ping_fruit_stand	  s
   

rO  signal_actorc                 C  sh   d}zd V  t dI d H  W n t jy+   d}tjjd  | j I d H  Y nw |s2t	dd S )NFd   TzGCancelledError wasn't raised during `send_signal_on_cancellation` block)
rD   rE   CancelledErrorr   _rayletasync_task_idr[   sendrs   r   )rP  	cancelledr*   r*   r+   send_signal_on_cancellation  s   rW  c                   @   sl   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd ZdS )FakeGrpcContextc                 C   s@   ddi| _ dg| _d| _d| _d| _d | _d | _g | _g | _d S )NrL   r  )rL   r  peers   peer_identitiespeer_identity_key)_auth_context_invocation_metadata_peer_peer_identities_peer_identity_key_code_details_trailing_metadatar3   r*   r*   r+   r,   $  s   

zFakeGrpcContext.__init__c                 C   r1   r-   )r[  r3   r*   r*   r+   auth_context/  r4   zFakeGrpcContext.auth_contextc                 C   r1   r-   r`  r3   r*   r*   r+   r  2  r4   zFakeGrpcContext.codec                 C   r1   r-   ra  r3   r*   r*   r+   r  5  r4   zFakeGrpcContext.detailsc                 C   r1   r-   )r]  r3   r*   r*   r+   rY  8  r4   zFakeGrpcContext.peerc                 C   r1   r-   )r^  r3   r*   r*   r+   peer_identities;  r4   zFakeGrpcContext.peer_identitiesc                 C   r1   r-   )r_  r3   r*   r*   r+   rZ  >  r4   z!FakeGrpcContext.peer_identity_keyc                 C   r1   r-   rb  r3   r*   r*   r+   trailing_metadataA  r4   z!FakeGrpcContext.trailing_metadatac                 C   rA   r-   rd  )r)   r  r*   r*   r+   set_codeD  rB   zFakeGrpcContext.set_codec                 C   rA   r-   re  )r)   r  r*   r*   r+   set_detailsG  rB   zFakeGrpcContext.set_detailsc                 C   rA   r-   rg  )r)   rh  r*   r*   r+   set_trailing_metadataJ  rB   z%FakeGrpcContext.set_trailing_metadatac                 C   r1   r-   )r\  r3   r*   r*   r+   invocation_metadataM  r4   z#FakeGrpcContext.invocation_metadataN)r;   r<   r=   r,   rc  r  r  rY  rf  rZ  rh  ri  rj  rk  rl  r*   r*   r*   r+   rX  #  s    rX  c                   @   st   e Zd Zddedee fddZdeeef fddZdd	ee	e
f deeef fd
dZdeeef fddZdS )	FakeGaugeNr   tag_keysc                 C   $   || _ t | _|p
d| _t | _d S r   )r   rJ   valuestagsdefault_tagsr)   r   rn  r*   r*   r+   r,   R     
zFakeGauge.__init__rq  c                 C   .   |  D ]\}}|| jv sJ || j|< qd S r-   r   rq  rr  r)   rq  rL   r  r*   r*   r+   set_default_tagsY     zFakeGauge.set_default_tagsr  c                 C   s   | j  }||p
i  t| t| jksJ | j}| jd d D ]}|| }||vr2t ||< || }q#|||| jd  < d S )N)rr  r   updater[   keysrq  rp  rJ   )r)   r  rq  merged_tagsdr  	tag_valuer*   r*   r+   r[   ^  s   


zFakeGauge.setc                 C   6   | j }| jD ]}|| }||}|d u r d S q|S r-   )rp  rq  rV   r)   rq  r  r  r  r*   r*   r+   	get_valuel     

zFakeGauge.get_valuerp   r-   )r;   r<   r=   rQ   r
   r,   r   rx  r   r   r>   r[   r  r*   r*   r*   r+   rm  Q  s
    $rm  c                   @   s   e Zd Zddedee fddZdeeef fddZdd
ee	e
f deeef fddZdeeef de	fddZdd ZdS )FakeCounterNr   rn  c                 C   ro  r   )r   rJ   countsrq  rr  rs  r*   r*   r+   r,   x  rt  zFakeCounter.__init__rq  c                 C   ru  r-   rv  rw  r*   r*   r+   rx    ry  zFakeCounter.set_default_tags      ?r  c                 C   s   | j  }||p
i  t| t| jksJ | j}| jd d D ]}|| }||vr2t ||< || }q#|| jd  }||d| ||< d S )Nrz  r   )	rr  r   r{  r[   r|  rq  r  rJ   rV   )r)   r  rq  r}  r~  r  r  rL   r*   r*   r+   inc  s   


zFakeCounter.incr0   c                 C   r  r-   )r  rq  rV   r  r*   r*   r+   	get_count  r  zFakeCounter.get_countc                 C   r1   r-   )rq  r3   r*   r*   r+   get_tags  r4   zFakeCounter.get_tagsrp   )r  N)r;   r<   r=   rQ   r
   r,   r   rx  r   r   r>   r  r  r  r*   r*   r*   r+   r  w  s    $
r  c                   C   s   t   S r-   )r   get_runtime_contextget_node_idr*   r*   r*   r+   r    s   r  c                 C   s&   dd t  D }t|| ksJ dS )Nc                 S   s   g | ]}|d  r|qS )Aliver*   )r   noder*   r*   r+   
<listcomp>  r   z)check_num_alive_nodes.<locals>.<listcomp>T)r   nodesr   )r   alive_nodesr*   r*   r+   check_num_alive_nodes  s   r  _clientc                 C   s&   |pt  }| }|d | d |  S )Nr   r   )r   get_serve_details)r   r   r  clientr  r*   r*   r+   get_deployment_details  s   
r  c                   @   s*   e Zd ZdefddZdd Zdd ZdS )	Counterr   c                 C   s   d| _ || _t | _d S r   )r   r   rD   Eventready_event)r)   r   r*   r*   r+   r,     s   zCounter.__init__c                 C   s,   |  j d7  _ | j | jkr| j  d S d S r   )r   r   r  r[   r3   r*   r*   r+   r    s   zCounter.incc                    s   | j  I d H  d S r-   )r  waitr3   r*   r*   r+   r    s   zCounter.waitN)r;   r<   r=   r   r,   r  r  r*   r*   r*   r+   r    s    r  INFOslevelc                 C   s6   t j  ddd }td| d| d|   dS )z&Convenient logging method for testing.z%H:%M:%S.%fN[z]  )datetimenowstrftimer	  )r  r  r  r*   r*   r+   tlog  s   r  r   use_localhostis_websocketexclude_route_prefixc                    s@  t  }| }||d vr|jgS |d | d }|rd}t tr&t  t|jj	
|} fdd|D }t|dkrLtd| d  d	| g }	|D ]M}
|
jD ]G}|r[d
n|j} tjkrw|rgdnd}| d| d|j | }n tjkr|rtd| d|j }ntd  |d}|	| qUqP|	S )a   Get the URL of the application.

    Args:
        protocol: The protocol to use for the application.
        app_name: The name of the application.
        use_localhost: Whether to use localhost instead of the IP address.
            Set to True if Serve deployments are not exposed publicly or
            for low latency benchmarking.
        is_websocket: Whether the url should be served as a websocket.
        exclude_route_prefix: The route prefix to exclude from the application.
    Returns:
        The URLs of the application.
    r   r    c                    s   g | ]	}|j  kr|qS r*   r   )r   target_groupr  r*   r+   r    s
    
z(get_application_urls.<locals>.<listcomp>r   zNo target group found for app z with protocol z and route prefix 	localhostwshttpz://:z6is_websocket=True is not supported with gRPC protocol.zUnsupported protocol: /)r   r  root_urlrP   rQ   r   r   rV   _controllerget_target_groupsrs   r   
ValueErrortargetsipHTTPportGRPCrstripappend)r   r   r  r  r  r  serve_detailsr   target_groupsurlsr  r   r  schemeurlr*   r  r+   get_application_urls  sJ   





r  c                 C   s   t t| ||||S )aU  Get the URL of the application.

    Args:
        protocol: The protocol to use for the application.
        app_name: The name of the application.
        use_localhost: Whether to use localhost instead of the IP address.
            Set to True if Serve deployments are not exposed publicly or
            for low latency benchmarking.
        is_websocket: Whether the url should be served as a websocket.
        exclude_route_prefix: The route prefix to exclude from the application.
    Returns:
        The URL of the application. If there are multiple URLs, a random one is returned.
    )randomchoicer  )r   r   r  r  r  r*   r*   r+   get_application_url  s
   
r  rp   )F)r  )mrD   r  r   r  r$   r.   
contextlibr   r   r   typingr   r   r   r   r	   r
   r   r  r   starlette.requestsr   r   ray.util.stateutilr   r   r   	ray.actorr   ray.serve._private.clientr   ray.serve._private.commonr   r   r   r   ray.serve._private.constantsr   r   #ray.serve._private.deployment_stater   r   ray.serve._private.proxyr   ray.serve._private.usager   ray.serve._private.utilsr   ray.serve.contextr   ray.serve.generatedr   r   ray.serve.schemar   r   r  r   r!   r?   rI   rZ   rr   rt   r   r   r   
deploymentr   bindget_pid_entrypointr   r   rQ   rY   r   r   r   r   r   r   r   r   rs   r   r   r  r  r  r&  r+  r9  r<  r@  rE  rO  rW  rX  rm  r  r  r  r  r  r  r  r  r  r*   r*   r*   r+   <module>   sh   $$	(
	



	
+





	.&*




?
