§
    Ÿjh¢  ã                   óà   — d Z 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Zddlm	Z	 ddl
mZmZ ddlmZmZmZmZ ddlmZmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z! ddl"m#Z#  G d	„ d
¦  «        Z$dS )z“
Dirty Arbiter Process

Asyncio-based arbiter that manages the dirty worker pool and routes
requests from HTTP workers to available dirty workers.
é    N)Úutilé   )Úget_app_workers_attributeÚparse_dirty_app_spec)Ú
DirtyErrorÚDirtyNoWorkersAvailableErrorÚDirtyTimeoutErrorÚDirtyWorkerError)ÚDirtyProtocolÚmake_error_responseÚmake_responseÚSTASH_OP_PUTÚSTASH_OP_GETÚSTASH_OP_DELETEÚSTASH_OP_KEYSÚSTASH_OP_CLEARÚSTASH_OP_INFOÚSTASH_OP_ENSUREÚSTASH_OP_DELETE_TABLEÚSTASH_OP_TABLESÚSTASH_OP_EXISTSÚMANAGE_OP_ADDÚMANAGE_OP_REMOVE)ÚDirtyWorkerc                   ó  — e Zd ZdZd„ d                     ¦   «         D ¦   «         ZdZd(d„Zd„ Zd„ Z	d	„ Z
d
„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd)d„Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd*d„Zd „ Z d!„ Z!d"„ Z"d#„ Z#d$„ Z$d+d&„Z%d'„ Z&dS ),ÚDirtyArbitera4  
    Dirty arbiter that manages the dirty worker pool.

    The arbiter runs an asyncio event loop and handles:
    - Spawning and managing dirty worker processes
    - Accepting connections from HTTP workers
    - Routing requests to available dirty workers
    - Monitoring worker health via heartbeat
    c                 ó>   — g | ]}t          t          d |z  ¦  «        ‘ŒS )zSIG%s)ÚgetattrÚsignal)Ú.0Úxs     úc/var/www/finuniver-perm.ru/html/student/venv/lib/python3.11/site-packages/gunicorn/dirty/arbiter.pyú
<listcomp>zDirtyArbiter.<listcomp><   s8   € ð Eð Eð E°�w•v˜w¨™{Ñ+Ô+ð Eð Eð Eó    z*HUP QUIT INT TERM TTIN TTOU USR1 USR2 CHLDé   Nc                 ó2  — || _         || _        d| _        t          j        ¦   «         | _        || _        t          j        d¬¦  «        | _	        |p$t          j
                             | j	        d¦  «        | _        i | _        i | _        i | _        i | _        i | _        d| _        d| _        d| _        | j         j        | _        d| _        d| _        i | _        i | _        i | _        i | _        i | _        g | _        i | _        |                       ¦   «          dS )zù
        Initialize the dirty arbiter.

        Args:
            cfg: Gunicorn config
            log: Logger
            socket_path: Path to the arbiter's Unix socket
            pidfile: Well-known PID file location for orphan detection
        Nzgunicorn-dirty-)Úprefixzarbiter.sockr   T)!ÚcfgÚlogÚpidÚosÚgetpidÚppidÚpidfileÚtempfileÚmkdtempÚtmpdirÚpathÚjoinÚsocket_pathÚworkersÚworker_socketsÚworker_connectionsÚworker_queuesÚworker_consumersÚ_worker_rr_indexÚ
worker_ageÚaliveÚdirty_workersÚnum_workersÚ_serverÚ_loopÚ_pending_requestsÚ	app_specsÚapp_worker_mapÚworker_app_mapÚ_app_rr_indicesÚ_pending_respawnsÚstash_tablesÚ_parse_app_specs)Úselfr(   r)   r4   r.   s        r"   Ú__init__zDirtyArbiter.__init__B   s  € ð ˆŒØˆŒØˆŒÝ”I‘K”KˆŒ	ØˆŒõ Ô&Ð.?Ð@Ñ@Ô@ˆŒØ&ð 
­"¬'¯,ª,ØŒK˜ñ+
ô +
ˆÔð ˆŒØ ˆÔØ"$ˆÔØˆÔØ "ˆÔØ !ˆÔØˆŒØˆŒ
Øœ8Ô1ˆÔàˆŒØˆŒ
Ø!#ˆÔð ˆŒà ˆÔà ˆÔà!ˆÔà!#ˆÔð ˆÔð 	×ÒÑÔÐÐÐr$   c                 ó  — | j         j        D ]~}t          |¦  «        \  }}|€D	 t          |¦  «        }n3# t          $ r&}| j                             d||¦  «         Y d}~nd}~ww xY w|||dœ| j        |<   t          ¦   «         | j	        |<   ŒdS )a‹  
        Parse all app specifications from config.

        Populates self.app_specs with parsed information about each app,
        including the import path and worker count limits.

        Worker count priority:
        1. Config override (e.g., "module:Class:2") - highest priority
        2. Class attribute (e.g., workers = 2 on the class)
        3. None (all workers) - default
        Nz,Could not read workers attribute from %s: %s)Úimport_pathÚworker_countÚoriginal_spec)
r(   Ú
dirty_appsr   r   Ú	Exceptionr)   ÚwarningrB   ÚsetrC   )rI   ÚspecrL   rM   Úes        r"   rH   zDirtyArbiter._parse_app_specsy   sÞ   € ð ”HÔ'ð 	5ð 	5ˆDÝ(<¸TÑ(BÔ(BÑ%ˆK˜ð Ð#ðÝ#<¸[Ñ#IÔ#I�L�LøÝ ð ð ð à”H×$Ò$ØFØ# Qñô ð ð ð ð ð ð øøøøðøøøð  +Ø ,Ø!%ð+ð +ˆDŒN˜;Ñ'õ 03©u¬uˆDÔ Ñ,Ð,ð)	5ð 	5s   ¤4´
A$¾AÁA$c                 óv   — d}| j                              ¦   «         D ]}|d         }|�t          ||¦  «        }Œ|S )a  
        Calculate minimum number of workers required by app specs.

        Returns the maximum worker_count across all apps that have limits.
        Apps with worker_count=None don't impose a minimum.

        Returns:
            int: Minimum workers required (at least 1)
        r   rM   )rB   ÚvaluesÚmax)rI   Úmin_requiredrS   rM   s       r"   Ú_get_minimum_workersz!DirtyArbiter._get_minimum_workers›   sL   € ð ˆØ”N×)Ò)Ñ+Ô+ð 	?ð 	?ˆDØ Ô/ˆLØÐ'Ý" <°Ñ>Ô>�øØÐr$   c                 ó&  — g }| j                              ¦   «         D ]t\  }}|d         }t          | j                             |t          ¦   «         ¦  «        ¦  «        }|€|                     |¦  «         ŒY||k     r|                     |¦  «         Œu|S )a�  
        Determine which apps a new worker should load.

        Returns a list of import paths for apps that need more workers.
        Apps with workers=None (all workers) are always included.
        Apps with worker limits are included only if they haven't
        reached their limit yet.

        Returns:
            List of import paths to load, or empty list if no apps need workers
        rM   )rB   ÚitemsÚlenrC   ÚgetrR   Úappend)rI   Ú	app_pathsrL   rS   rM   Úcurrent_workerss         r"   Ú_get_apps_for_new_workerz%DirtyArbiter._get_apps_for_new_worker¬   sž   € ð ˆ	à!%¤×!5Ò!5Ñ!7Ô!7ð 		.ð 		.ÑˆK˜Ø Ô/ˆLÝ! $Ô"5×"9Ò"9¸+ÅsÁuÄuÑ"MÔ"MÑNÔNˆOð Ð#Ø× Ò  Ñ-Ô-Ð-Ð-à  <Ò/Ð/Ø× Ò  Ñ-Ô-Ð-øàÐr$   c                 ó¼   — t          |¦  «        | j        |<   |D ]A}|| j        vrt          ¦   «         | j        |<   | j        |                              |¦  «         ŒBdS )a?  
        Register which apps a worker has loaded.

        Updates both app_worker_map and worker_app_map to track the
        bidirectional relationship between workers and apps.

        Args:
            worker_pid: The PID of the worker
            app_paths: List of app import paths loaded by this worker
        N)ÚlistrD   rC   rR   Úadd©rI   Ú
