o
    i)                     @   sR   d 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 G dd dej	Z
dS )zy
ASGI worker for gunicorn.

Provides native asyncio-based ASGI support using gunicorn's own
HTTP parsing infrastructure.
    N)baseASGIProtocolc                       s   e Zd ZdZ fddZedd Z f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d Zd d! Zd"d# Z  ZS )$
ASGIWorkerzASGI worker using asyncio event loop.

    Supports:
    - HTTP/1.1 with keepalive
    - WebSocket connections
    - Lifespan protocol (startup/shutdown hooks)
    - Optional uvloop for improved performance
    c                    sD   t  j|i | | jj| _d | _g | _d| _d | _i | _d| _	d S )Nr   F)
super__init__cfgworker_connectionsloopserversnr_connslifespanstate_quick_shutdown)selfargskwargs	__class__ J/home/ubuntu/.local/lib/python3.10/site-packages/gunicorn/workers/gasgi.pyr      s   

zASGIWorker.__init__c                 C   s   |j dkr|d dS dS )z'Validate configuration for ASGI worker.   zOASGI worker does not use threads configuration. Use worker_connections instead.N)threadswarning)clsr   logr   r   r   check_config)   s   
zASGIWorker.check_configc                    s   |    t   dS )zInitialize the worker process.N)_setup_event_loopr   init_processr   r   r   r   r   0   s   zASGIWorker.init_processc                 C   s   t | jdd}|dkrzddl}d}W n ty   d}Y nw |dkrIzddl}| | _| jd W n tyH   | jd t	 | _Y nw t	 | _| jd	 t	
| j dS )
zSetup the asyncio event loop.	asgi_loopautor   NuvloopasynciozUsing uvloop event loopz-uvloop not available, falling back to asynciozUsing asyncio event loop)getattrr   r"   ImportErrornew_event_loopr
   r   debugr   r#   set_event_loop)r   	loop_typer"   r   r   r   r   6   s(   

zASGIWorker._setup_event_loopc              
   C   s`   z	| j  | _W dS  ty/ } z| jjs | j| | t	|| _W Y d}~dS d}~ww )zLoad the ASGI application.N)
appwsgiasgiSyntaxErrorr   reloadr   	exception_make_error_appstrr   er   r   r   	load_wsgiO   s   zASGIWorker.load_wsgic                    s    fdd}|S )z9Create an error ASGI app for syntax errors during reload.c                    s   | d dkr$|dddgdI d H  |dd    d	I d H  d S | d d
krV| I d H }|d dkr?|ddiI d H  | I d H }|d dkrX|ddiI d H  d S d S d S )Ntypehttpzhttp.response.starti  )s   content-types
   text/plain)r5   statusheaderszhttp.response.bodyzApplication error: )r5   bodyr   zlifespan.startupzlifespan.startup.completezlifespan.shutdownzlifespan.shutdown.complete)encode)scopereceivesendmessage	error_msgr   r   	error_app[   s(   z-ASGIWorker._make_error_app.<locals>.error_appr   )r   r@   rA   r   r?   r   r0   Y   s   zASGIWorker._make_error_appc                 C   s   | j D ]	}t|tj q| jtj| j | jtj| j | jtj	| j | jtj
| j | jtj| j | jtj| j dS )z'Initialize signal handlers for asyncio.N)SIGNALSsignalSIG_DFLr
   add_signal_handlerSIGQUIThandle_quit_signalSIGTERMhandle_exit_signalSIGINTSIGUSR1handle_usr1_signalSIGWINCHhandle_winch_signalSIGABRThandle_abort_signal)r   sr   r   r   init_signalso   s   
zASGIWorker.init_signalsc                 C   s&   d| _ | jsdS d| _| j|  dS )z+Handle SIGQUIT/SIGINT - immediate shutdown.TNF)r   aliver   
worker_intr   r   r   r   rG   }   s
   zASGIWorker.handle_quit_signalc                 C   s
   d| _ dS )z#Handle SIGTERM - graceful shutdown.FN)rS   r   r   r   r   rI      s   
zASGIWorker.handle_exit_signalc                 C   s   | j   dS )z"Handle SIGUSR1 - reopen log files.N)r   reopen_filesr   r   r   r   rL      s   zASGIWorker.handle_usr1_signalc                 C   s   | j d dS )z$Handle SIGWINCH - ignored in worker.zworker: SIGWINCH ignored.N)r   r'   r   r   r   r   rN      s   zASGIWorker.handle_winch_signalc                 C   s    d| _ | j|  td dS )zHandle SIGABRT - abort.Fr   N)rS   r   worker_abortsysexitr   r   r   r   rP      s   zASGIWorker.handle_abort_signalc              
   C   sp   z2z
| j |   W n ty$ } z| jd| W Y d}~nd}~ww W |   dS W |   dS |   w )z Main entry point for the worker.zWorker exception: %sN)r
   run_until_complete_serve	Exceptionr   r/   _cleanupr2   r   r   r   run   s   zASGIWorker.runc                    s  t  jdd}|dkrUddlm} | j j j _z
 j I dH  W n. t	yT } z"|dkr@ j
d| W Y d}~dS  jd	| d _W Y d}~nd}~ww   } jD ]>}z" jj fd
d|j|dddI dH } j|  jd| W q\ t	y } z j
d|| W Y d}~q\d}~ww  js j
d dS z# jrȈ    jt kr jd  ntdI dH   jsW n
 tjy   Y nw   I dH  dS )zMain async serving loop.asgi_lifespanr!   offr   )LifespanManagerNonz ASGI lifespan startup failed: %sz&ASGI lifespan not supported by app: %sc                      s   t  S )Nr   r   r   r   r   <lambda>   s    z#ASGIWorker._serve.<locals>.<lambda>T)socksslreuse_addressstart_servingzASGI server listening on %sz!Failed to create server on %s: %szNo servers could be startedz!Parent changed, shutting down: %s      ?)r$   r   gunicorn.asgi.lifespanr`   r,   r   r   r   startupr[   errorr'   _get_ssl_contextsocketsr
   create_serverrc   r   appendinforS   notifyppidosgetppidr#   sleepCancelledError	_shutdown)r   lifespan_moder`   r3   ssl_contextrc   serverr   r   r   rZ      s^   


zASGIWorker._servec              
      sr  | j d | jD ]}|  q
