o
    ci^                     @   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
mZ d dlmZ d dlmZmZmZmZ d dl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m Z m!Z!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l0m1Z1 d dl2m3Z3 d dl4m5Z5 d dl6m7Z7 d dl8m9Z9m:Z:m;Z;m<Z< d dl=m>Z> d dl?m@Z@ d dlAmBZB d dlCmDZEmFZGmHZHmIZJmKZL d dlMmNZNmDZDmOZOmPZPmQZQ d dlRmSZS eTe'ZUdZVG dd deZWe
G dd dZXe
d d!G d"d# d#ZFe
d d!G d$d% d%ZKe
G d&d' d'ZYG d(d) d)ZZG d*d+ d+Z[ej\d d,d-d.e]d/e]d0e]d1ed2ePd3eeee  ee] f fd4d5Z^d6ee]e-f d7eeQ d3ee]e-f fd8d9Z_dS ):    N)deepcopy)asdict	dataclassfield)Enum)DictListOptionalTuple)cloudpickle)import_attr)RuntimeEnvSetupError)BuiltApplication	build_app)DeploymentIDDeploymentStatusDeploymentStatusInfoDeploymentStatusTriggerEndpointInfoTargetCapacityDirection)DeploymentConfig)RAY_SERVE_ENABLE_TASK_EVENTSSERVE_LOGGER_NAME)deploy_args_to_deployment_infoget_app_code_versionget_deploy_args)DeploymentInfo)DeploymentStateManager)EndpointState)configure_component_logger)KVStoreBase)ServeUsageTag)DEFAULTcheck_obj_ref_ready_nowait%override_runtime_envs_except_env_varsvalidate_route_prefix)ASGIAppReplicaWrapper)AutoscalingConfig)RayServeException)ApplicationStatusApplicationStatusInfoDeploymentLanguageDeploymentStatusInfoListStatusOverview)APITyper)   DeploymentDetailsLoggingConfigServeApplicationSchema)	ObjectRefz"serve-application-state-checkpointc                   @   s    e Zd ZdZdZdZdZdZdS )BuildAppStatusz%Status of the build application task.            N)__name__
__module____qualname____doc__NO_TASK_IN_PROGRESSIN_PROGRESS	SUCCEEDEDFAILED r@   r@   X/home/ubuntu/.local/lib/python3.10/site-packages/ray/serve/_private/application_state.pyr3   D   s    r3   c                   @   sJ   e Zd ZU dZeed< eed< eed< ee	 ed< ee
 ed< eed< dS )	BuildAppTaskInfoa8  Stores info on the current in-progress build app task.

    We use a class instead of only storing the task object ref because
    when a new config is deployed, there can be an outdated in-progress
    build app task. We attach the code version to the task info to
    distinguish outdated build app tasks.
    obj_refcode_versionconfigtarget_capacitytarget_capacity_directionfinishedN)r8   r9   r:   r;   r2   __annotations__strr1   r	   floatr   boolr@   r@   r@   rA   rB   M   s   
 rB   T)eqc                   @   sP   e Zd ZU eed< dZeed< dZeed< dd Z	dd	 Z
ed
efddZdS )r*   status messager   deployment_timestampc                 C      t jt| ddS Nr7   )indentjsondumpsr   selfr@   r@   rA   debug_stringe      z"ApplicationStatusInfo.debug_stringc                 C   s   t d| jj | j| jdS NAPPLICATION_STATUS_)rN   rP   rQ   )ApplicationStatusInfoProtorN   namerP   rQ   rX   r@   r@   rA   to_protoh   s
   zApplicationStatusInfo.to_protoprotoc                 C   s.   t |jtdd  }| t||j|jdS r\   )ApplicationStatusProtoNamerN   lenr)   rP   rQ   )clsra   rN   r@   r@   rA   
from_protoo   s   z ApplicationStatusInfo.from_protoN)r8   r9   r:   r)   rI   rP   rJ   rQ   rK   rZ   r`   classmethodr^   rf   r@   r@   r@   rA   r*   _   s   
 r*   c                   @   st   e Zd ZU eed< dZeed< eedZ	e
e ed< dd Zdedee fd	d
Zdd Zededd fddZdS )r-   
app_statusrO   r_   )default_factorydeployment_statusesc                 C   rR   rS   rU   rX   r@   r@   rA   rZ      r[   zStatusOverview.debug_stringreturnc                 C   s"   | j D ]}||jkr|  S qdS )zGet a deployment's status by name.

        Args:
            name: Deployment's name.

        Returns:
            Optional[DeploymentStatusInfo]: The status of the deployment if it exists,
                otherwise None.
        N)rj   r_   )rY   r_   deployment_statusr@   r@   rA   get_deployment_status   s
   

z$StatusOverview.get_deployment_statusc                 C   s<   | j  }tdd | j}t }|j| t| j||dS )Nc                 S   s   |   S N)r`   )rN   r@   r@   rA   <lambda>   s    z)StatusOverview.to_proto.<locals>.<lambda>)r_   rh   rj   )	rh   r`   maprj   DeploymentStatusInfoListProtodeployment_status_infosextendStatusOverviewProtor_   )rY   app_status_protodeployment_status_protosdeployment_status_proto_listr@   r@   rA   r`      s   