worker_pidr_   Úapp_paths       r"   Ú_register_worker_appsz"DirtyArbiter._register_worker_appsÇ   sn   € õ +/¨y©/¬/ˆÔ˜JÑ'à!ð 	:ð 	:ˆHØ˜tÔ2Ð2Ð2Ý03±´�Ô# HÑ-ØÔ Ô)×-Ò-¨jÑ9Ô9Ð9Ð9ð	:ð 	:r$   c                 ó˜   — | j                              |g ¦  «        }|D ]+}|| j        v r | j        |                              |¦  «         Œ,dS )zº
        Unregister a worker's apps when it exits.

        Removes the worker from all tracking maps.

        Args:
            worker_pid: The PID of the worker to unregister
        N)rD   ÚpoprC   Údiscardre   s       r"   Ú_unregister_workerzDirtyArbiter._unregister_workerÙ   sf   € ð Ô'×+Ò+¨J¸Ñ;Ô;ˆ	ð "ð 	Bð 	BˆHØ˜4Ô.Ð.Ð.ØÔ# HÔ-×5Ò5°jÑAÔAÐAøð	Bð 	Br$   c                 ó
  — t          j        ¦   «         | _        | j                             d| j        ¦  «         | j        rˆ	 t          | j        d¦  «        5 }|                     t          | j        ¦  «        ¦  «         ddd¦  «         n# 1 swxY w Y   n2# t          $ r%}| j         
                    d|¦  «         Y d}~nd}~ww xY w| j        t           j        d<   | j                             | ¦  «         |                      ¦   «          t!          j        d¦  «         	 t%          j        |                      ¦   «         ¦  «         n# t*          $ r Y nw xY w|                      ¦   «          dS # |                      ¦   «          w xY w)z&Run the dirty arbiter (blocking call).z Dirty arbiter starting (pid: %s)ÚwNzFailed to write PID file: %sÚGUNICORN_DIRTY_SOCKETzdirty-arbiter)r+   r,   r*   r)   Úinfor.   ÚopenÚwriteÚstrÚIOErrorrQ   r4   Úenvironr(   Úon_dirty_startingÚinit_signalsr   Ú_setproctitleÚasyncioÚrunÚ
_run_asyncÚKeyboardInterruptÚ_cleanup_sync)rI   ÚfrT   s      r"   rz   zDirtyArbiter.runê   sÊ  € å”9‘;”;ˆŒØŒ�ŠÐ8¸$¼(ÑCÔCÐCð Œ<ð 	DðDÝ˜$œ,¨Ñ,Ô,ð +°Ø—G’G�C ¤™MœMÑ*Ô*Ð*ð+ð +ð +ñ +ô +ð +ð +ð +ð +ð +ð +øøøð +ð +ð +ð +øøåð Dð Dð DØ”× Ò Ð!?ÀÑCÔCÐCÐCÐCÐCÐCÐCøøøøðDøøøð /3Ô.>�Œ
Ð*Ñ+ð 	Œ×"Ò" 4Ñ(Ô(Ð(ð 	×ÒÑÔÐõ 	Ô˜?Ñ+Ô+Ð+ð	!ÝŒK˜ŸšÑ)Ô)Ñ*Ô*Ð*Ð*øÝ ð 	ð 	ð 	ØˆDð	øøøð ×ÒÑ Ô Ð Ð Ð øˆD×ÒÑ Ô Ð Ð øøøsf   ÁB Á(B
Á>B Â
BÂB ÂBÂB Â
CÂ C Ã CÄ&E ÅE, Å
EÅE, ÅEÅE, Å,Fc                 ó˜  — | j         D ]!}t          j        |t          j        ¦  «         Œ"t          j        t          j        | j        ¦  «         t          j        t          j        | j        ¦  «         t          j        t          j        | j        ¦  «         t          j        t          j        | j        ¦  «         t          j        t          j        | j        ¦  «         t          j        t          j	        | j        ¦  «         t          j        t          j
        | j        ¦  «         t          j        t          j        | j        ¦  «         dS )zSet up signal handlers.N)ÚSIGNALSr   ÚSIG_DFLÚSIGTERMÚ_signal_handlerÚSIGQUITÚSIGINTÚSIGHUPÚSIGUSR1ÚSIGCHLDÚSIGTTINÚSIGTTOU)rI   Úsigs     r"   rw   zDirtyArbiter.init_signals
  sè   € à”<ð 	/ð 	/ˆCÝŒM˜#�vœ~Ñ.Ô.Ð.Ð.åŒ•f”n dÔ&:Ñ;Ô;Ð;ÝŒ•f”n dÔ&:Ñ;Ô;Ð;ÝŒ•f”m TÔ%9Ñ:Ô:Ð:ÝŒ•f”m TÔ%9Ñ:Ô:Ð:ÝŒ•f”n dÔ&:Ñ;Ô;Ð;ÝŒ•f”n dÔ&:Ñ;Ô;Ð;ÝŒ•f”n dÔ&:Ñ;Ô;Ð;ÝŒ•f”n dÔ&:Ñ;Ô;Ð;Ð;Ð;r$   c                 ó¤  ‡ — |t           j        k    r&‰ j        r‰ j                             ˆ fd„¦  «         dS |t           j        k    r‰ j                             ¦   «          dS |t           j        k    r&‰ j        r‰ j                             ˆ fd„¦  «         dS |t           j        k    rV‰ xj	        dz  c_	        ‰ j         
                    d‰ j	        ¦  «         ‰ j        r‰ j                             ˆ fd„¦  «         dS |t           j        k    r’‰                      ¦   «         }‰ j	        |k    r‰ j                             d|¦  «         dS ‰ xj	        dz  c_	        ‰ j         
                    d‰ j	        ¦  «         ‰ j        r‰ j                             ˆ fd	„¦  «         dS d
‰ _        ‰ j        r!‰ j                             ‰ j        ¦  «         dS dS )zHandle signals.c                  óP   •— t          j        ‰                      ¦   «         ¦  «        S ©N)ry   Úcreate_taskÚ_handle_sigchld©rI   s   €r"   ú<lambda>z.DirtyArbiter._signal_handler.<locals>.<lambda>  s   ø€ �GÔ/°×0DÒ0DÑ0FÔ0FÑGÔG€ r$   Nc                  óP   •— t          j        ‰                      ¦   «         ¦  «        S rŽ   )ry   r�   Úreloadr‘   s   €r"   r’   z.DirtyArbiter._signal_handler.<locals>.<lambda>+  s   ø€ �GÔ/°·²±´Ñ>Ô>€ r$   r   z'SIGTTIN: Increasing dirty workers to %sc                  óP   •— t          j        ‰                      ¦   «         ¦  «        S rŽ   ©ry   r�   Úmanage_workersr‘   s   €r"   r’   z.DirtyArbiter._signal_handler.<locals>.<lambda>6  ó   ø€ �GÔ/°×0CÒ0CÑ0EÔ0EÑFÔF€ r$   zASIGTTOU: Cannot decrease below %s workers (required by app specs)z'SIGTTOU: Decreasing dirty workers to %sc                  óP   •— t          j        ‰                      ¦   «         ¦  «        S rŽ   r–   r‘   s   €r"   r’   z.DirtyArbiter._signal_handler.<locals>.<lambda>I  r˜   r$   F)r   rˆ   r@   Úcall_soon_threadsafer‡   r)   Úreopen_filesr†   r‰   r>   rp   rŠ   rY   rQ   r<   Ú	_shutdown)rI   r‹   ÚframeÚmin_workerss   `   r"   rƒ   zDirtyArbiter._signal_handler  s&  ø€ à•&”.Ò Ð àŒzð Ø”
×/Ò/ØGÐGÐGÐGñô ð ð ˆFà•&”.Ò Ð àŒH×!Ò!Ñ#Ô#Ð#ØˆFà•&”-ÒÐàŒzð Ø”
×/Ò/Ø>Ð>Ð>Ð>ñô ð ð ˆFà•&”.Ò Ð àÐÔ Ñ!ÐÔØŒH�MŠMÐCØÔ*ñ,ô ,ð ,àŒzð Ø”
×/Ò/ØFÐFÐFÐFñô ð ð ˆFà•&”.Ò Ð à×3Ò3Ñ5Ô5ˆKØÔ ;Ò.Ð.Ø”× Ò ð.àñô ð ð
 �ØÐÔ Ñ!ÐÔØŒH�MŠMÐCØÔ*ñ,ô ,ð ,àŒzð Ø”