| js7| jD ]}| jr nztj| ddI dH  W q tjy6   Y qw | j	dkr| js| j
j}| j d| j	 | j | }| j	dkr|| j |k r|| jrh| j d ntdI dH  | j	dkr|| j |k s^| j	dkr| j d	| j	 | jr| jsz| j I dH  W dS  ty } z| j d
| W Y d}~dS d}~ww dS dS )zPerform graceful shutdown.zWorker shutting down...g      ?timeoutNr   z'Waiting for %d connections to finish...zQuick shutdown requestedg?zForcing close of %d connectionsz ASGI lifespan shutdown error: %s)r   ro   r   closer   r#   wait_forwait_closedTimeoutErrorr   r   graceful_timeoutr
   timert   r   r   shutdownr[   rj   )r   ry   r   deadliner3   r   r   r   rv      sB   



zASGIWorker._shutdownc              
   C   s\   | j jsdS zddlm} || j W S  ty- } z| jd| W Y d}~dS d}~ww )zGet SSL context if configured.Nr   )rc   z Failed to create SSL context: %s)r   is_sslgunicornrc   rx   r[   r   rj   )r   rc   r3   r   r   r   rk     s   zASGIWorker._get_ssl_contextc              
   C   s   zGt | j}|D ]}|  q	|rAt j|ddi}| jr;z| jt j|dd W n t jy:   | j	
d Y nw | j| | j  W n ty` } z| j	
d| W Y d}~nd}~ww | jD ]}z|  W qd tyu   Y qdw dS )zClean up resources on exit.return_exceptionsTrg   rz   z#Timeout waiting for tasks to cancelzCleanup error: %sN)r#   	all_tasksr
   cancelgatherr   rY   r}   r   r   r'   r|   r[   rl   )r   pendingtaskr   r3   rQ   r   r   r   r\     s6   

zASGIWorker._cleanup)__name__
__module____qualname____doc__r   classmethodr   r   r   r4   r0   rR   rG   rI   rL   rN   rP   r]   rZ   rv   rk   r\   __classcell__r   r   r   r   r      s(    	


		<'r   )r   r#   rr   rC   rW   gunicorn.workersr   gunicorn.asgi.protocolr   Workerr   r   r   r   r   <module>   s   