zStatusOverview.to_protora   c                 C   s>   t |j}g }|jjD ]
}|t| q| |||jdS )N)rh   rj   r_   )r*   rf   rh   rj   rr   appendr   r_   )re   ra   rh   rj   
info_protor@   r@   rA   rf      s   zStatusOverview.from_protoN)r8   r9   r:   r*   rI   r_   rJ   r   listrj   r   r   rZ   r	   rm   r`   rg   rt   rf   r@   r@   r@   rA   r-   y   s   
 r-   c                   @   sf   e Zd ZU dZeeeef  ed< ee ed< ee	 ed< ee
 ed< ee ed< eed< eed< d	S )
ApplicationTargetStatea  Defines target state of application.

    Target state can become inconsistent if the code version doesn't
    match that of the config. When that happens, a new build app task
    should be kicked off to reconcile the inconsistency.

    deployment_infos: map of deployment name to deployment info. This is
      - None if a config was deployed but the app hasn't finished
        building yet,
      - An empty dict if the app is deleting.
    code_version: Code version of all deployments in target state. None
        if application was deployed through serve.run.
    config: application config deployed by user. None if application was
        deployed through serve.run.
    target_capacity: the target_capacity to use when adjusting num_replicas.
    target_capacity_direction: the scale direction to use when
        running the Serve autoscaler.
    deleting: whether the application is being deleted.
    deployment_infosrD   rE   rF   rG   deletingapi_typeN)r8   r9   r:   r;   r	   r   rJ   r   rI   r1   rK   r   rL   r.   r@   r@   r@   rA   r{      s   
 r{   c                   @   s  e Zd ZdZdedededefddZe	de
e fd	d
Ze	de
e fddZe	defddZe	defddZe	dee fddZe	de
e fddZe	defddZdefddZddddde
eeef  dede
e d e
e d!e
e d"e
e d#efd$d%Zd&d' Zd e
e fd(d)Zd*d+ Z d,d- Z!defd.d/Z"d0ed1eddfd2d3Z#deeef fd4d5Z$d6ed!e
e d"e
e d7eddf
d8d9Z%dee fd:d;Z&de'eef fd<d=Z(de'e
e e)ef fd>d?Z*deeef ddfd@dAZ+deeef de'eef fdBdCZ,dUdDdEZ-defdFdGZ.defdHdIZ/dee0 fdJdKZ1de2fdLdMZ3deee4f fdNdOZ5dVdQedReddfdSdTZ6dS )WApplicationStatez4Manage single application states with all operationsr_   deployment_state_managerendpoint_statelogging_configc              	   C   sf   || _ d| _|| _|| _d| _d| _d| _tj| _	t

 | _d| _tddddddtjd| _|| _dS )z
        Args:
            name: Application name.
            deployment_state_manager: State manager for all deployments
                in the cluster.
            endpoint_state: State manager for endpoints in the system.
        rO   NF)r|   rD   rE   rF   rG   r}   r~   )_name_status_msg_deployment_state_manager_endpoint_state_route_prefix
_docs_path_ingress_deployment_namer)   	DEPLOYING_statustime_deployment_timestamp_build_app_task_infor{   r.   UNKNOWN_target_state_logging_config)rY   r_   r   r   r   r@   r@   rA   __init__   s(   

	zApplicationState.__init__rk   c                 C      | j S rn   )r   rX   r@   r@   rA   route_prefix     zApplicationState.route_prefixc                 C   s*   | j d ur| j S t| j| j}| j|S rn   )r   r   r   r   r   get_deployment_docs_path)rY   ingress_deploymentr@   r@   rA   	docs_path	  s   
zApplicationState.docs_pathc                 C   r   )a  Status of the application.

        DEPLOYING: The build task is still running, or the deployments
            have started deploying but aren't healthy yet.
        RUNNING: All deployments are healthy.
        DEPLOY_FAILED: The build task failed or one or more deployments
            became unhealthy in the process of deploying
        UNHEALTHY: While the application was running, one or more
            deployments transition from healthy to unhealthy.
        DELETING: Application and its deployments are being deleted.
        )r   rX   r@   r@   rA   rN     s   zApplicationState.statusc                 C   r   rn   )r   rX   r@   r@   rA   rQ   )  r   z%ApplicationState.deployment_timestampc                 C   s    | j jdu rg S t| j j S )z/List of target deployment names in application.N)r   r|   rz   keysrX   r@   r@   rA   target_deployments-  s   z#ApplicationState.target_deploymentsc                 C   r   rn   )r   rX   r@   r@   rA   r   4  r   z#ApplicationState.ingress_deploymentc                 C   s   | j jS rn   )r   r~   rX   r@   r@   rA   r~   8  s   zApplicationState.api_typecheckpoint_datac              	   C   s`   t d| j d | j|j|j|j|j|j|j	|j
