
    &`i~                        d dl Z d dlZd dlZd dl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 d dlmZmZmZmZmZmZm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%m&Z&m'Z'm(Z(m)Z)  ej*        e$          Z+ G d d          Z,e G d de-                      Z. G d de/e          Z0e
 G d d                      Z1e
 G d d                      Z2e
 G d d                      Z3e
 G d d                      Z4deeeeef         f         deeef         fdZ5 G d de          Z6 G d  d!e6          Z7dS )"    N)ABCabstractmethod)defaultdict)	dataclass)Enum)total_ordering)AnyCallableDictListOptionalSetTuple)ClusterNodeInfoCache)CreatePlacementGroupRequestDeploymentID	ReplicaID)ReplicaConfig)(RAY_SERVE_HIGH_PRIORITY_CUSTOM_RESOURCES)RAY_SERVE_USE_COMPACT_SCHEDULING_STRATEGY&RAY_SERVE_USE_PACK_SCHEDULING_STRATEGYSERVE_LOGGER_NAME)LabelMatchExpressionsTNodeAffinitySchedulingStrategyNodeLabelSchedulingStrategy PlacementGroupSchedulingStrategyc                       e Zd ZdZdS ) SpreadDeploymentSchedulingPolicyz;A scheduling policy that spreads replicas with best effort.N)__name__
__module____qualname____doc__     {/home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/ray/serve/_private/deployment_scheduler.pyr   r   $   s        EEDr$   r   c                   b     e Zd ZU eZee         ed<   dZdef fdZ	d Z
d Zd Zd Zd	 Z xZS )
	ResourcesCUSTOM_PRIORITYg&.>keyc                     t                                          |          }||S |                    t          j        j                  rdS dS )N   r   )superget
startswithray_rayletIMPLICIT_RESOURCE_PREFIX)selfr)   val	__class__s      r%   r-   zResources.get0   sI    ggkk#?J >>#+>?? 	1 qr$   c                      t                                                     t                                                    z  }t           fd|D                       S )Nc              3      K   | ]8}                     |          j        z                        |          k    V  9d S N)r-   EPSILON.0kotherr2   s     r%   	<genexpr>z$Resources.can_fit.<locals>.<genexpr>?   sC      LL!488A;;-1=LLLLLLr$   setkeysallr2   r<   r@   s   `` r%   can_fitzResources.can_fit<   sT    499;;#ejjll"3"33LLLLLtLLLLLLr$   c                      t                                                     t                                                    z  }t           fd|D                       S )Nc                 h    g | ].}                     |                               |          k    /S r#   r-   r9   s     r%   
<listcomp>z$Resources.__eq__.<locals>.<listcomp>C   s2    >>>ADHHQKK599Q<</>>>r$   r>   rB   s   `` r%   __eq__zResources.__eq__A   sT    499;;#ejjll"3"33>>>>>>>>???r$   c                    t          |                                           t          |                                          z  }t                      }|D ]}|                    t          j        j                  r=t          d|                     |          |                    |          z             ||<   c|                     |          |                    |          z   ||<   t          |          S )N      ?)
r?   r@   dictr.   r/   r0   r1   minr-   r'   )r2   r<   r@   kwargsr)   s        r%   __add__zResources.__add__E   s    499;;#ejjll"3"33 	= 	=C~~ckBCC =!#txx}}uyy~~'EFFs"hhsmmeiinn<s   r$   c                      t                                                     t                                                    z  } fd|D             }t          |          S )Nc                 h    i | ].}|                     |                               |          z
  /S r#   rF   )r:   r)   r<   r2   s     r%   
<dictcomp>z%Resources.__sub__.<locals>.<dictcomp>S   s4    FFF##txx}}uyy~~5FFFr$   )r?   r@   r'   )r2   r<   r@   rM   s   ``  r%   __sub__zResources.__sub__Q   sX    499;;#ejjll"3"33FFFFFFFF   r$   c                    t          |                                           t          |                                          z  }|h dz
  }| j        D ]`}|                     |          |                    |          k     r dS |                     |          |                    |          k    r dS a|                     d          |                    d          k     rdS |                     d          |                    d          k    rdS |                     d          |                    d          k     rdS |                     d          |                    d          k    rdS |                     d          |                    d          k     rdS |                     d          |                    d          k    rdS |t          | j                  z
  D ]`}|                     |          |                    |          k     r dS |                     |          |                    |          k    r dS adS )a  Determines priority when sorting a list of SoftResources.
        1. Custom resources defined in RAY_SERVE_HIGH_PRIORITY_CUSTOM_RESOURCES (sorted by priority)
        2. GPU
        3. CPU
        4. memory
        5. Other custom resources
        This means a resource with a larger number of high-priority resources is always
        sorted higher than one with fewer, regardless of other types.
        >   CPUGPUmemoryTFrU   rT   rV   )r?   r@   r(   r-   )r2   r<   r@   custom_keysr)   s        r%   __lt__zResources.__lt__V   s    499;;#ejjll"3"335555' 	 	Cxx}}uyy~~--tt#3//uu 0 88E??UYYu----4XXe__uyy////588E??UYYu----4XXe__uyy////588H		( 3 3334XXh%))H"5"5555T%9!:!:: 	 	Cxx}}uyy~~--tt#3//uu 0 ur$   )r   r    r!   r   r(   r   str__annotations__r8   r-   rC   rH   rN   rR   rX   __classcell__)r4   s   @r%   r'   r'   *   s          "JOT#YIIIG
s 
 
 
 
 
 
M M M
@ @ @
! 
! 
!! ! !
) ) ) ) ) ) )r$   r'   c                   "    e Zd ZdZdZdZdZdZdS )ReplicaSchedulingRequestStatusz+The status of a replica scheduling request.IN_PROGRESS	SUCCEEDEDACTOR_CREATION_FAILEDPLACEMENT_GROUP_CREATION_FAILEDN)r   r    r!   r"   r^   r_   r`   ra   r#   r$   r%   r]   r]      s,        55KI3&G###r$   r]   c                      e Zd ZU dZeed<   ej        j        ed<   e	ed<   e	ed<   e
ed<   eed<   ej        Zeed<   d	Zeee	eef                           ed
<   d	Zee         ed<   d	Zee         ed<   edefd            Zd	S )ReplicaSchedulingRequestzRequest to schedule a single replica.

    The scheduler is responsible for scheduling
    based on the deployment scheduling policy.
    
