o
    wvXje  ã                   @   sÞ   d Z ddlmZmZ ddl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 ddlmZ dd	lmZ d
dlmZ d
dlmZ dZeeƒZejejejZZZeej dd¡ƒZG dd„ dej ƒZ!G dd„ deƒZ"dS )zûPool Autoscaling.

This module implements the internal thread responsible
for growing and shrinking the pool according to the
current autoscale settings.

The autoscale thread is only enabled if
the :option:`celery worker --autoscale` option is used.
é    )Úabsolute_importÚunicode_literalsN)Úsleep)Ú	DummyLock)Ú	bootsteps)Ú	monotonic)Ú
get_logger)ÚbgThreadé   )Ústate)ÚPool)Ú
AutoscalerÚWorkerComponentÚAUTOSCALE_KEEPALIVEé   c                   @   s>   e Zd ZdZdZdZefZdd„ Zdd„ Z	dd	„ Z
d
d„ ZdS )r   z?Bootstep that starts the autoscaler thread/timer in the worker.r   Tc                 K   s   |j | _d |_d S ©N)Ú	autoscaleÚenabledÚ
autoscaler)ÚselfÚwÚkwargs© r   úT/var/www/html/myproject/venv/lib/python3.10/site-packages/celery/worker/autoscale.pyÚ__init__*   ó   
zWorkerComponent.__init__c                 C   s>   | j |j|j|j|j||jrtƒ nd d� }|_|js|S d S )N)ÚworkerÚmutex)ÚinstantiateÚautoscaler_clsÚpoolÚmax_concurrencyÚmin_concurrencyÚuse_eventloopr   r   )r   r   Úscalerr   r   r   Úcreate.   s   ýzWorkerComponent.createc                 C   s*   |j j |jj¡ | |jj|jj¡ d S r   )ÚconsumerÚon_task_messageÚaddr   Úmaybe_scaleÚcall_repeatedlyÚ	keepalive)r   r   Úhubr   r   r   Úregister_with_event_loop6   s   ÿz(WorkerComponent.register_with_event_loopc                 C   s   d|j  ¡ iS )zReturn `Autoscaler` info.r   )r   Úinfo)r   r   r   r   r   r.   <   s   zWorkerComponent.infoN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚlabelÚconditionalr   Úrequiresr   r%   r-   r.   r   r   r   r   r   #   s    r   c                       s¨   e Zd ZdZddedf‡ fdd„	Zdd„ Zd"dd	„Zd"d
d„Zd#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edd„ ƒZed d!„ ƒZ‡  ZS )$r   z,Background thread to autoscale pool workers.r   Nc                    sR   t t| ƒ ¡  || _|pt ¡ | _|| _|| _|| _	d | _
|| _| j	s'J dƒ‚d S )Nzcannot scale down too fast.)Úsuperr   r   r    Ú	threadingÚLockr   r!   r"   r+   Ú_last_scale_upr   )r   r    r!   r"   r   r+   r   ©Ú	__class__r   r   r   D   s   zAutoscaler.__init__c                 C   s:   | j � |  ¡  W d   ƒ n1 sw   Y  tdƒ d S )Ng      ð?)r   r)   r   ©r   r   r   r   ÚbodyR   s   
ÿzAutoscaler.bodyc                 C   sZ   | j }t| j| jƒ}||kr|  || ¡ dS t| j| jƒ}||k r+|  || ¡ dS d S )NT)Ú	processesÚminÚqtyr!   Úscale_upÚmaxr"   Ú
scale_down)r   ÚreqÚprocsÚcurr   r   r   Ú_maybe_scaleW   s   þzAutoscaler._maybe_scalec                 C   s   |   |¡r| j ¡  d S d S r   )rG   r    Úmaintain_pool)r   rD   r   r   r   r)   b   s   
ÿzAutoscaler.maybe_scalec                 C   s�   | j �; |d ur|| jk r|  | j| ¡ |  |¡ || _|d ur1|| jkr.|  || j ¡ || _| j| jfW  d   ƒ S 1 sAw   Y  d S r   )r   r>   Ú_shrinkÚ_update_consumer_prefetch_countr!   Ú_growr"   )r   rB   r?   r   r   r   Úupdatef   s   



$özAutoscaler.updatec                 C   sZ   | j �  | j| }|| jkr|  |¡ || _|  |¡ W d   ƒ d S 1 s&w   Y  d S r   )r   r>   r!   rJ   rK   ©r   ÚnÚnewr   r   r   Úforce_scale_ups   s   


"ûzAutoscaler.force_scale_upc                 C   s^   | j �" | j| }|| jk rt|dƒ| _|  t|| jƒ¡ W d   ƒ d S 1 s(w   Y  d S )Nr   )r   r>   r"   rB   rI   r?   rM   r   r   r   Úforce_scale_down{   s   

"üzAutoscaler.force_scale_downc                 C   s   t ƒ | _|  |¡S r   )r   r9   rK   ©r   rN   r   r   r   rA   ‚   r   zAutoscaler.scale_upc                 C   s*   | j rtƒ | j  | jkr|  |¡S d S d S r   )r9   r   r+   rI   rR   r   r   r   rC   †   s
   
þzAutoscaler.scale_downc                 C   s   t d|ƒ | j |¡ d S )NzScaling up %s processes.)r.   r    ÚgrowrR   r   r   r   rK   ‹   s   
zAutoscaler._growc              
   C   sl   t d|ƒ z	| j |¡ W d S  ty   tdƒ Y d S  ty5 } ztd|dd� W Y d }~d S d }~ww )NzScaling down %s processes.z0Autoscaler won't scale down: all processes busy.zAutoscaler: scale_down: %rT)Úexc_info)r.   r    ÚshrinkÚ
ValueErrorÚdebugÚ	ExceptionÚerror)r   rN   Úexcr   r   r   rI   �   s   
€ÿzAutoscaler._shrinkc                 C   s$   || j  }|r| jj |¡ d S d S r   )r!   r   r&   Ú_update_prefetch_count)r   Únew_maxÚdiffr   r   r   rJ   ˜   s   
ÿÿz*Autoscaler._update_consumer_prefetch_countc                 C   s   | j | j| j| jdœS )N)rB   r?   Úcurrentr@   )r!   r"   r>   r@   r<   r   r   r   r.   Ÿ   s
   üzAutoscaler.infoc                 C   s
   t tjƒS r   )Úlenr   Úreserved_requestsr<   r   r   r   r@   §   s   
zAutoscaler.qtyc                 C   s   | j jS r   )r    Únum_processesr<   r   r   r   r>   «   s   zAutoscaler.processesr   )NN)r/   r0   r1   r2   r   r   r=   rG   r)   rL   rP   rQ   rA   rC   rK   rI   rJ   r.   Úpropertyr@   r>   Ú__classcell__r   r   r:   r   r   A   s*    þ


	
r   )#r2   Ú
__future__r   r   Úosr7   Útimer   Úkombu.asynchronous.semaphorer   Úceleryr   Úcelery.fiver   Úcelery.utils.logr   Úcelery.utils.threadsr	   Ú r   Ú
componentsr   Ú__all__r/   ÚloggerrW   r.   rY   ÚfloatÚenvironÚgetr   ÚStartStopStepr   r   r   r   r   r   Ú<module>   s$   	