d |jd ur.| |j\| _| _d S d S )Nz)Recovering target state for application 'z' from checkpoint.)r~   rD   target_configrF   rG   r}   )loggerinfor   _set_target_stater|   r~   rD   rE   rF   rG   r}   _check_routesr   r   )rY   r   r@   r@   rA   $recover_target_state_from_checkpoint<  s"   
z5ApplicationState.recover_target_state_from_checkpointNF)rF   rG   r}   r|   r~   rD   r   rF   rG   r}   c             	   C   sl   |r	|  tj n|  tj |du rd| _n| D ]
\}}	|	jr%|| _qt|||||||d}
|
| _dS )ac  Set application target state.

        While waiting for build task to finish, this should be
            (None, False)
        When build task has finished and during normal operation, this should be
            (target_deployments, False)
        When a request to delete the application has been received, this should be
            ({}, True)
        N)r~   )	_update_statusr)   DELETINGr   r   itemsingressr{   r   )rY   r|   r~   rD   r   rF   rG   r}   r_   r   target_stater@   r@   rA   r   S  s&   

z"ApplicationState._set_target_statec                 C   s   | j i | jjdddd dS )zlSet target state to deleting.

        Wipes the target deployment infos, code version, and config.
        NTr|   r~   rD   r   r}   )r   r   r~   rX   r@   r@   rA   _set_target_state_deleting  s   
z+ApplicationState._set_target_state_deletingc                 C   s   | j dtjd|dd dS )zClears the target state and stores the config.

        NOTE: this currently assumes that this method is *only* called when managing
        apps deployed with the declarative API.
        NFr   )r   r.   DECLARATIVE)rY   r   r@   r@   rA   $_clear_target_state_and_store_config  s   	
z5ApplicationState._clear_target_state_and_store_configc                 C   s*   t || jd}| j| | j| d S )Nr_   app_name)r   r   r   delete_endpointr   delete_deployment)rY   r_   idr@   r@   rA   _delete_deployment  s   z#ApplicationState._delete_deploymentc                 C   s4   | j tjkrtjd| j dddid |   dS )zDelete the applicationzDeleting app ''.log_to_stderrF)extraN)r   r)   r   r   r   r   r   rX   r@   r@   rA   delete  s   zApplicationState.deletec                 C   s   | j jot|  dkS )zCheck whether the application is already deleted.

        For an application to be considered deleted, the target state has to be set to
        deleting and all deployments have to be deleted.
        r   )r   r}   rd   _get_live_deploymentsrX   r@   r@   rA   
is_deleted  s   zApplicationState.is_deleteddeployment_namedeployment_infoc                 C   s   |j }|dur|dstd| dt|| jd}| j|| |j dur<|j}| j	|t
|j |jtjkd dS | j| dS )z(Deploys a deployment in the application.N/zInvalid route prefix "z", it must start with "/"r   )routeapp_is_cross_language)r   
startswithr(   r   r   r   deploydeployment_configr   update_endpointr   deployment_languager+   PYTHONr   )rY   r   r   r   deployment_idrE   r@   r@   rA   apply_deployment_info  s&   

z&ApplicationState.apply_deployment_infoc                 C   s8   |  | | |\| _| _| j|tjddddd dS )a%  (Re-)deploy the application from list of deployment infos.

        This function should only be called to deploy an app from an
        imperative API (i.e., `serve.run` or Java API).

        Raises: RayServeException if there is more than one route prefix
            or docs path.
        N)r|   r~   rD   r   rF   rG   )_check_ingress_deploymentsr   r   r   r   r.   
IMPERATIVE)rY   r|   r@   r@   rA   
deploy_app  s   