replica_id	actor_defactor_resourcesactor_optionsactor_init_argson_scheduledstatusNplacement_group_bundlesplacement_group_strategymax_replicas_per_nodereturnc                 ,   | j         6| j        dk    r+t          d | j         D             t                                S t          | j                  }| j        ;| j        j        }t          j	        j
         |j         d|j         }d| j        z  ||<   |S )a  The resources required to schedule this replica on a node.

        If this replica uses a strict pack placement group, the
        required resources is the sum of the placement group bundles.
        Otherwise, required resources is simply the actor resources.
        NSTRICT_PACKc                 ,    g | ]}t          |          S r#   r'   r:   bundles     r%   rG   z?ReplicaSchedulingRequest.required_resources.<locals>.<listcomp>   s     NNNv6""NNNr$   :rJ   )rk   rl   sumr'   rf   rm   rd   deployment_idr/   r0   r1   app_namename)r2   requiredrw   implicit_resources       r%   required_resourcesz+ReplicaSchedulingRequest.required_resources   s     (4->>NN1MNNN  
 !!566H
 )5 $ ={; E$-E E0=0BE E " /2D4N.N*+Or$   )r   r    r!   r"   r   rZ   r/   actor
ActorClassr   r   r
   r]   r^   rj   rk   r   r   rY   floatrl   rm   intpropertyr'   r|   r#   r$   r%   rc   rc      s           y####-K-WF*WWW AEXd4U