×/Ò/ØFÐFÐFÐFñô ð ð ˆFð ˆŒ
ØŒ:ð 	<ØŒJ×+Ò+¨D¬NÑ;Ô;Ð;Ð;Ð;ð	<ð 	<r$   c                 óJ   — | j         r| j                              ¦   «          dS dS )zInitiate async shutdown.N)r?   Úcloser‘   s    r"   rœ   zDirtyArbiter._shutdownR  s0   € àŒ<ð 	!ØŒL×ÒÑ Ô Ð Ð Ð ð	!ð 	!r$   c              ƒ   ó  K  — t          j        ¦   «         | _        t          j                             | j        ¦  «        rt          j        | j        ¦  «         t          j        | j	        | j        ¬¦  «        ƒ d{V —†| _
        t          j        | j        d¦  «         | j                             d| j        ¦  «         |                      ¦   «         ƒ d{V —† t          j        |                      ¦   «         ¦  «        }	 | j
        4 ƒd{V —† | j
                             ¦   «         ƒ d{V —† ddd¦  «        ƒd{V —† n# 1 ƒd{V —†swxY w Y   n# t           j        t&          f$ r Y nw xY w|                     ¦   «          	 |ƒ d{V —† n# t           j        $ r Y nw xY w|                      ¦   «         ƒ d{V —† dS # |                     ¦   «          	 |ƒ d{V —† n# t           j        $ r Y nw xY w|                      ¦   «         ƒ d{V —† w xY w)z/Main async loop - start server, manage workers.)r2   Ni€  zDirty arbiter listening on %s)ry   Úget_running_loopr@   r+   r2   Úexistsr4   ÚunlinkÚstart_unix_serverÚhandle_clientr?   Úchmodr)   rp   r—   r�   Ú_worker_monitorÚserve_foreverÚCancelledErrorÚRuntimeErrorÚcancelÚstop)rI   Úmonitor_tasks     r"   r{   zDirtyArbiter._run_asyncW  s  è è € åÔ-Ñ/Ô/ˆŒ
õ Œ7�>Š>˜$Ô*Ñ+Ô+ð 	(ÝŒI�dÔ&Ñ'Ô'Ð'õ %Ô6ØÔØÔ!ð
ñ 
ô 
ð 
ð 
ð 
ð 
ð 
ð 
ˆŒõ 	Œ�Ô! 5Ñ)Ô)Ð)àŒ�ŠÐ5°tÔ7GÑHÔHÐHð ×!Ò!Ñ#Ô#Ð#Ð#Ð#Ð#Ð#Ð#Ð#õ Ô*¨4×+?Ò+?Ñ+AÔ+AÑBÔBˆð	Ø”|ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3Ø”l×0Ò0Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Ð2Ð2ð3ð 3ð 3ñ 3ô 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3øøøð 3ð 3ð 3ð 3øøåÔ&­Ð5ð 	ð 	ð 	àˆDð	øøøð ×ÒÑ!Ô!Ð!ðØ"Ð"Ð"Ð"Ð"Ð"Ð"Ð"Ð"øÝÔ)ð ð ð Ø�ðøøøð —)’)‘+”+ÐÐÐÐÐÐÐÐÐøð ×ÒÑ!Ô!Ð!ðØ"Ð"Ð"Ð"Ð"Ð"Ð"Ð"Ð"øÝÔ)ð ð ð Ø�ðøøøð —)’)‘+”+ÐÐÐÐÐÐÐÐøøøs„   Ã>E Ä D=Ä+E Ä=
EÅE Å
EÅE ÅF: ÅE(Å%F: Å'E(Å(F: Æ F	 Æ	FÆFÆ:H	ÇGÇH	ÇG+Ç(H	Ç*G+Ç+H	c              ƒ   ól  K  — | j         rªt          j        d¦  «        ƒ d{V —† t          j        ¦   «         | j        k    r7| j                             d¦  «         d| _         |                      ¦   «          dS |  	                    ¦   «         ƒ d{V —† |  
                    ¦   «         ƒ d{V —† | j         °¨dS dS )z1Periodically check worker health and manage pool.g      ð?Nz+Parent changed, shutting down dirty arbiterF)r<   ry   Úsleepr+   Úgetppidr-   r)   rQ   rœ   Úmurder_workersr—   r‘   s    r"   r¨   zDirtyArbiter._worker_monitor  sâ   è è € àŒjð 	(Ý”- Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$õ Œz‰|Œ|˜tœyÒ(Ð(Ø”× Ò Ð!NÑOÔOÐOØ"�”
Ø—’Ñ Ô Ð Ø�à×%Ò%Ñ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ø×%Ò%Ñ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'Ð'ð Œjð 	(ð 	(ð 	(ð 	(ð 	(r$   c              ƒ   óx   K  — |                       ¦   «          | j        r|                      ¦   «         ƒ d{V —† dS dS )z#Handle SIGCHLD - reap dead workers.N)Úreap_workersr<   r—   r‘   s    r"   r�   zDirtyArbiter._handle_sigchldŽ  sV   è è € à×ÒÑÔÐàŒ:ð 	(Ø×%Ò%Ñ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ð'ð	(ð 	(r$   c              ƒ   óœ  K  — | j                              d¦  «         	 | j        rð	 t          j        |¦  «        ƒ d{V —†}n# t
          j        $ r Y nÃw xY w|                     d¦  «        }|t          j        k    r|  	                    ||¦  «        ƒ d{V —† nv|t          j
        k    r|                      ||¦  «        ƒ d{V —† nI|t          j        k    r|                      ||¦  «        ƒ d{V —† n|                      ||¦  «        ƒ d{V —† | j        °ðn2# t          $ r%}| j                              d|¦  «         Y d}~nd}~ww xY w|                     ¦   «          	 |                     ¦   «         ƒ d{V —† dS # t          $ r Y dS w xY w# |                     ¦   «          	 |                     ¦   «         ƒ d{V —† w # t          $ r Y w w xY wxY w)a
  
        Handle a connection from an HTTP worker.

        Routes requests to available dirty workers and returns responses.
        Supports both regular responses and streaming (chunk-based) responses.
        Also handles stash (shared state) operations.
        z&New client connection from HTTP workerNÚtypezClient connection error: %s)r)   Údebugr<   r   Úread_message_asyncry   ÚIncompleteReadErrorr]   ÚMSG_TYPE_STASHÚhandle_stash_requestÚMSG_TYPE_STATUSÚhandle_status_requestÚMSG_TYPE_MANAGEÚhandle_manage_requestÚroute_requestrP   Úerrorr    Úwait_closed)rI   ÚreaderÚwriterÚmessageÚmsg_typerT   s         r"   r¦   zDirtyArbiter.handle_client•  su  è è € ð 	Œ�ŠÐ?Ñ@Ô@Ð@ð	Ø”*ð >ðÝ$1Ô$DÀVÑ$LÔ$LÐLÐLÐLÐLÐLÐL�G�GøÝÔ2ð ð ð Ø�Eðøøøð #Ÿ;š; vÑ.Ô.�ð �}Ô;Ò;Ð;Ø×3Ò3°G¸VÑDÔDÐDÐDÐDÐDÐDÐDÐDÐDà¥Ô!>Ò>Ð>Ø×4Ò4°W¸fÑEÔEÐEÐEÐEÐEÐEÐEÐEÐEà¥Ô!>Ò>Ð>Ø×4Ò4°W¸fÑEÔEÐEÐEÐEÐEÐEÐEÐEÐEð ×,Ò,¨W°fÑ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=Ð=ð' ”*ð >øøõ( ð 	=ð 	=ð 	=ØŒH�NŠNÐ8¸!Ñ<Ô<Ð<Ð<Ð<Ð<Ð<Ð<øøøøð	=øøøð �LŠL‰NŒNˆNðØ×(Ò(Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*øÝð ð ð Ø��ðøøøøð �LŠL‰NŒNˆNðØ×(Ò(Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*øÝð ð ð Ø�ðøøøøøøs‰   žD ¦A Á D ÁAÁD ÁAÁCD ÄF
 Ä
EÄ E Ä;F
 Å EÅF
 ÅE9 Å9
FÆFÆ
GÆ F;Æ:GÆ;
GÇGÇGÇGc              ƒ   ó  K  — |                      dd¦  «        }|                      d¦  «        }|                      |¦  «        ƒ d{V —†}|€l| j        st          d¦  «        }n(|r| j        rt          |¦  «        }nt          d¦  «        }t          ||¦  «        }t          j        ||¦  «        ƒ d{V —† dS || j	        vr|  
                    |¦  «        ƒ d{V —† | j	        |         }t          j        ¦   «                              ¦   «         }	|                     |||	f¦  «        ƒ d{V —† 	 |	ƒ d{V —† dS # t          $ rH}
t          |t!          d|
› �|¬¦  «        ¦  «        }t          j        ||¦  «        ƒ d{V —† Y d}
~
dS d}
~
ww xY w)aä  
        Route a request to an available dirty worker via queue.

        Each worker has a dedicated queue and consumer task. Requests are
        submitted to the queue and processed sequentially by the consumer.

        For streaming responses, messages (chunks) are forwarded directly
        to the client_writer as they arrive from the worker.

        Args:
            request: Request message dict
            client_writer: StreamWriter to send responses to client
        ÚidÚunknownrg   NzNo dirty workers availablezRequest failed: ©Ú	worker_id)r]   Ú_get_available_workerr5   r   rB   r   r   r   Úwrite_message_asyncr8   Ú_start_worker_consumerry   r¢   Úcreate_futureÚputrP   r
   )rI   ÚrequestÚclient_writerÚ