zApplicationState.deploy_apprE   deployment_timec                 C   s  || _ t|}|| jjkrhz!t| jj|}| |\| _| _| j	| jjt
j||||d W dS  tttfyI   | | | tjt  Y dS  tyg   | | | tjd| j dt   Y dS w | jr| jjstd| j d t| jj | | | jjj ds| jjj drt!j"#d td	| j d
 t$j%|jt&d'|j(||j)|j*| j+}t,|||||dd| _dS )a  Apply the config to the application.

        If the code version matches that of the current live deployments
        then it only applies the updated config to the deployment state
        manager. If the code version doesn't match, this will re-build
        the application.

        This function should only be called to (re-)deploy an app from
        the declarative API (i.e., through the REST API).
        )rD   r~   r|   r   rF   rG   AUnexpected error occurred while applying config for application '': 
z%Received new config for application 'z'. Cancelling previous request.	container	image_uri1zImporting and building app 'r   )runtime_envenable_task_eventsF)rC   rD   rE   rF   rG   rH   N)-r   r   r   rD   override_deployment_infor|   r   r   r   r   r.   r   	TypeError
ValueErrorr(   r   r   r)   DEPLOY_FAILED	traceback
format_exc	Exceptionr   r   rH   r   r   raycancelrC   rE   r   getr!   APP_CONTAINER_RUNTIME_ENV_USEDrecordbuild_serve_applicationoptionsr   remoteimport_pathr_   argsr   rB   )rY   rE   rF   rG   r   config_versionoverrided_infosbuild_app_obj_refr@   r@   rA   apply_app_config  s   








z!ApplicationState.apply_app_configc                 C   s   | j | jS rn   )r   get_deployments_in_applicationr   rX   r@   r@   rA   r   K  s   z&ApplicationState._get_live_deploymentsc                 C   s   | j jr	tjdfS |  }t|dd d}|jtjkr+dd |D }tjd| dfS |jtj	krAd	d |D }tj	d
| dfS |jtj
krLtjdfS |jtjtjfv r`|jtjkr`tjdfS tjdfS )a  Check deployment statuses and target state, and determine the
        corresponding application status.

        Returns:
            Status (ApplicationStatus):
                RUNNING: all deployments are healthy or autoscaling.
                DEPLOYING: there is one or more updating deployments,
                    and there are no unhealthy deployments.
                DEPLOY_FAILED: one or more deployments became unhealthy
                    while the application was deploying.
                UNHEALTHY: one or more deployments became unhealthy
                    while the application was running.
                DELETING: the application is being deleted.
            Error message (str):
                Non-empty string if status is DEPLOY_FAILED or UNHEALTHY
        rO   c                 S   r   rn   )rank)r   r@   r@   rA   ro   g  s    z8ApplicationState._determine_app_status.<locals>.<lambda>)keyc                 S      g | ]}|j tjkr|jqS r@   )rN   r   r   r_   .0sr@   r@   rA   
<listcomp>i  
    z:ApplicationState._determine_app_status.<locals>.<listcomp>z!Failed to update the deployments .c                 S   r   r@   )rN   r   	UNHEALTHYr_   r   r@   r@   rA   r   s  r   zThe deployments z are UNHEALTHY.)r   r}   r)   r   get_deployments_statusesminrN   r   r   r   UPDATINGr   	UPSCALINGDOWNSCALINGstatus_triggerr   CONFIG_UPDATE_STARTEDRUNNING)rY   rj   lowest_rank_statusfailed_deploymentsunhealthy_deployment_namesr@   r@   rA   _determine_app_statusN  s8   






z&ApplicationState._determine_app_statusc              
      s   j du s	 j jrdtjdfS t j jsdtjdfS d j _z(t j j\}}|du r8t	
d j d ndtjd j d| fW S W n3 tya   d j d	t  }dtj|f Y S  tyz   d
 j dt  }dtj|f Y S w z  fdd|D }t| j j} |\ _ _|tjdfW S  tttfy   dtjt f Y S  ty   d j dt  }dtj|f Y S w )a  If necessary, reconcile the in-progress build task.

        Returns:
            Deploy arguments (Dict[str, DeploymentInfo]):
                The deploy arguments returned from the build app task
                and their code version.
            Status (BuildAppStatus):
                NO_TASK_IN_PROGRESS: There is no build task to reconcile.
                SUCCEEDED: Task finished successfully.
                FAILED: An error occurred during execution of build app task
                IN_PROGRESS: Task hasn't finished yet.
            Error message (str):
                Non-empty string if status is DEPLOY_FAILED or UNHEALTHY
        NrO   TzImported and built app 'z' successfully.zDeploying app 'z' failed with exception:
zRuntime env setup for app 'z
' failed:
z7Unexpected error occurred while deploying application 'r   c                    s*   i | ]}|d  t di |d jiqS r   r   r@   )r   r   r   paramsrX   r@   rA   
<dictcomp>  s    z>ApplicationState._reconcile_build_app_task.<locals>.<dictcomp>r   )r   rH   r3   r<   r#   rC   r=   r   r   r   r   r   r?   r   r   r   r   r   rE   r   r   r   r>   r   r   r(   )rY   r   err	error_msgr|   r   r@   rX   rA   _reconcile_build_app_task  sb   	
z*ApplicationState._reconcile_build_app_taskc                 C   sT   d}|  D ]}t|jjrt|jjtr|d7 }q|dkr(td| j ddS )zCheck @serve.ingress of deployments in app.

        Raises: RayServeException if more than one @serve.ingress
            is found among deployments.
        r   r4   3Found multiple FastAPI deployments in application "z`".Please only include one deployment with @serve.ingressin your application to avoid this issue.N)	valuesinspectisclassreplica_configdeployment_def
issubclassr&   r(   r   )rY   r|   num_ingress_deploymentsr   r@   r@   rA   r     s   z+ApplicationState._check_ingress_deploymentsc                 C   s   d}d}d}d}|  D ]}|jdur|j}|d7 }|jdur&|j}|d7 }q|dkr4td| j d|dkrAtd| j d||fS )a  Check route prefixes and docs paths of deployments in app.

        There should only be one non-null route prefix. If there is one,
        set it as the application route prefix. This function must be
        run every control loop iteration because the target config could
        be updated without kicking off a new task.

        Returns: tuple of route prefix, docs path.
        Raises: RayServeException if more than one route prefix or docs
            path is found among deployments.
        r   Nr4   z0Found multiple route prefixes from application "zP", Please specify only one route prefix for the application to avoid this issue.z+Found multiple deployments in application "z" that have a docs path. This may be due to using multiple FastAPI deployments in your application. Please only include one deployment with a docs path in your application to avoid this issue.)r  r   r   r(   r   )rY   r|   num_route_prefixesnum_docs_pathsr   r   r   r@   r@   rA   r     s*   

zApplicationState._check_routesc                 C   s   | j j D ]/\}}t|}|j| j j| j jd | j jr/| j jjr/|j	jdu r/| j jj|j	_| 
|| q|  D ]}|| jvrF| | q:dS )zReconcile target deployments in application target state.

        Ensure each deployment is running on up-to-date info, and
        remove outdated deployments from the application.
        )new_target_capacitynew_target_capacity_directionN)r   r|   r   r   set_target_capacityrF   rG   rE   r   r   r   r   r   r   )rY   r   r   deploy_infor@   r@   rA   _reconcile_target_deployments  s&   


z.ApplicationState._reconcile_target_deploymentsc                 C   s   |   \}}}|tjkr"| j|| jj| jj| jj| jj	| jj
d n|tjkr.| tj| | jjdurD|   |  \}}| || | jjrL|  S dS )a&  Attempts to reconcile this application to match its target state.

        Updates the application status and status message based on the
        current state of the system.

        Returns:
            A boolean indicating whether the application is ready to be
            deleted.
        )r|   rD   r~   r   rF   rG   NF)r  r3   r>   r   r   rD   r   r~   rE   rF   rG   r?   r   r)   r   r|   r  r   r}   r   )rY   infostask_statusmsgrN   
status_msgr@   r@   rA   update8  s&   


zApplicationState.updatec                 C   r   rn   )r   rX   r@   r@   rA   get_checkpoint_data_  s   z$ApplicationState.get_checkpoint_datac                    s     fdd j D } j|S )z(Return all deployment status informationc                    s   g | ]	}t | jd qS r   )r   r   )r   
deploymentrX   r@   rA   r   d  s    z=ApplicationState.get_deployments_statuses.<locals>.<listcomp>)r   r   get_deployment_statuses)rY   deploymentsr@   rX   rA   r   b  s   
z)ApplicationState.get_deployments_statusesc                 C   s   t | j| j| jdS )z)Return the application status informationrP   rQ   )r*   r   r   r   rX   r@   r@   rA   get_application_status_infoj  s
   z,ApplicationState.get_application_status_infoc                    s&    fdd j D }dd | D S )a  Gets detailed info on all live deployments in this application.
        (Does not include deleted deployments.)

        Returns:
            A dictionary of deployment infos. The set of deployment info returned
            may not be the full list of deployments that are part of the application.
            This can happen when the application is still deploying and bringing up
            deployments, or when the application is deleting and some deployments have
            been deleted.
        c              	      s$   i | ]}| j t| jd qS r  )r   get_deployment_detailsr   r   )r   r   rX   r@   rA   r   }  s    z<ApplicationState.list_deployment_details.<locals>.<dictcomp>c                 S   s   i | ]\}}|d ur||qS rn   r@   )r   kvr@   r@   rA   r     s    )r   r   )rY   detailsr@   rX   rA   list_deployment_detailsr  s   