+;&<=DDD.2hsm222+/8C=///I    X  r$   rc   c                   (    e Zd ZU dZeed<   eed<   dS )DeploymentDownscaleRequestz{Request to stop a certain number of replicas.

    The scheduler is responsible for
    choosing the replicas to stop.
    rw   num_to_stopN)r   r    r!   r"   r   rZ   r   r#   r$   r%   r   r      s6            r$   r   c                       e Zd ZU eed<   eed<   dZee         ed<   dZ	ee
e                  ed<   dZee         ed<   dZee         ed<   edefd	            Zdefd
ZdS )DeploymentSchedulingInforw   scheduling_policyNrf   rk   rl   rm   rn   c                     | j         ,| j        dk    r!t          | j         t                                S | j        }| j        r9t          j        j         | j	        j
         d| j	        j         }d| j        z  ||<   |S )a   The resources required to schedule a replica of this deployment on a node.

        If this replicas uses a strict pack placement group, the
        required resources is the sum of the placement group bundles.
        Otherwise, required resources is simply the actor resources.
        Nrp   ru   rJ   )rk   rl   rv   r'   rf   rm   r/   r0   r1   rw   rx   ry   )r2   rz   r{   s      r%   r|   z+DeploymentSchedulingInfo.required_resources   s     (4->>t3Y[[AAA+H
 ) O{; O)2O O595G5LO O " /2D4N.N*+Or$   c                 *    | j         d uo
| j        dk    S )Nrp   )rk   rl   )r2   s    r%   is_non_strict_pack_pgz.DeploymentSchedulingInfo.is_non_strict_pack_pg   s"    (4 ?->	
r$   )r   r    r!   r   rZ   r	   rf   r   r'   rk   r   rl   rY   rm   r   r   r|   boolr   r#   r$   r%   r   r      s         +/OXi(///9=Xd9o6===.2hsm222+/8C=///I    X8
t 
 
 
 
 
 
r$   r   c                   X    e Zd ZU dZdZee         ed<   dZee	ee
f                  ed<   dS )LaunchingReplicaInfoa  Describes a replica for which a schedule request has been sent to
    core but has not been scheduled (placed on a node) yet.

    Args:
        target_node_id: The exact node that's been requested for this
            replica. This is best effort and may not be fulfilled.
        target_labels: The node labels that have been requested for this
            replica. This is best effort and may not be fulfilled.
    Ntarget_node_idtarget_labels)r   r    r!   r"   r   r   rY   rZ   r   r   r	   r#   r$   r%   r   r      sO           %)NHSM(((.2M8DcN+22222r$   r   deployment_to_replicasrn   c                 >    d |                                  D             S )zKFlattens a dict of {deployment_id: {replica_id: val}} to {replica_id: val}.c                 H    i | ]}|                                 D ]\  }}||	 S r#   )items)r:   replicasrd   r3   s       r%   rQ   z_flatten.<locals>.<dictcomp>  sO       '~~//  J 	C   r$   )values)r   s    r%   _flattenr     s/    
 .5577   r$   c            
       :   e Zd ZdZdededefdZdede	dd	fd