request_idrg   rf   rÁ   ÚresponseÚqueueÚfuturerT   s              r"   rÀ   zDirtyArbiter.route_request½  s	  è è € ð —[’[  yÑ1Ô1ˆ
Ø—;’;˜zÑ*Ô*ˆð  ×5Ò5°hÑ?Ô?Ð?Ð?Ð?Ð?Ð?Ð?ˆ
ØÐà”<ð AÝ"Ð#?Ñ@Ô@��Øð A˜dœnð Aå4°XÑ>Ô>��å"Ð#?Ñ@Ô@�Ý*¨:°uÑ=Ô=ˆHÝÔ3°MÀ8ÑLÔLÐLÐLÐLÐLÐLÐLÐLØˆFð ˜TÔ/Ð/Ð/Ø×-Ò-¨jÑ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9Ð9àÔ" :Ô.ˆÝÔ)Ñ+Ô+×9Ò9Ñ;Ô;ˆð �iŠi˜ -°Ð8Ñ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9Ð9ð	MØˆLˆLˆLˆLˆLˆLˆLˆLˆLøÝð 	Mð 	Mð 	MÝ*ØÝ Ð!7°AÐ!7Ð!7À:ÐNÑNÔNñô ˆHõ  Ô3°MÀ8ÑLÔLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLøøøøð	Møøøs   Ä,D6 Ä6
FÅ =FÆFc              ƒ   ó¤   ‡ ‡‡K  — t          j        ¦   «         Š‰‰ j        ‰<   ˆˆ ˆfd„}t          j         |¦   «         ¦  «        }|‰ j        ‰<   dS )z3Start a consumer task for a worker's request queue.c               “   ó  •K  — ‰j         rõ	 ‰                     ¦   «         ƒ d {V —†\  } }}	 ‰                     ‰| |¦  «        ƒ d {V —† |                     ¦   «         s|                     d ¦  «         n@# t
          $ r3}|                     ¦   «         s|                     |¦  «         Y d }~nd }~ww xY w‰                     ¦   «          n# ‰                     ¦   «          w xY wn# t          j	        $ r Y d S w xY w‰j         °ód S d S rŽ   )
r<   r]   Ú_execute_on_workerÚdoneÚ
set_resultrP   Úset_exceptionÚ	task_donery   rª   )rÑ   rÒ   rÖ   rT   rÕ   rI   rf   s       €€€r"   Úconsumerz5DirtyArbiter._start_worker_consumer.<locals>.consumerö  s`  øè è € Ø”*ð ðØ;@¿9º9¹;¼;Ð5FÐ5FÐ5FÐ5FÐ5FÐ5FÑ2�G˜]¨Fð
*Ø"×5Ò5Ø&¨°ñô ð ð ð ð ð ð ð ð  &Ÿ{š{™}œ}ð 4Ø"×-Ò-¨dÑ3Ô3Ð3øøÝ$ð 4ð 4ð 4Ø%Ÿ{š{™}œ}ð 4Ø"×0Ò0°Ñ3Ô3Ð3øøøøøøøøøð4øøøð ŸšÑ)Ô)Ð)Ð)ø˜ŸšÑ)Ô)Ð)Ð)øøøÐ)øÝÔ-ð ð ð Ø�E�Eðøøøð ”*ð ð ð ð ð sM   ŒC! «AA2 Á1C Á2
B/Á<)B*Â%C Â*B/Â/C Â2C! ÃCÃC! Ã!C4Ã3C4N)ry   ÚQueuer8   r�   r9   )rI   rf   rÞ   ÚtaskrÕ   s   ``  @r"   rÎ   z#DirtyArbiter._start_worker_consumerñ  so   øøøè è € å”‘”ˆØ).ˆÔ˜:Ñ&ð	ð 	ð 	ð 	ð 	ð 	ð 	õ$ Ô" 8 8¡:¤:Ñ.Ô.ˆØ,0ˆÔ˜jÑ)Ð)Ð)r$   c              ƒ   ó^  K  — |                      dd¦  «        }	 |                      |¦  «        ƒ d{V —†\  }}t          j        ||¦  «        ƒ d{V —† 	 	 t	          j        t          j        |¦  «        | j        j        ¬¦  «        ƒ d{V —†}nY# t          j	        $ rG t          |t          d| j        j        ¦  «        ¦  «        }t          j        ||¦  «        ƒ d{V —† Y dS w xY w|                      d¦  «        }	|	t          j        k    rt          j        ||¦  «        ƒ d{V —† ŒÕ|	t          j        k    rt          j        ||¦  «        ƒ d{V —† dS |	t          j        t          j        fv rt          j        ||¦  «        ƒ d{V —† dS | j                             d|	¦  «         �ŒU# t$          $ ry}
| j                             d	||
¦  «         |                      |¦  «         t          |t+          d
|
› �|¬¦  «        ¦  «        }t          j        ||¦  «        ƒ d{V —† Y d}
~
dS d}
~
ww xY w)a  
        Execute request on a specific worker (called by consumer).

        Handles both regular responses and streaming (chunk-based) responses.
        For streaming, chunk and end messages are forwarded directly to the
        client_writer as they arrive from the worker.
        rÈ   rÉ   NT)ÚtimeoutzWorker timeoutr¶   z$Unknown message type from worker: %sz Error executing on worker %s: %szWorker communication failed: rÊ   )r]   Ú_get_worker_connectionr   rÍ   ry   Úwait_forr¸   r(   Údirty_timeoutÚTimeoutErrorr   r	   ÚMSG_TYPE_CHUNKÚMSG_TYPE_ENDÚMSG_TYPE_RESPONSEÚMSG_TYPE_ERRORr)   rQ   rP   rÁ   Ú_close_worker_connectionr
   )rI   rf   rÑ   rÒ   rÓ   rÃ   rÄ   rÅ   rÔ   rÆ   rT   s              r"   rÙ   zDirtyArbiter._execute_on_worker  sè  è è € ð —[’[  yÑ1Ô1ˆ
ð0	MØ#'×#>Ò#>¸zÑ#JÔ#JÐJÐJÐJÐJÐJÐJ‰NˆF�FÝÔ3°F¸GÑDÔDÐDÐDÐDÐDÐDÐDÐDð!SðÝ$+Ô$4Ý%Ô8¸Ñ@Ô@Ø $¤Ô 6ð%ñ %ô %ð ð ð ð ð ð �G�Gøõ Ô+ð ð ð Ý2Ø"Ý)Ð*:¸D¼HÔ<RÑSÔSñ ô  �Hõ (Ô;¸MÈ8ÑTÔTÐTÐTÐTÐTÐTÐTÐTØ�F�Fðøøøð #Ÿ;š; vÑ.Ô.�ð �}Ô;Ò;Ð;Ý'Ô;¸MÈ7ÑSÔSÐSÐSÐSÐSÐSÐSÐSØð �}Ô9Ò9Ð9Ý'Ô;¸MÈ7ÑSÔSÐSÐSÐSÐSÐSÐSÐSØ�Fð ¥Ô ?Ý -Ô <ð >ð >ð >å'Ô;¸MÈ7ÑSÔSÐSÐSÐSÐSÐSÐSÐSØ�Fð ”× Ò Ð!GÈÑRÔRÐRñC!SøõF ð 	Mð 	Mð 	MØŒH�NŠNÐ=¸zÈ1ÑMÔMÐMØ×)Ò)¨*Ñ5Ô5Ð5Ý*ØÝ Ð!DÀÐ!DÐ!DØ+5ð7ñ 7ô 7ñô ˆHõ
  Ô3°MÀ8ÑLÔLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLøøøøð	MøøøsJ   š:F) Á8B ÂF) ÂAC$Ã F) Ã#C$Ã$A/F) Å5F) ÆF) Æ)