z(ApplicationState.list_deployment_detailsrO   rN   r  c                 C   s8   |r|t jt jfv r|| jkrt| || _|| _d S rn   )r)   r   r   r   r   errorr   )rY   rN   r  r@   r@   rA   r     s   


zApplicationState._update_statusrk   N)rO   )7r8   r9   r:   r;   rJ   r   r   r0   r   propertyr	   r   r   r)   rN   rK   rQ   r   r   r   r.   r~   r{   r   r   r   r1   r   rL   r   r   r   r   r   r   r   r   r   r   r
   r   r3   r  r   r   r  r  r  r   r   r*   r  r/   r!  r   r@   r@   r@   rA   r      s    
(
	
,
	
#
^:E





1$'r   c                
   @   s  e Zd ZdedededefddZdd Zd	e	d
dfddZ
dee	ee f d
dfddZd	e	dee d
dfddZdddddee dedee dee fddZde	d
ee	 fddZde	d
ee fdd Zd	e	d
efd!d"Zd	e	d
efd#d$Zde	d
ee	 fd%d&Zd	e	d
ee	 fd'd(Zd	e	d
ee	 fd)d*Zd	e	d
efd+d,Zd
ee	ef fd-d.Z d	e	d
ee	e!f fd/d0Z"d1d2 Z#d9d3d4Z$d
e%fd5d6Z&d9d7d8Z'dS ):ApplicationStateManagerr   r   kv_storer   c                 C   s0   || _ || _|| _|| _d| _i | _|   d S )NF)r   r   	_kv_storer   _shutting_down_application_states_recover_from_checkpoint)rY   r   r   r&  r   r@   r@   rA   r     s   z ApplicationStateManager.__init__c                 C   s`   | j t}|d ur,t|}| D ]\}}t|| j| j| j	}|
| || j|< qd S d S rn   )r'  r   CHECKPOINT_KEYr   loadsr   r   r   r   r   r   r)  )rY   
checkpointapplication_state_infor   r   	app_stater@   r@   rA   r*    s   