Z
dededd	fdZdedd	fdZdedd	fdZdededd	fdZdedd	fdZ	 	 d#dedee         deeeef                  fdZ	 d$dee         deeee         f         fdZdeeef         fdZdedeeef         dee         fdZedeeee         f         deeef         deeee         f         fd            Z	 	 d#dededee         dee          fd Z!ed!e"dee#ee$f                  fd"            Z%d	S )%DeploymentSchedulerz{A centralized scheduler for all Serve deployments.

    It makes a batch of scheduling decisions in each update cycle.
    cluster_node_info_cachehead_node_idcreate_placement_group_fnc                    i | _         t          t                    | _        t          t                    | _        t          t
                    | _        t          t                    | _        || _        || _	        || _
        d S r7   )_deploymentsr   rK   _pending_replicas_launching_replicasr?   _recovering_replicas_running_replicas_cluster_node_info_cache_head_node_id_create_placement_group_fn)r2   r   r   r   s       r%   __init__zDeploymentScheduler.__init__  sz     KM
  	  	  %0$4$4! "-T!2!2(?%)*C'''r$   rw   r   rn   Nc                     || j         vsJ || j        vsJ || j        vsJ || j        vsJ t	          ||          | j        |<   dS )z,Called whenever a new deployment is created.)rw   r   N)r   r   r   r   r   r   )r2   rw   r   s      r%   on_deployment_createdz)DeploymentScheduler.on_deployment_created=  s|     D$:::::D$<<<<<D$=====D$:::::+C';L,
 ,
 ,
-(((r$   replica_configc                     || j         v sJ | j         |         }t          |j                  |_        |j        |_        |j        rd |j        D             |_        |j        r|j        |_        d S d S )Nc                 ,    g | ]}t          |          S r#   rr   rs   s     r%   rG   z>DeploymentScheduler.on_deployment_deployed.<locals>.<listcomp>V  s-     , , ,&,	&!!, , ,r$   )r   r'   resource_dictrf   rm   rk   rl   )r2   rw   r   infos       r%   on_deployment_deployedz*DeploymentScheduler.on_deployment_deployedK  s    
  11111 /()EFF%3%I"1 	, ,0>0V, , ,D( 2 	T,:,SD)))	T 	Tr$   c                 f   | j         |         rJ | j                             |d           | j        |         rJ | j                            |d           | j        |         rJ | j                            |d           | j        |         rJ | j                            |d           | j        |= dS )z(Called whenever a deployment is deleted.N)r   popr   r   r   r   )r2   rw   s     r%   on_deployment_deletedz)DeploymentScheduler.on_deployment_deleted\  s    )-8888""=$777+M:::: $$]D999,];;;;!%%mT:::)-8888""=$777m,,,r$   rd   c                    |j         }| j        |                             |d           | j        |                             |d           | j        |                             |           | j        |                             |d           dS )z6Called whenever a deployment replica is being stopped.N)rw   r   r   r   r   discardr   r2   rd   rw   s      r%   on_replica_stoppingz'DeploymentScheduler.on_replica_stoppingl  s    "0}-11*dCCC /33JEEE!-088DDD}-11*dCCCCCr$   node_idc                     |j         }|| j        |         vsJ | j        |                             |d           | j        |                             |           || j        |         |<   dS )zECalled whenever a deployment replica is running with a known node id.N)rw   r   r   r   r   r   r   )r2   rd   r   rw   s       r%   on_replica_runningz&DeploymentScheduler.on_replica_runningt  su    "0!7!FFFFF /33JEEE!-088DDD<C}-j999r$   c                     |j         }|| j        |         vsJ || j        |         vsJ || j        |         vsJ || j        |         vsJ | j        |                             |           dS )z3Called whenever a deployment replica is recovering.N)rw   r   r   r   r   addr   s      r%   on_replica_recoveringz)DeploymentScheduler.on_replica_recovering~  s    "0!7!FFFFF!9-!HHHHH!7!FFFFF!:=!IIIII!-044Z@@@@@r$   r   r   c                 R    |j         }t          ||          | j        |         |<   d S )Nr   r   )rw   r   r   )r2   rd   r   r   rw   s        r%   _on_replica_launchingz)DeploymentScheduler._on_replica_launching  s8     #0>R)?
 ?
 ?
 /