H,Æ3A.H'È'H,c              ƒ   ó®  K  — |r-| j         r&|| j        v rt          | j        |         ¦  «        }n(dS t          | j                             ¦   «         ¦  «        }|sdS |r@| j         r9| j                             |d¦  «        }|dz   t          |¦  «        z  | j        |<   n!| j        }|dz   t          |¦  «        z  | _        ||t          |¦  «        z           S )añ  
        Get an available worker PID using round-robin selection.

        If app_path is provided, only returns workers that have loaded
        that specific app. Uses per-app round-robin to ensure fair
        distribution among eligible workers.

        Args:
            app_path: Optional import path of the target app. If None,
                     returns any worker using global round-robin.

        Returns:
            Worker PID or None if no eligible workers are available.
        Nr   r   )	rB   rC   rc   r5   ÚkeysrE   r]   r\   r:   )rI   rg   Úeligible_pidsÚidxs       r"   rÌ   z"DirtyArbiter._get_available_workerG  sø   è è € ð  ð 	6˜œð 	6ð ˜4Ô.Ð.Ð.Ý $ TÔ%8¸Ô%BÑ CÔ C��ð �tõ ! ¤×!2Ò!2Ñ!4Ô!4Ñ5Ô5ˆMàð 	Ø�4ð ð 	C˜œð 	CØÔ&×*Ò*¨8°QÑ7Ô7ˆCØ.1°A©g½¸]Ñ9KÔ9KÑ-KˆDÔ  Ñ*Ð*àÔ'ˆCØ%(¨1¡Wµ°MÑ0BÔ0BÑ$BˆDÔ!à˜S¥3 }Ñ#5Ô#5Ñ5Ô6Ð6r$   c              ƒ   ó¦  K  — || j         v r| j         |         S | j                             |¦  «        }|st          d|› �¦  «        ‚t	          d¦  «        D ]=}t
          j                             |¦  «        r n-t          j	        d¦  «        ƒ d{V —† Œ>t          d|› �¦  «        ‚t          j
        |¦  «        ƒ d{V —†\  }}||f| j         |<   ||fS )z%Get or create connection to a worker.zNo socket for worker é2   çš™™™™™¹?NzWorker socket not ready: )r7   r6   r]   r   Úranger+   r2   r£   ry   r°   Úopen_unix_connection)rI   rf   r4   Ú_rÃ   rÄ   s         r"   rã   z#DirtyArbiter._get_worker_connectionq  s
  è è € à˜Ô0Ð0Ð0ØÔ*¨:Ô6Ð6àÔ)×-Ò-¨jÑ9Ô9ˆØð 	CÝÐA°ZÐAÐAÑBÔBÐBõ �r‘”ð 	Hð 	HˆAÝŒw�~Š~˜kÑ*Ô*ð Ø�Ý”- Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$Ð$åÐF¸ÐFÐFÑGÔGÐGå&Ô;¸KÑHÔHÐHÐHÐHÐHÐHÐH‰ˆ�Ø/5°vÐ.>ˆÔ 
Ñ+Ø�vˆ~Ðr$   c                 ó~   — || j         v r3| j                              |¦  «        \  }}|                     ¦   «          dS dS )zClose connection to a worker.N)r7   rj   r    )rI   rf   Ú_readerrÄ   s       r"   rë   z%DirtyArbiter._close_worker_connection†  sC   € à˜Ô0Ð0Ð0Ø"Ô5×9Ò9¸*ÑEÔE‰OˆG�VØ�LŠL‰NŒNˆNˆNˆNð 1Ð0r$   c              ƒ   óÄ  K  — |                      dd¦  «        }t          j        ¦   «         }g }| j                             ¦   «         D ]�\  }}	 |j                             ¦   «         }t          ||z
  d¦  «        }	n# t          t          t          f$ r d}	Y nw xY w|                     ||j        t          |dg ¦  «        t          |dd¦  «        |	dœ¦  «         Œ‘|                     d	„ ¬
¦  «         | j        |t!          |¦  «        | j        r&t%          | j                             ¦   «         ¦  «        ng dœ}
t)          ||
¦  «        }t+          j        ||¦  «        ƒ d{V —† dS )zô
        Handle a status query request.

        Returns information about the dirty arbiter and its workers.

        Args:
            message: Status request message
            client_writer: StreamWriter to send response to client
        rÈ   rÉ   é   Nr_   ÚbootedF)r*   ÚageÚappsrú   Úlast_heartbeatc                 ó   — | d         S )Nrû   © )rn   s    r"   r’   z4DirtyArbiter.handle_status_request.<locals>.<lambda>­  s
   € ¨¨%¬€ r$   ©Úkey)Úarbiter_pidr5   rM   rü   )r]   ÚtimeÚ	monotonicr5   r[   ÚtmpÚlast_updateÚroundÚOSErrorÚ
ValueErrorÚAttributeErrorr^   rû   r   Úsortr*   r\   rB   rc   rí   r   r   rÍ   )rI   rÅ   rÒ   rÓ   ÚnowÚworkers_infor*   Úworkerr  rý   ÚresultrÔ   s               r"   r½   z"DirtyArbiter.handle_status_request�  s˜  è è € ð —[’[  yÑ1Ô1ˆ
ÝŒnÑÔˆàˆØœ<×-Ò-Ñ/Ô/ð 	ð 	‰KˆC�ð&Ø$œj×4Ò4Ñ6Ô6�Ý!& s¨[Ñ'8¸!Ñ!<Ô!<��øÝ�Z­Ð8ð &ð &ð &Ø!%���ð&øøøð ×ÒØØ”zÝ ¨°RÑ8Ô8Ý! &¨(°EÑ:Ô:Ø"0ð!ð !ñ ô ð ð ð 	×ÒÐ0Ð0ÐÑ1Ô1Ð1ð  œ8Ø#Ý Ñ-Ô-Ø37´>ÐI•D˜œ×,Ò,Ñ.Ô.Ñ/Ô/Ð/Àrð	
ð 
ˆõ ! ¨VÑ4Ô4ˆÝÔ/°¸xÑHÔHÐHÐHÐHÐHÐHÐHÐHÐHÐHs   Á,A:Á:BÂBc              ƒ   óv  ‡ K  — |                      dd¦  «        }|                      d¦  «        }t          dt          |                      dd¦  «        ¦  «        ¦  «        }	 |t          k    r¤d}t	          |¦  «        D ]G}‰                      ¦   «         }|�‰ xj        dz  c_        |dz  }t          j        d¦  «        ƒ d{V —† ŒH|dk    r#d	d
|ddt          ‰ j
        ¦  «        ‰ j        dœ}�nVd	d
||t          ‰ j
        ¦  «        ‰ j        dœ}�n4|t          k    rê‰                      ¦   «         }	d}
t	          |¦  «        D ]£}‰ j        |	k    r n•t          ‰ j
        ¦  «        dk    r n{‰ xj        dz  c_        t          ‰ j
                             ¦   «         ˆ fd„¬¦  «        }‰                      |t           j        ¦  «         |
dz  }
t          j        d¦  «        ƒ d{V —† Œ¤d	d||
t          ‰ j
        ¦  «        ‰ j        dœ}n?t%          d|› �¦  «        }t'          ||¦  «        }t)          j        ||¦  «        ƒ d{V —† dS ‰ j                             d|t          k    rd