z0ApplicationStateManager._recover_from_checkpointr_   rk   Nc                 C   s    || j vrdS | j |   dS )zDelete application by nameN)r)  r   rY   r_   r@   r@   rA   
delete_app  s   
z"ApplicationStateManager.delete_appname_to_deployment_argsc              
      s   dd | j  D }| D ]`\ }|D ]+}|d}|d u r q||}|d ur;| kr;td| d| d  d ||< q | j vrRt | j| j| j| j  < tj	
tt| j   fdd|D }| j   | qd S )	Nc                 S   s.   i | ]\}}|j d ur|jtjks|j |qS rn   )r   rN   r)   r   r   r   r/  r@   r@   rA   r     s    
z7ApplicationStateManager.deploy_apps.<locals>.<dictcomp>r   zPrefix z is being used by application "z!". Failed to deploy application "z".c                    s(   i | ]}|d  t di |d iqS r   )r   r   r_   r@   rA   r     s    )r)  r   r   r(   r   r   r   r   r!   NUM_APPSr   rJ   rd   r   )rY   r2  live_route_prefixesdeployment_argsdeploy_paramdeploy_app_prefixexisting_app_namer|   r@   r4  rA   deploy_apps  s>   


	


z#ApplicationStateManager.deploy_appsr7  c                 C   s   |  ||i dS )a  Deploy the specified app to the list of deployment arguments.

        This function should only be called if the app is being deployed
        through serve.run instead of from a config.

        Args:
            name: application name
            deployment_args_list: arguments for deploying a list of deployments.

        Raises:
            RayServeException: If the list of deployments is trying to
                use a route prefix that is already used by another application
        N)r;  )rY   r_   r7  r@   r@   rA   r     s   z"ApplicationStateManager.deploy_appr   )r   rF   rG   app_configsr   rF   rG   c          	      C   s   |D ]/}|j | jvr$td|j  d t|j | j| j| jd| j|j < | j|j  j||||d qdd | j	 D }dd |D }|| D ]}| 
| qGtjtt| j dS )	a  Declaratively apply the list of application configs.

        The applications will be reconciled to match the target state of the config.

        Any applications previously deployed declaratively that are *not* present in
        the list will be deleted.
        zDeploying new app 'r   )r   r   )r   c                 S   s    h | ]\}}|j tjkr|qS r@   )r~   r.   r   )r   r_   r/  r@   r@   rA   	<setcomp>  s
    z<ApplicationStateManager.apply_app_configs.<locals>.<setcomp>c                 S   s   h | ]}|j qS r@   r4  )r   
app_configr@   r@   rA   r=  "  s    N)r_   r)  r   r   r   r   r   r   r   r   r1  r!   r5  r   rJ   rd   )	rY   r<  r   rF   rG   r>  existing_appsapps_in_configapp_to_deleter@   r@   rA   apply_app_configs  s,   	z)ApplicationStateManager.apply_app_configsr   c                 C   s   || j vrg S | j | jS )z'Return all deployment names by app name)r)  r   rY   r   r@   r@   rA   get_deployments(  s   
z'ApplicationStateManager.get_deploymentsc                 C   s   || j vrg S | j |  S )z*Return all deployment statuses by app name)r)  r   rC  r@   r@   rA   r   .     
z0ApplicationStateManager.get_deployments_statusesc                 C   s   || j vrtjS | j | jS rn   )r)  r)   NOT_STARTEDrN   r0  r@   r@   rA   get_app_status4  s   
z&ApplicationStateManager.get_app_statusc                 C   s0   || j vrttjd| dddS | j |  S )NzApplication z doesn't existr   r  )r)  r*   r)   rF  r  r0  r@   r@   rA   get_app_status_info:  s   

z+ApplicationStateManager.get_app_status_infoc                 C      | j | jS rn   )r)  r   rC  r@   r@   rA   get_docs_pathC     z%ApplicationStateManager.get_docs_pathc                 C   rI  rn   )r)  r   r0  r@   r@   rA   get_route_prefixF  rK  z(ApplicationStateManager.get_route_prefixc                 C   s   || j vrd S | j | jS rn   )r)  r   r0  r@   r@   rA   get_ingress_deployment_nameI  s   
z3ApplicationStateManager.get_ingress_deployment_namec                 C   rI  rn   )r)  r~   r0  r@   r@   rA   get_app_sourceO  rK  z&ApplicationStateManager.get_app_sourcec                    s    fdd j D S )z5Return a dictionary with {app name: application info}c                    s   i | ]
}| j |  qS r@   )r)  r  )r   r_   rX   r@   rA   r   T  s    z=ApplicationStateManager.list_app_statuses.<locals>.<dictcomp>)r)  rX   r@   rX   rA   list_app_statusesR  s   
z)ApplicationStateManager.list_app_statusesc                 C   s   || j vri S | j |  S )z?Gets detailed info on all deployments in specified application.)r)  r!  r0  r@   r@   rA   r!  Y  rE  z/ApplicationStateManager.list_deployment_detailsc                 C   s|   g }| j  D ]\}}| }|r|| td| d qt|dkr<|D ]}| j |= q(tj	t
t| j  dS dS )zUpdate each application statezApplication 'z' deleted successfully.r   N)r)  r   r  rx   r   debugrd   r!   r5  r   rJ   )rY   apps_to_be_deletedr_   appready_to_be_deletedr   r@   r@   rA   r  _  s   

zApplicationStateManager.updatec                 C   s.   d| _ | j D ]}|  q| jt d S )NT)r(  r)  r  r   r'  r+  )rY   r/  r@   r@   rA   shutdownm  s   
z ApplicationStateManager.shutdownc                 C   s   | j otdd | j D S )zReturn whether all applications have shut down.

        Iterate through all application states and check if all their applications
        are deleted.
        c                 s   s    | ]}|  V  qd S rn   )r   )r   r/  r@   r@   rA   	<genexpr>{  s    
z@ApplicationStateManager.is_ready_for_shutdown.<locals>.<genexpr>)r(  allr)  r  rX   r@   r@   rA   is_ready_for_shutdownu  s   z-ApplicationStateManager.is_ready_for_shutdownc                 C   s6   | j rdS dd | j D }| jtt| dS )z-Write a checkpoint of all application states.Nc                 S   s   i | ]	\}}||  qS r@   )r  r3  r@   r@   rA   r     s    z;ApplicationStateManager.save_checkpoint.<locals>.<dictcomp>)r(  r)  r   r'  putr+  r   rW   )rY   r.  r@   r@   rA   save_checkpoint  s   z'ApplicationStateManager.save_checkpointr#  )(r8   r9   r:   r   r   r    r0   r   r*  rJ   r1  r   r   r;  r   r1   rK   r	   r   rB  rD  r   r   r)   rG  r*   rH  rJ  rL  rM  r.   rN  rO  r/   r!  r  rT  rL   rW  rY  r@   r@   r@   rA   r%    sP    
/
-	

r%  r4   )num_cpus	max_callsr   rD   r_   r   r   rk   c                 C   s^  t dd| dt  |d zuddlm} |rd| nd}td	| d
| d |t| |}g }t||t	
 jd}	d}
|	jD ].}t|jrUt|jtrU|
d7 }
|j|	jk}|t|j|j||j||rjdnd|jd qC|
dkrdd|	j dfW S |dfW S  ty   td Y dS  ty   td| dt   dt f Y S w )a  Import and build a Serve application.

    Args:
        import_path: import path to top-level bound deployment.
        code_version: code version inferred from app config. All
            deployment versions are set to this code version.
        name: application name. If specified, application will be deployed
            without removing existing applications.
        args: Arguments to be passed to the application builder.
        logging_config: the logging config for the build app task.
    Returns:
        Deploy arguments: a list of deployment arguments if application
            was built successfully, otherwise None.
        Error message: a string if an error was raised, otherwise None.
    
controllerbuild__)component_namecomponent_idr   r   ),call_user_app_builder_with_args_if_necessaryz with arguments rO   zImporting application ''r   )r_   default_runtime_envr4   r   N)r_   r  r   r   versionr   r   r  zb". Please only include one deployment with @serve.ingress in your application to avoid this issue.zLExisting config deployment request terminated because of keyboard interrupt.)NNz!Exception importing application 'z'.
)r   osgetpidray.serve._private.apira  r   r   r   r   r   get_runtime_contextr   r  r  r  func_or_classr  r&   r_   ingress_deployment_namerx   r   r   _replica_config_deployment_configr   KeyboardInterruptr   r"  r   r   )r   rD   r_   r   r   ra  args_info_strrR  deploy_args_list	built_appr	  r  
is_ingressr@   r@   rA   r     sh   


r   r|   override_configc                 C   s|  t | } |du r
| S |jdd}|dg }|D ]}d|v r%|d|d< |d }|| vr;td| dt|   | | }|j }|d	 t| |d
dkr}d|d
< t	
  }|dpf|jj}	|	rn||	 t	di ||d< tjd i }
|j}|j}d|v r|di }n|jpi }|d|j}|d|j}|d|j}|dr|d ds|d drtjd t||di }|d|i |j||||d ||
d< |dd || tdi ||
d< |jdi |
| |< | | j}|jdur|j|j k rtd q|dtj}t| t|   D ]}|tjur:|j!dur:||_!q)| S )a  Override deployment infos with options from app config.

    Args:
        app_name: application name
        deployment_infos: deployment info loaded from code
        override_config: application config deployed by user with
            options to override those loaded from code.

    Returns: the updated deployment infos.

    Raises:
        ValueError: If config options have invalid values.
        TypeError: If config options have invalid types.
    NT)exclude_unsetr  max_ongoing_requestsr_   zDeployment 'z' does not exist. Available: user_configured_option_namesnum_replicasautoautoscaling_configr   ray_actor_optionsplacement_group_bundlesplacement_group_strategymax_replicas_per_noder   r   r   )ry  rz  r{  r|  r  r   ziAutoscaling will never happen, because 'max_ongoing_requests' is less than 'target_ongoing_requests' now.r   r@   )"r   dictr   r   rz   r   r   r  setr'   defaultrx  r!   AUTO_NUM_REPLICAS_USEDr   r  r   popry  rz  r{  r|  %DEPLOYMENT_CONTAINER_RUNTIME_ENV_USEDr$   r   rt  get_target_ongoing_requestsr   warningr"   VALUEr%   r  r   )r|   rr  config_dictdeployment_override_optionsr   r   r   original_options
new_configrx  override_optionsr  app_runtime_envoverride_actor_options override_placement_group_bundles!override_placement_group_strategyoverride_max_replicas_per_node
merged_envr   app_route_prefixr  r@   r@   rA   r     s   







r   )`r  rV   loggingre  r   r   copyr   dataclassesr   r   r   enumr   typingr   r   r	   r
   r   r   ray._common.utilsr   ray.exceptionsr   ray.serve._private.build_appr   r   ray.serve._private.commonr   r   r   r   r   r   ray.serve._private.configr   ray.serve._private.constantsr   r   ray.serve._private.deploy_utilsr   r   r   "ray.serve._private.deployment_infor   #ray.serve._private.deployment_stater   !ray.serve._private.endpoint_stater    ray.serve._private.logging_utilsr   #ray.serve._private.storage.kv_storer    ray.serve._private.usager!   ray.serve._private.utilsr"   r#   r$   r%   ray.serve.apir&   ray.serve.configr'   ray.serve.exceptionsr(   ray.serve.generated.serve_pb2r)   rb   r*   r^   r+   r,   rq   r-   rt   ray.serve.schemar.   r/   r0   r1   	ray.typesr2   	getLoggerr   r+  r3   rB   r{   r   r%  r   rJ   r   r   r@   r@   r@   rA   <module>   s     
	A     @ }U