;;;r$   c                 \   t          t                    }|rA| j        |                                         D ] \  }}||                             |           !nT| j                                        D ]:\  }}|                                D ] \  }}||                             |           !;|S r7   )r   r?   r   r   r   )r2   rw   resrd   r   _r   s          r%   _get_node_to_running_replicasz1DeploymentScheduler._get_node_to_running_replicas  s     # 	1'+'=m'L'R'R'T'T - -#
GG  ,,,,-  $5;;== 1 18+3>>+;+; 1 1'JL$$Z00001 
r$   c                   	
 | j                                         }| j                                         }d |                                D             
d |                                D             | j                                        D ]L\  }}| j        |         }|                                D ]%}|j        }|r|vr|xx         |j        z  cc<   &M| j	                                        D ]C\  }}| j        |         }|                                D ]}|vr|xx         |j        z  cc<   Ddt          dt          fd		
fd| j                                         D             S )a  Gets current available resources per node.

        This returns a conservative view of the available resources
        currently in the cluster. It returns the minimum of:

        1. The available resources per node fetched and cached from the
           GCS every control loop.
        2. The remaining resources left over on each node after
           subtracting the resources taken up by running (already
           scheduled by core) and launching (to-be-scheduled and soft
           targeting that node) replicas.

        Note that (1) may not be accurate because it uses cached info
        and there is a delay from fetching data from GCS, and (2) may
        not be accurate because there can be other actors (not replicas)
        running in the cluster, and launching replicas may not end up on
        the node we're targeting. So the information returned from this
        method is only best effort.
        c                 4    i | ]\  }}|t          |          S r#   rr   )r:   r   rs      r%   rQ   zIDeploymentScheduler._get_available_resources_per_node.<locals>.<dictcomp>  s$    XXXjgqGYq\\XXXr$   c                 4    i | ]\  }}|t          |          S r#   rr   )r:   r   	resourcess      r%   rQ   zIDeploymentScheduler._get_available_resources_per_node.<locals>.<dictcomp>  s6      
  
  
" Yy)) 
  
  
r$   abc                 $   t          |                                           t          |                                          z  }t                      }|D ];}t          |                     |          |                    |                    ||<   <|S r7   )r?   r@   r'   rL   r-   )r   r   r@   r   r)   s        r%   
custom_minzIDeploymentScheduler._get_available_resources_per_node.<locals>.custom_min  sn    qvvxx==3qvvxx==0D++C 7 7quuSzz155::66CJr$   c                     i | ]O}|                      |t                                                     |t                                          PS r#   )r-   r'   )r:   r   r   gcs_infototal_minus_replicass     r%   rQ   zIDeploymentScheduler._get_available_resources_per_node.<locals>.<dictcomp>  se     
 
 

 	 ZZWikk22$(()++>> 
 
 
r$   )r    get_available_resources_per_nodeget_total_resources_per_noder   r   r   r   r   r|   r   r'   get_active_node_ids)r2   available_resourcestotal_resourcesrw   r   
deploymentr   r   r   r   r   r   s            @@@r%   !_get_available_resources_per_nodez5DeploymentScheduler._get_available_resources_per_node  s   , )JJLL 	 7TTVVXX<O<U<U<W<WXXX 
  
&5&;&;&=&= 
  
  
 (,'?'E'E'G'G 	V 	V#M8*=9J )) V V!%!4% ?S)S)S$^444
8UU4444V (,'='C'C'E'E 	O 	O#M8*=9J#??,, O O"666$W---1NN----	O	) 		 	 	 	 	
 
 
 
 
 

  8LLNN
 
 
 	
r$   r|   r   c                 ~    d}d}|D ]5}||                              |          s||         |z
  }|||k     r|}|}6|S )a  Chooses a node using best fit strategy.

        This strategy picks the node where, if the required resources
        were to be scheduled on that node, it will leave the smallest
        remaining space. This minimizes fragmentation of resources.
        N)rC   )r2   r|   r   min_remaining_spacechosen_noder   remaining_spaces          r%   _best_fit_nodez"DeploymentScheduler._best_fit_node  sr     #* 		& 		&G&w/778JKK  2':=OOO"*o@S.S.S&5#%r$   upscales