nd||                      d|                      dd¦  «        ¦  «        ¦  «         t1          ||¦  «        }t)          j        ||¦  «        ƒ d{V —† dS # t2          $ rk}‰ j                             d|¦  «         t'          |t%          t7          |¦  «        ¦  «        ¦  «        }t)          j        ||¦  «        ƒ d{V —† Y d}~dS d}~ww xY w)zý
        Handle a worker management request.

        Supports adding or removing dirty workers via protocol messages.

        Args:
            message: Manage request message
            client_writer: StreamWriter to send response to client
        rÈ   rÉ   Úopr   Úcountr   Nrò   Trd   z)All apps have reached their worker limits)ÚsuccessÚ	operationÚ	requestedÚspawnedÚreasonÚtotal_workersÚtarget_workers)r  r  r  r  r  r  c                 ó(   •— ‰j         |          j        S rŽ   ©r5   rû   ©ÚprI   s    €r"   r’   z4DirtyArbiter.handle_manage_request.<locals>.<lambda>ö  s   ø€ °4´<À´?Ô3F€ r$   r   Úremove)r  r  r  Úremovedr  r  zUnknown manage operation: z6Worker management: %s %d workers (spawned/removed: %d)r  r  zManage operation error: %s)r]   rW   Úintr   ró   Úspawn_workerr>   ry   r°   r\   r5   r   rY   Úminrí   Úkill_workerr   r‚   r   r   r   rÍ   r)   rp   r   rP   rÁ   rs   )rI   rÅ   rÒ   rÓ   r  r  r  rõ   r  rž   r  Ú
oldest_pidrÁ   rÔ   rT   s   `              r"   r¿   z"DirtyArbiter.handle_manage_request¹  sÑ  øè è € ð —[’[  yÑ1Ô1ˆ
Ø�[Š[˜ÑÔˆÝ�A•s˜7Ÿ;š; w°Ñ2Ô2Ñ3Ô3Ñ4Ô4ˆðN	MØ•]Ò"Ð"à�Ý˜u™œð -ð -�AØ!×.Ò.Ñ0Ô0�FØÐ)ØÐ(Ô(¨AÑ-Ð(Ô(Ø 1™˜Ý!œ-¨Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ð,ð ˜a’<�<à#'Ø%*Ø%*Ø#$Ø"MÝ),¨T¬\Ñ):Ô):Ø*.Ô*:ðð �F‘Fð $(Ø%*Ø%*Ø#*Ý),¨T¬\Ñ):Ô):Ø*.Ô*:ðð �F‘Fð Õ'Ò'Ð'à"×7Ò7Ñ9Ô9�Ø�å˜u™œð -ð -�AØÔ'¨;Ò6Ð6Ø˜Ý˜4œ<Ñ(Ô(¨AÒ-Ð-Ø˜àÐ$Ô$¨Ñ)Ð$Ô$õ "% T¤\×%6Ò%6Ñ%8Ô%8Ø)FÐ)FÐ)FÐ)Fð"Hñ "Hô "H�Jà×$Ò$ Zµ´Ñ@Ô@Ð@Ø˜q‘L�GÝ!œ-¨Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ð,ð  $Ø!)Ø!&Ø&Ý%(¨¬Ñ%6Ô%6Ø&*Ô&6ðð ��õ #Ð#DÀÐ#DÐ#DÑEÔE�Ý.¨z¸5ÑAÔA�Ý#Ô7¸ÀxÑPÔPÐPÐPÐPÐPÐPÐPÐPØ�àŒH�MŠMÐRØ#%­Ò#6Ð#6˜%˜%¸HØØ Ÿ*š* Y°·
²
¸9ÀaÑ0HÔ0HÑIÔIñKô Kð Kõ
 % Z°Ñ8Ô8ˆHÝÔ3°MÀ8ÑLÔLÐLÐLÐLÐLÐLÐLÐLÐLÐLøåð 	Mð 	Mð 	MØŒH�NŠNÐ7¸Ñ;Ô;Ð;Ý*¨:µzÅ#ÀaÁ&Ä&Ñ7IÔ7IÑJÔJˆHÝÔ3°MÀ8ÑLÔLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLøøøøð	Møøøs!   Á!G!K ÉA=K Ë
L8ËA L3Ì3L8c           	   ƒ   ód  ‡K  — |                      dd¦  «        }|                      d¦  «        }|                      dd¦  «        }|                      d¦  «        }|                      d¦  «        }|                      d¦  «        Š	 d	}|t          k    r'|| j        vr
i | j        |<   || j        |         |<   d
}�n#|t          k    r9|| j        vrddi}�n	|| j        |         vrddi}�nô| j        |         |         }�nß|t          k    r.|| j        v r!|| j        |         v r| j        |         |= d
}�nªd}�n¦|t
          k    rM|| j        vrg }�nŽt          | j        |                              ¦   «         ¦  «        }	‰rˆfd„|	D ¦   «         }	|	}�nN|t          k    r,|| j        v r| j        |          	                    ¦   «          d
}�n|t          k    r,|| j        vrddi}nþt          | j        |         ¦  «        |dœ}nà|t          k    r|| j        vr
i | j        |<   d
}n¿|t          k    r|| j        v r| j        |= d
}n d}n�|t          k    r't          | j                             ¦   «         ¦  «        }nk|t          k    r!|| j        vrd}nT|€d
}nO|| j        |         v }n?t!          d|› �¦  «        }
t#          ||
¦  «        }t%          j        ||¦  «        ƒ d	{V —† d	S t)          |t*          ¦  «        rœd|v r˜|d         }|dk    rt!          d|› �¦  «        }
n5|dk    rt!          d|› �¦  «        }
nt!          t-          |¦  «        ¦  «        }
d|                     ¦   «                              dd¦  «        › d�|
_        t#          ||
¦  «        }nt5          ||¦  «        }t%          j        ||¦  «        ƒ d	{V —† d	S # t6          $ rk}| j                             d|¦  «         t#          |t!          t-          |¦  «        ¦  «        ¦  «        }t%          j        ||¦  «        ƒ d	{V —† Y d	}~d	S d	}~ww xY w)a!  
        Handle a stash operation directly in the arbiter.

        All stash tables are stored in arbiter memory for simplicity
        and fast access.

        Args:
            message: Stash operation message
            client_writer: StreamWriter to send response to client
        rÈ   rÉ   r  ÚtableÚ r  ÚvalueÚpatternNTrÁ   Úkey_not_foundFc                 óX   •— g | ]&}t          j         t          |¦  «        ‰¦  «        ¯$|‘Œ'S rÿ   )Úfnmatchrs   )r    Úkr)  s     €r"   r#   z5DirtyArbiter.handle_stash_request.<locals>.<listcomp>H  sF   ø€ ð $Ið $Ið $I¨!Ý'.¤µs¸1±v´v¸wÑ'GÔ'Gð$I Að $Ið $Ið $Ir$   Útable_not_found)Úsizer&  zUnknown stash operation: zTable not found: zKey not found: ÚStashrõ   ÚErrorzStash operation error: %s)r]   r   rG   r   r   r   rc   rí   r   Úclearr   r\   r   r   r   r   r   r   r   rÍ   Ú
isinstanceÚdictrs   ÚtitleÚreplaceÚ
error_typer   rP   r)   rÁ   )rI   rÅ   rÒ   rÓ   r  r&  r  r(  r  Úall_keysrÁ   rÔ   r7  rT   r)  s                 @r"   r»   z!DirtyArbiter.handle_stash_request  s	  øè è € ð —[’[  yÑ1Ô1ˆ
Ø�[Š[˜ÑÔˆØ—’˜G RÑ(Ô(ˆØ�kŠk˜%Ñ Ô ˆØ—’˜GÑ$Ô$ˆØ—+’+˜iÑ(Ô(ˆða	MØˆFà•\Ò!Ð!à Ô 1Ð1Ð1Ø/1�DÔ% eÑ,Ø05�Ô! %Ô(¨Ñ-Ø�‘à•|Ò#Ð#Ø Ô 1Ð1Ð1Ø% Ð7�F‘FØ Ô 1°%Ô 8Ð8Ð8Ø% Ð7�F‘Fà!Ô.¨uÔ5°cÔ:�F‘Fà•Ò&Ð&Ø˜DÔ-Ð-Ð-°#¸Ô9JÈ5Ô9QÐ2QÐ2QØÔ)¨%Ô0°Ð5Ø!�F‘Fà"�F‘Fà•}Ò$Ð$Ø Ô 1Ð1Ð1Ø�F‘Få# DÔ$5°eÔ$<×$AÒ$AÑ$CÔ$CÑDÔD�HØð Ið$Ið $Ið $Ið $I¨xð $Iñ $Iô $I˜à%�F‘Fà•~Ò%Ð%Ø˜DÔ-Ð-Ð-ØÔ% eÔ,×2Ò2Ñ4Ô4Ð4Ø�‘à•}Ò$Ð$Ø Ô 1Ð1Ð1Ø%Ð'8Ð9�F�Fõ !$ DÔ$5°eÔ$<Ñ =Ô =Ø!&ðð �F�Fð
 •Ò&Ð&Ø Ô 1Ð1Ð1Ø/1�DÔ% eÑ,Ø��àÕ,Ò,Ð,Ø˜DÔ-Ð-Ð-ØÔ)¨%Ð0Ø!�F�Fà"�F�Fà•Ò&Ð&Ý˜dÔ/×4Ò4Ñ6Ô6Ñ7Ô7��à•Ò&Ð&Ø Ô 1Ð1Ð1Ø"�F�FØ�[Ø!�F�Fà  DÔ$5°eÔ$<Ð<�F�Fõ #Ð#C¸rÐ#CÐ#CÑDÔD�Ý.¨z¸5ÑAÔA�Ý#Ô7¸ÀxÑPÔPÐPÐPÐPÐPÐPÐPÐPØ�õ ˜&¥$Ñ'Ô'ð =¨G°vÐ,=Ð,=Ø# Gœ_�
ØÐ!2Ò2Ð2Ý&Ð'B¸5Ð'BÐ'BÑCÔC�E�EØ ?Ò2Ð2Ý&Ð'>¸Ð'>Ð'>Ñ?Ô?�E�Eå&¥s¨6¡{¤{Ñ3Ô3�EØ#U¨:×+;Ò+;Ñ+=Ô+=×+EÒ+EÀcÈ2Ñ+NÔ+NÐ#UÐ#UÐ#U�Ô Ý.¨z¸5ÑAÔA��å(¨°VÑ<Ô<�åÔ3°MÀ8ÑLÔLÐLÐLÐLÐLÐLÐLÐLÐLÐLøåð 	Mð 	Mð 	MØŒH�NŠNÐ6¸Ñ:Ô:Ð:Ý*¨:µzÅ#ÀaÁ&Ä&Ñ7IÔ7IÑJÔJˆHÝÔ3°MÀ8ÑLÔLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLÐLøøøøð	Møøøs!   ÂIN: ËCN: Î:
P/ÏA P*Ð*P/c              ƒ   ó8  ‡ K  — ‰ j         sdS ‰ j        }‰ j         rht          ‰ j        ¦  «        |k     rP‰                      ¦   «         }|€n9t          j        d¦  «        ƒ d{V —† ‰ j         rt          ‰ j        ¦  «        |k     °Pt          ‰ j        ¦  «        |k    rt          ‰ j                             ¦   «         ˆ fd„¬¦  «        }‰  	                    |t          j        ¦  «         t          j        d¦  «        ƒ d{V —† t          ‰ j        ¦  «        |k    °}dS dS )z%Maintain the number of dirty workers.Nrò   c                 ó(   •— ‰j         |          j        S rŽ   r  r  s    €r"   r’   z-DirtyArbiter.manage_workers.<locals>.<lambda>Ÿ  s   ø€ ¨4¬<¸¬?Ô+>€ r$   r   )r<   r>   r\   r5   r!  ry   r°   r"  rí   r#  r   r‚   )rI   r>   r  r$  s   `   r"   r—   zDirtyArbiter.manage_workersŒ  s@  øè è € àŒzð 	ØˆFàÔ&ˆð Œjð 	%�S ¤Ñ.Ô.°Ò<Ð<Ø×&Ò&Ñ(Ô(ˆFØˆ~àÝ”- Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$ð Œjð 	%�S ¤Ñ.Ô.°Ò<Ð<õ �$”,ÑÔ +Ò-Ð-å˜Tœ\×.Ò.Ñ0Ô0Ø!>Ð!>Ð!>Ð!>ð@ñ @ô @ˆJà×Ò˜Z­¬Ñ8Ô8Ð8Ý”- Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$õ �$”,ÑÔ +Ò-Ð-Ð-Ð-Ð-Ð-r$   Fc                 óÂ  — | j         r| j                              d¦  «        }n=|r't          | j                             ¦   «         ¦  «        }n|                      ¦   «         }|s| j                             d¦  «         dS | xj        dz  c_        t          j
                             | j        d| j        › d�¦  «        }t          | j        | j        || j        | j        |¬¦  «        }t          j        ¦   «         }|dk    rj||_        || j        |<   || j        |<   |                      ||¦  «         | j                             | |¦  «         | j                             d||¦  «         |S t          j        ¦   «         |_        	 t/          j        d	| j        j        › d