downscalesc                     t           )a9  Called for each update cycle to do batch scheduling.

        Args:
            upscales: a dict of deployment name to a list of replicas to schedule.
            downscales: a dict of deployment name to a downscale request.

        Returns:
            The name of replicas to stop for each deployment.
        NotImplementedError)r2   r   r   s      r%   schedulezDeploymentScheduler.schedule  s
     "!r$   scheduling_requestdefault_scheduling_strategyc           	         |j         }|j        }d}|}|j        |j        r|j        nd}		 |                     t          |j        |	||j        d                             }
n@# t          $ r3 t          	                    d| d           t          j        |_        Y dS w xY wt          |
d          }d}n,|t          |dd	          }d}n|t          i |
          }d}t!          j        |j                  }|j        <d|vri |d<   d|j        z  |d         t&          j        j         |j         d|j         <   	   |j        j        dd|i|j        |j         }n@# t          $ r3 t          	                    d| d           t          j        |_        Y dS w xY w| j        |         |= |                     |||           t?          |t                    r|j         }t          j!        |_        |"                    ||           dS )aR  Schedule a replica from a scheduling request.

        The following special scheduling strategies will be used, in
        order of highest to lowest priority.
        1. If a replica requires placement groups, we will choose to use
           a `PlacementGroupSchedulingStrategy`. This can also take a
           target node into consideration (soft target), if provided.
           However it cannot take into account target labels.
        2. If a `target_node_id` is provided, we will choose to use a
           `NodeAffinitySchedulingStrategy`.
        3. If `target_labels` is provided, we will choose to use a
           `NodeLabelSchedulingStrategy`.

        Args:
            scheduling_request: A request to schedule a replica.
            default_scheduling_strategy: The scheduling strategy to fall
                back to if no special scheduling strategy is necessary.
            target_node_id: Attempt to schedule this replica onto this
                target node.
            target_labels: Attempt to schedule this replica onto nodes
                with these target labels.
        NPACKry   )bundlesstrategyr   ry   z'Failed to create a placement group for .T)placement_group#placement_group_capture_child_tasks)r   soft_spill_on_unavailable)hardr   r   rJ   ru   scheduling_strategyzFailed to create an actor for r   )r   r#   )#rd   rw   rk   rl   r   r   rg   	Exceptionlogger	exceptionr]   ra   rj   r   r   r   copydeepcopyrm   r/   r0   r1   rx   ry   re   optionsremoterh   r`   r   r   
isinstancer   r_   ri   )r2   r   r   r   r   rd   rw   r   r   rl   pgrg   actor_handles                r%   _schedule_replicaz%DeploymentScheduler._schedule_replica  s   < (2
"095A &>";; %
44/ 2 J!9'5/=fE	     
 
 
   KjKKK   3R #) 
 #C "48# # # !MM'"@&T# # # !MM&"=m# # # "N&8&FGG3?-//-/k* )?? +&;7 A )A A,9,>A A
	?-7?  $7  (8:LL  	 	 	 KjKKKLLL.D % FF	 "=1*=""~] 	# 	
 	
 	
 )+KLL 	B1AO$B$L!''o'VVVVVs#   6A" "9BB?!E! !9FFallow_new_compactionc                     t           )z;Returns a node ID to be compacted and a compaction deadlne.r   r2   r   s     r%   get_node_to_compactz'DeploymentScheduler.get_node_to_compact  s
    
 "!r$   )NNr7   )&r   r    r!   r"   r   rY   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r	   r   r   r   r'   r   r   r   r   rc   r   r   r   r   r   r   r   r   r#   r$   r%   r   r     sX        
D!5D D $,	D D D D@
#
 <
 
	
 
 
 
T#T &T 
	T T T T"-< -D - - - - Di DD D D D DDY D D D D D DA	 Ad A A A A )-26		
 	
	
 !	
  S#X/		
 	
 	
 	
 7; %l3	c3y>!	"   A
4Y3G A
 A
 A
 A
F"+BFsI~BV	#   4 "|T*B%CCD" 'AAB" 
lC	N*	+	" " " ^"( )-:>pW pW4pW &)pW !	pW
   67pW pW pW pWd "$("	%U
#	$" " " ^" " "r$   r   c            	           e Zd Zdeeee         f         deeef         deeee	         f         fdZ
dededee	         fdZded	eeef         dee         fd
Zdedeeeef                  fdZdS )DefaultDeploymentSchedulerr   r   rn   c                 l   |                                 D ]%}|D ] }|j        }|j        }|| j        |         |<   !&t	          d | j                                         D                       }t          rt          j        dt          d           t          r|st          t          | j                                                   d d          }|D ]G}|                     |j        |                                           }	|                     |d|		           HnZ| j                                         D ]@}
|
st#          |
                                           D ]}|                     |d
           Ai }|                                 D ]*}|                     |j        |j                  ||j        <   +|S )a8  Called for each update cycle to do batch scheduling.

        Args:
            upscales: a dict of deployment name to a list of replicas to schedule.
            downscales: a dict of deployment name to a downscale request.

        Returns:
            The IDs of replicas to stop for each deployment.
        c              3   >   K   | ]}|                                 V  d S r7   )r   )r:   ds     r%   r=   z6DefaultDeploymentScheduler.schedule.<locals>.<genexpr>  s?       (
 (
*+A##%%(
 (
 (
 (
 (
 (
r$   zThe environment variable 'RAY_SERVE_USE_COMPACT_SCHEDULING_STRATEGY' is deprecated and will be removed in a v2.55.0 release. Please use 'RAY_SERVE_USE_PACK_SCHEDULING_STRATEGY' instead.   )
stacklevelc                     | j         S r7   )r|   )r   s    r%   <lambda>z5DefaultDeploymentScheduler.schedule.<locals>.<lambda>  s	    a2 r$   T)r)   reverseDEFAULT)r   r   SPREAD)r   r   )r   rd   rw   r   anyr   r   warningswarnDeprecationWarningr   sortedr   _find_best_available_noder|   r   r   list_get_replicas_to_stopr   )r2   r   r   upscaler   rd   rw   non_strict_pack_pgs_existall_scheduling_requeststarget_nodepending_replicasdeployment_to_replicas_to_stop	downscales                r%   r   z#DefaultDeploymentScheduler.schedule  sb     (( 	W 	WG&- W W"/:
 * 8DV&}5jAAW
 %( (
 (
/3/@/G/G/I/I(
 (
 (
 %
 %
! 5 	MO #    2 	:S 	 '-/00779922' ' '# '> 
 
""<<&9::<< 
 &&&09#. '    
 %)$:$A$A$C$C   ' *./?/F/F/H/H*I*I  &**+=4< +     *,&#**,, 	 	I **')>  +'  .-r$   rw   max_num_to_stopc                 D    t                      }t                                           j        |                                          j        |                                          j        |                   }|D ].}|                    |           t          |          |k    r|c S /                                 }t           j
        |                                                   }|                                 t          t                    }|D ] \  }	}
||
                             |	           ! fd}t          |                                |          D ]C\  }}||vr