�¦  «         |                     ¦   «          t          j        d¦  «         dS # t8          $ r-}t          j        |j        �|j        nd¦  «         Y d}~dS d}~wt<          $ rR | j                             d¦  «         |j         st          j        | j!        ¦  «         t          j        d¦  «         Y dS w xY w)a  
        Spawn a new dirty worker.

        Worker app assignment follows these priorities:
        1. If there are pending respawns (from dead workers), use those apps
        2. Otherwise, determine apps for a new worker based on allocation
        3. If force_all_apps=True, spawn with all apps regardless of limits

        Args:
            force_all_apps: If True, spawn worker with all apps ignoring limits

        Returns:
            Worker PID in parent process, or None if no apps need workers
        r   z)No apps need more workers, skipping spawnNr   zworker-z.sock)rû   r-   r_   r(   r)   r4   z,Spawned dirty worker (pid: %s) with apps: %szdirty-worker [ú]z!Exception in dirty worker process)"rF   rj   rc   rB   rí   ra   r)   r·   r;   r+   r2   r3   r1   r   r*   r(   Úforkr5   r6   rh   Údirty_post_forkrp   r,   r   rx   Ú	proc_nameÚinit_processÚ_exitÚ
SystemExitÚcoderP   Ú	exceptionrú   ÚWORKER_BOOT_ERROR)rI   Úforce_all_appsr_   r4   r  r*   rT   s          r"   r!  zDirtyArbiter.spawn_worker£  sv  € ð  Ô!ð 	8ØÔ.×2Ò2°1Ñ5Ô5ˆIˆIØð 	8å˜Tœ^×0Ò0Ñ2Ô2Ñ3Ô3ˆIˆIð ×5Ò5Ñ7Ô7ˆIàð 	ØŒH�NŠNÐFÑGÔGÐGØ�4àˆŒ˜1ÑˆŒÝ”g—l’lØŒKÐ9 4¤?Ð9Ð9Ð9ñ
ô 
ˆõ Ø”Ø”ØØ”Ø”Ø#ð
ñ 
ô 
ˆõ Œg‰iŒiˆØ�!Š8ˆ8àˆFŒJØ &ˆDŒL˜ÑØ'2ˆDÔ Ñ$ð ×&Ò& s¨IÑ6Ô6Ð6àŒH×$Ò$ T¨6Ñ2Ô2Ð2ØŒH�MŠMÐHØ˜yñ*ô *ð *àˆJõ ”Y‘[”[ˆŒ
ð
	ÝÔÐE°´Ô0BÐEÐEÐEÑFÔFÐFØ×ÒÑ!Ô!Ð!ÝŒH�Q‰KŒKˆKˆKˆKøÝð 	:ð 	:ð 	:ÝŒH˜qœvÐ1�Q”V�V°qÑ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9Ð9øøøøÝð 	ð 	ð 	ØŒH×ÒÐBÑCÔCÐCØ”=ð 1Ý”˜Ô/Ñ0Ô0Ð0ÝŒH�Q‰KŒKˆKˆKˆKˆKð		øøøs    ÆA
G Ç
IÇ"G?Ç?AIÉIc                 óÂ   — 	 t          j        ||¦  «         dS # t          $ r;}|j        t          j        k    r|                      |¦  «         Y d}~dS Y d}~dS d}~ww xY w)zKill a worker by PID.N)r+   Úkillr  ÚerrnoÚESRCHÚ_cleanup_worker)rI   r*   r‹   rT   s       r"   r#  zDirtyArbiter.kill_workerë  s‡   € ð	*ÝŒG�C˜ÑÔÐÐÐøÝð 	*ð 	*ð 	*ØŒw�%œ+Ò%Ð%Ø×$Ò$ SÑ)Ô)Ð)Ð)Ð)Ð)Ð)Ð)Ð)ð &Ð%Ð%Ð%Ð%Ð%øøøøð	*øøøs   ‚ ™
A£*AÁAc                 óª  — |                       |¦  «         || j        v r'| j        |                              ¦   «          | j        |= | j                             |d¦  «         || j        v r6t          | j        |         ¦  «        }|r| j                             |¦  «         |  	                    |¦  «         | j
                             |d¦  «        }|r| j                             | |¦  «         | j                             |d¦  «        }|rGt          j                             |¦  «        r*	 t          j        |¦  «         dS # t$          $ r Y dS w xY wdS dS )z¤
        Clean up after a worker exits.

        Saves the dead worker's app list to pending respawns so the
        replacement worker gets the same apps.
        N)rë   r9   r¬   r8   rj   rD   rc   rF   r^   rl   r5   r(   Údirty_worker_exitr6   r+   r2   r£   r¤   r  )rI   r*   Ú	dead_appsr  r4   s        r"   rK  zDirtyArbiter._cleanup_workeró  s  € ð 	×%Ò% cÑ*Ô*Ð*ð �$Ô'Ð'Ð'ØÔ! #Ô&×-Ò-Ñ/Ô/Ð/ØÔ% cÐ*ð 	Ô×Ò˜s DÑ)Ô)Ð)ð �$Ô%Ð%Ð%Ý˜TÔ0°Ô5Ñ6Ô6ˆIØð 9ØÔ&×-Ò-¨iÑ8Ô8Ð8ð 	×Ò Ñ$Ô$Ð$à”×!Ò! # tÑ,Ô,ˆØð 	5ØŒH×&Ò& t¨VÑ4Ô4Ð4ØÔ)×-Ò-¨c°4Ñ8Ô8ˆØð 	�2œ7Ÿ>š>¨+Ñ6Ô6ð 	ðÝ”	˜+Ñ&Ô&Ð&Ð&Ð&øÝð ð ð Ø��ðøøøð	ð 	ð 	ð 	s   Ä*E  Å 