||         D ]0}	|                    |	           t          |          |k    r|c c S 1D|S )ar  Prioritize replicas running on a node with fewest replicas of
            all deployments.

        This algorithm helps to scale down more intelligently because it can
        relinquish nodes faster. Note that this algorithm doesn't consider
        other non-serve actors on the same node. See more at
        https://github.com/ray-project/ray/issues/20599.
        c                 h    | d         j         k    rt          | d                   nt          j        S )Nr   r+   )r   lensysmaxsize)0node_and_num_running_replicas_of_all_deploymentsr2   s    r%   r)   z=DefaultDeploymentScheduler._get_replicas_to_stop.<locals>.key  s@     DAF%& & DQGHHH [	r$   )r)   )r?   unionr   r@   r   r   r   r  r   r  r   r   r  r   appendr  )r2   rw   r  replicas_to_stop%pending_launching_recovering_replicas$pending_launching_recovering_replica+node_to_running_replicas_of_all_deploymentsordered_running_replicas-ordered_running_replicas_of_target_deploymentrd   replica_node_idr)   r   r   s   `             r%   r  z0DefaultDeploymentScheduler._get_replicas_to_stop  s
    55 14"=16688$]388::%m41
 1
- 3	( 	(0  !EFFF#$$77'''' 8 ..00 	4 $((>}(M(S(S(U(U#V#V  ((***  	6 ,D 	 	'J9/JQQ   	 	 	 	 	 !7==??S
 
 
 
	, 
	,JGQ KKK LGT , ,
 $$Z000'((O;;++++++ <,
  r$   r|   available_resources_per_nodec                    |                                  fd|                                D             }fd|                                D             }|                     ||          }|r|S |                     ||          }|r|S dS )zChooses best available node to schedule the required resources.

        If there are available nodes, returns the node ID of the best
        available node, minimizing fragmentation. Prefers non-idle nodes
        over idle nodes.
        c           	          i | ];\  }}t                              |t                                          d k    8||<S r   r  r-   r?   r:   r   r   node_to_running_replicass      r%   rQ   zHDefaultDeploymentScheduler._find_best_available_node.<locals>.<dictcomp>&  sQ     
 
 
+//??@@1DD SDDDr$   c           	          i | ];\  }}t                              |t                                          d k    8||<S r*  r+  r,  s      r%   rQ   zHDefaultDeploymentScheduler._find_best_available_node.<locals>.<dictcomp>+  sQ     
 
 
+//??@@AEE SEEEr$   N)r   r   r   )r2   r|   r'  non_idle_nodes
idle_nodesr   r-  s         @r%   r  z4DefaultDeploymentScheduler._find_best_available_node  s     $(#E#E#G#G 
 
 
 
 < B B D D
 
 


 
 
 
 < B B D D
 
 

 ))*<nMM 	 ))*<jII 		 	r$   r   c                     d S r7   r#   r   s     r%   r   z.DefaultDeploymentScheduler.get_node_to_compact;  s	     tr$   N)r   r    r!   r   r   r   rc   r   r   r   r   r   r  r'   rY   r   r  r   r   r   r   r#   r$   r%   r   r     s       I.|T*B%CCDI. 'AABI. 
lC	N*	+	I. I. I. I.VA )A <?A 	YA  A  A  A F!%! '+3	>&:! 
#	! ! ! !F$(	%U
#	$     r$   r   )8r   loggingr  r	  abcr   r   collectionsr   dataclassesr   enumr   	functoolsr   typingr	   r
   r   r   r   r   r   r/   *ray.serve._private.cluster_node_info_cacher   ray.serve._private.commonr   r   r   ray.serve._private.configr   ray.serve._private.constantsr   r   r   r   ray.util.scheduling_strategiesr   r   r   r   	getLoggerr   r   rK   r'   rY   r]   rc   r   r   r   r   r   r   r#   r$   r%   <module>r?     s     



  # # # # # # # # # # # # # # ! ! ! ! ! !       $ $ $ $ $ $ B B B B B B B B B B B B B B B B B B 



 K K K K K K         
 4 3 3 3 3 3                       
	,	-	-	 	 	 	 	 	 	 	 T T T T T T T TnH H H H HS$ H H H 3 3 3 3 3 3 3 3l         )
 )
 )
 )
 )
 )
 )
 )
X 3 3 3 3 3 3 3 3	 tIsN/C!CD		)S.	 	 	 	o" o" o" o" o"# o" o" o"du u u u u!4 u u u u ur$   