EÅEc              ƒ   óü  K  — | j         j        sdS t          | j                             ¦   «         ¦  «        D ]Ä\  }}	 t          j        ¦   «         |j                             ¦   «         z
  | j         j        k    rŒBn# t          t          f$ r Y ŒVw xY w|j        sC| j                             d|¦  «         d|_        |                      |t          j        ¦  «         Œ¤|                      |t          j        ¦  «         ŒÅdS )z!Kill workers that have timed out.NzDIRTY WORKER TIMEOUT (pid:%s)T)r(   rå   rc   r5   r[   r  r  r  r  r  r	  Úabortedr)   Úcriticalr#  r   ÚSIGABRTÚSIGKILL)rI   r*   r  s      r"   r²   zDirtyArbiter.murder_workers  s  è è € àŒxÔ%ð 	ØˆFå ¤× 2Ò 2Ñ 4Ô 4Ñ5Ô5ð 	6ð 	6‰KˆC�ðÝ”>Ñ#Ô# f¤j×&<Ò&<Ñ&>Ô&>Ñ>À$Ä(ÔBXÒXÐXØð Yøå�ZÐ(ð ð ð Ø�ðøøøð ”>ð 6Ø”×!Ò!Ð"AÀ3ÑGÔGÐGØ!%�”Ø× Ò  ¥f¤nÑ5Ô5Ð5Ð5à× Ò  ¥f¤nÑ5Ô5Ð5Ð5ð	6ð 	6s   ½;A:Á:BÂBc                 ó:  — 	 	 t          j        dt           j        ¦  «        \  }}|sdS d}t          j        |¦  «        rt          j        |¦  «        }nDt          j        |¦  «        r0t          j        |¦  «        }| j                             d||¦  «         || j	        k    r| j         
                    d|¦  «         |                      |¦  «         | j                             d|¦  «         Œì# t          $ r!}|j        t          j        k    r‚ Y d}~dS d}~ww xY w)zReap dead worker processes.TéÿÿÿÿNz)Dirty worker (pid:%s) killed by signal %sz$Dirty worker failed to boot (pid:%s)zDirty worker exited (pid:%s))r+   ÚwaitpidÚWNOHANGÚ	WIFEXITEDÚWEXITSTATUSÚWIFSIGNALEDÚWTERMSIGr)   rQ   rE  rÁ   rK  rp   r  rI  ÚECHILD)rI   ÚwpidÚstatusÚexitcoder‹   rT   s         r"   r´   zDirtyArbiter.reap_workers*  s;  € ð	ðDÝ!œz¨"­b¬jÑ9Ô9‘��fØð Ø�Eà�Ý”< Ñ'Ô'ð 0Ý!œ~¨fÑ5Ô5�H�HÝ”^ FÑ+Ô+ð 0Ýœ+ fÑ-Ô-�CØ”H×$Ò$Ð%PØ%)¨3ñ0ô 0ð 0ð ˜tÔ5Ò5Ð5Ø”H—N’NÐ#IÈ4ÑPÔPÐPà×$Ò$ TÑ*Ô*Ð*Ø”—’Ð<¸dÑCÔCÐCð#Døõ$ ð 	ð 	ð 	ØŒw�%œ,Ò&Ð&Øð 'Ð&Ð&Ð&Ð&Ð&øøøøð	øøøs   ‚%C/ ©CC/ Ã/
DÃ9DÄDc              ƒ   óŒ  K  — | j                              d¦  «         t          | j        j        ¦  «        D ]0}|                      ¦   «          t          j        d¦  «        ƒ d{V —† Œ1t          | j	         
                    ¦   «         ¦  «        }|| j        j        d…         D ]"}|                      |t          j        ¦  «         Œ#dS )z!Reload workers (SIGHUP handling).zReloading dirty workersrò   N)r)   rp   ró   r(   r=   r!  ry   r°   rc   r5   rí   r#  r   r‚   )rI   rõ   Úold_workersr*   s       r"   r”   zDirtyArbiter.reloadC  sÑ   è è € àŒ�ŠÐ/Ñ0Ô0Ð0õ �t”xÔ-Ñ.Ô.ð 	%ð 	%ˆAØ×ÒÑÔÐÝ”- Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$Ð$õ ˜4œ<×,Ò,Ñ.Ô.Ñ/Ô/ˆØ˜tœxÔ5Ð6Ð6Ô7ð 	2ð 	2ˆCØ×Ò˜S¥&¤.Ñ1Ô1Ð1Ð1ð	2ð 	2r$   Tc              ƒ   óê  K  — | j                              ¦   «         D ]}|                     ¦   «          Œ|rt          j        nt          j        }t          j        ¦   «         | j        j        z   }t          | j
                             ¦   «         ¦  «        D ]}|                      ||¦  «         Œ| j
        rct          j        ¦   «         |k     rL|                      ¦   «          t          j        d¦  «        ƒ d{V —† | j
        rt          j        ¦   «         |k     °Lt          | j
                             ¦   «         ¦  «        D ]"}|                      |t          j        ¦  «         Œ#|                      ¦   «          dS )zStop all workers.rò   N)r9   rV   r¬   r   r‚   r„   r  r(   Údirty_graceful_timeoutrc   r5   rí   r#  r´   ry   r°   rS  )rI   Úgracefulrà   r‹   Úlimitr*   s         r"   r­   zDirtyArbiter.stopQ  sb  è è € ð Ô)×0Ò0Ñ2Ô2ð 	ð 	ˆDØ�KŠK‰MŒMˆMˆMà (Ð<�fŒnˆn­f¬nˆÝ”	‘”˜dœhÔ=Ñ=ˆõ ˜œ×)Ò)Ñ+Ô+Ñ,Ô,ð 	'ð 	'ˆCØ×Ò˜S #Ñ&Ô&Ð&Ð&ð Œlð 	%�tœy™{œ{¨UÒ2Ð2Ø×ÒÑÔÐÝ”- Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$Ð$ð Œlð 	%�tœy™{œ{¨UÒ2Ð2õ
 ˜œ×)Ò)Ñ+Ô+Ñ,Ô,ð 	2ð 	2ˆCØ×Ò˜S¥&¤.Ñ1Ô1Ð1Ð1Ø×ÒÑÔÐÐÐr$   c                 óŒ  — | j         rOt          j                             | j         ¦  «        r+	 t          j        | j         ¦  «         n# t
          $ r Y nw xY wt          j                             | j        ¦  «        r+	 t          j        | j        ¦  «         n# t
          $ r Y nw xY w	 t          j        | j        ¦  «        D ]9}t          j        t          j         	                    | j        |¦  «        ¦  «         Œ:t          j
        | j        ¦  «         n# t
          $ r Y nw xY w| j                             d| j        ¦  «         dS )zSynchronous cleanup on exit.zDirty arbiter exiting (pid: %s)N)r.   r+   r2   r£   r¤   r  r4   Úlistdirr1   r3   Úrmdirr)   rp   r*   )rI   r~   s     r"   r}   zDirtyArbiter._cleanup_synch  sP  € ð Œ<ð 	�BœGŸNšN¨4¬<Ñ8Ô8ð 	ðÝ”	˜$œ,Ñ'Ô'Ð'Ð'øÝð ð ð Ø�ðøøøõ Œ7�>Š>˜$Ô*Ñ+Ô+ð 	ðÝ”	˜$Ô*Ñ+Ô+Ð+Ð+øÝð ð ð Ø�ðøøøð	Ý”Z ¤Ñ,Ô,ð 8ð 8�Ý”	�"œ'Ÿ,š, t¤{°AÑ6Ô6Ñ7Ô7Ð7Ð7ÝŒH�T”[Ñ!Ô!Ð!Ð!øÝð 	ð 	ð 	ØˆDð	øøøð 	Œ�ŠÐ7¸¼ÑBÔBÐBÐBÐBs6   ­A Á
AÁAÁ<B Â
B#Â"B#Â'A,D Ä
D!Ä D!)NNrŽ   )F)T)'Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úsplitr€   rE  rJ   rH   rY   ra   rh   rl   rz   rw   rƒ   rœ   r{   r¨   r�   r¦   rÀ   rÎ   rÙ   rÌ   rã   rë   r½   r¿   r»   r—   r!  r#  rK  r²   r´   r”   r­   r}   rÿ   r$   r"   r   r   1   sx  € € € € € ðð ðEð EØ;×AÒAÑCÔCðEñ Eô E€Gð Ðð5 ð 5 ð 5 ð 5 ðn 5ð  5ð  5ðDð ð ð"ð ð ð6:ð :ð :ð$Bð Bð Bð"!ð !ð !ð@<ð <ð <ð8<ð 8<ð 8<ðt!ð !ð !ð
&ð &ð &ðP(ð (ð (ð(ð (ð (ð&ð &ð &ðP2Mð 2Mð 2Mðh1ð 1ð 1ð4:Mð :Mð :Mðx(7ð (7ð (7ð (7ðTð ð ð*ð ð ð'Ið 'Ið 'IðR\Mð \Mð \Mð|sMð sMð sMðj%ð %ð %ð.Fð Fð Fð FðP*ð *ð *ð"ð "ð "ðH6ð 6ð 6ð&ð ð ð22ð 2ð 2ðð ð ð ð.Cð Cð Cð Cð Cr$   r   )%rl  ry   rI  r,  r+   r   r/   r  Úgunicornr   Úappr   r   Úerrorsr   r   r	   r
   Úprotocolr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r   rÿ   r$   r"   ú<module>rr     sº  ðð
ð ð €€€Ø €€€Ø €€€Ø 	€	€	€	Ø €€€Ø €€€Ø €€€à Ð Ð Ð Ð Ð à @Ð @Ð @Ð @Ð @Ð @Ð @Ð @ðð ð ð ð ð ð ð ð ð ð ð ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð"  Ð Ð Ð Ð Ð ðOCð OCð OCð OCð OCñ OCô OCð OCð OCð OCr$   