+
    jh                         R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIH	t	 ^RI
HtHt ^RIHtHtHtHt ^RIHtHtHtHtHtHtHtHtHtHtHtHtHtH t H!t! ^RI"H#t#  ! R R4      t$R# )	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                   l  a ] tR t^1t oRtRP                  4        U u. uF  p \        \        RV ,          4      NK  	  up t^t	R&R lt
R tR tR tR	 tR
 tR tR tR tR tR tR tR tR tR tR tR tR'R ltR tR tR tR tR t R t!R(R lt"R t#R t$R  t%R! t&R" t'R)R# lt(R$ t)R%t*Vt+R# u up i )*DirtyArbitera  
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
z*HUP QUIT INT TERM TTIN TTOU USR1 USR2 CHLDzSIG%sNc                Z   Wn         W n        RV n        \        P                  ! 4       V n        W@n        \        P                  ! RR7      V n	        T;'       g+    \        P                  P                  V P                  R4      V n        / V n        / V n        / V n        / V n        / V n        ^ V n        ^ V n        RV n        V P                   P*                  V n        RV n        RV n        / V n        / V n        / V n        / V n        / V n        . V n        / V n        V PA                  4        R# )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.sockT)!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   r)   r#   s   &&&&&K/var/www/idalgo/venv/lib/python3.14/site-packages/gunicorn/dirty/arbiter.py__init__DirtyArbiter.__init__B   s    IIK	 &&.?@& 
 
"'',,KK+
  "$ " !
8811
!#   !!#  	    c                :   V P                   P                   FL  p\        V4      w  r#Vf    \        V4      pRVRVRV/V P                  V&   \        4       V P                  V&   KN  	  R#   \         d'   pT P
                  P                  RY$4        Rp?L^Rp?ii ; i)aK  
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   warningr7   setr8   )r>   specrD   rE   es   &    r?   r=   DirtyArbiter._parse_app_specsy   s     HH''D(<T(B%K ##<[#IL {+DNN;' 03uD,) ( ! HH$$F# s   A))B4BBc                    ^pV P                   P                  4        F  pVR,          pVf   K  \        W4      pK  	  V# )z
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)
rE   )r7   valuesmax)r>   min_requiredrK   rE   s   &   r?   _get_minimum_workers!DirtyArbiter._get_minimum_workers   sB     NN))+D/L'"<> , rB   c                   . pV P                   P                  4        Fk  w  r#VR,          p\        V P                  P	                  V\        4       4      4      pVf   VP                  V4       KR  WT8  g   KZ  VP                  V4       Km  	  V# )aP  
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
rE   )r7   itemslenr8   getrJ   append)r>   	app_pathsrD   rK   rE   current_workerss   &     r?   _get_apps_for_new_worker%DirtyArbiter._get_apps_for_new_worker   s~     	!%!5!5!7K/L!$"5"5"9"9+su"MNO #  - /  - "8 rB   c                    \        V4      V P                  V&   V FL  pW0P                  9  d   \        4       V P                  V&   V P                  V,          P	                  V4       KN  	  R# )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)listr9   r8   rJ   addr>   
worker_pidrY   app_paths   &&& r?   _register_worker_apps"DirtyArbiter._register_worker_apps   sY     +/y/J'!H22203##H-)--j9 "rB   c                    V P                   P                  V. 4      pV F7  pW0P                  9   g   K  V P                  V,          P                  V4       K9  	  R# )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)r9   popr8   discardr`   s   &&  r?   _unregister_workerDirtyArbiter._unregister_worker   sM     ''++J;	 "H...##H-55jA "rB   c                B   \         P                  ! 4       V n        V P                  P	                  RV P                  4       V P
                  '       dM    \        V P
                  R4      ;_uu_ 4       pVP                  \        V P                  4      4       RRR4       V P                  \         P                  R&   V P                  P                  V 4       V P                  4        \         P"                  ! R4        \$        P&                  ! V P)                  4       4       V P-                  4        R#   + '       g   i     L; i  \         d'   pT P                  P                  RT4        Rp?LRp?ii ; i  \*         d     Lfi ; i  T P-                  4        i ; i)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IOErrorrI   r)   environr   on_dirty_startinginit_signalsr   _setproctitleasynciorun
_run_asyncKeyboardInterrupt_cleanup_sync)r>   frL   s   &  r?   rw   DirtyArbiter.run   s&   99;8$((C <<<D$,,,,GGCM* - /3.>.>

*+ 	""4( 	 	?+	!KK)*  - -, D  !?CCD" ! 		  sZ   E 2%D4E >$E; 4E	?E E E8E33E8;F	F F		F Fc                f   V P                    F(  p\        P                  ! V\        P                  4       K*  	  \        P                  ! \        P                  V P                  4       \        P                  ! \        P
                  V P                  4       \        P                  ! \        P                  V P                  4       \        P                  ! \        P                  V P                  4       \        P                  ! \        P                  V P                  4       \        P                  ! \        P                  V P                  4       \        P                  ! \        P                  V P                  4       \        P                  ! \        P                  V P                  4       R# )zSet up signal handlers.N)SIGNALSsignalSIG_DFLSIGTERM_signal_handlerSIGQUITSIGINTSIGHUPSIGUSR1SIGCHLDSIGTTINSIGTTOU)r>   sigs   & r?   rt   DirtyArbiter.init_signals
  s    <<CMM#v~~.   	fnnd&:&:;fnnd&:&:;fmmT%9%9:fmmT%9%9:fnnd&:&:;fnnd&:&:;fnnd&:&:;fnnd&:&:;rB   c                  a  V\         P                  8X  d4   S P                  '       d    S P                  P                  V 3R l4       R# V\         P                  8X  d   S P
                  P                  4        R# V\         P                  8X  d4   S P                  '       d    S P                  P                  V 3R l4       R# V\         P                  8X  ds   S ;P                  ^,          un	        S P
                  P                  RS P                  4       S P                  '       d    S P                  P                  V 3R l4       R# V\         P                  8X  d   S P                  4       pS P                  V8:  d   S P
                  P                  RV4       R# S ;P                  ^,          un	        S P
                  P                  RS P                  4       S P                  '       d    S P                  P                  V 3R l4       R# R	S n        S P                  '       d(   S P                  P                  S P                  4       R# R# )
zHandle signals.c                  L   < \         P                  ! S P                  4       4      # N)rv   create_task_handle_sigchldr>   s   r?   <lambda>.DirtyArbiter._signal_handler.<locals>.<lambda>  s    G//0D0D0FGrB   Nc                  L   < \         P                  ! S P                  4       4      # r   )rv   r   reloadr   s   r?   r   r   +  s    G//>rB   z'SIGTTIN: Increasing dirty workers to %sc                  L   < \         P                  ! S P                  4       4      # r   rv   r   manage_workersr   s   r?   r   r   6      G//0C0C0EFrB   zASIGTTOU: Cannot decrease below %s workers (required by app specs)z'SIGTTOU: Decreasing dirty workers to %sc                  L   < \         P                  ! S P                  4       4      # r   r   r   s   r?   r   r   I  r   rB   F)r   r   r5   call_soon_threadsafer   r   reopen_filesr   r   r3   rm   r   rR   rI   r1   	_shutdown)r>   r   framemin_workerss   f&& r?   r   DirtyArbiter._signal_handler  s   &.. zzz

//G &.. HH!!#&--zzz

//> &.. !HHMMC**,zzz

//F &.. 335K;.  .
 !HHMMC**,zzz

//F  
:::JJ++DNN; rB   c                b    V P                   '       d   V P                   P                  4        R# R# )zInitiate async shutdown.N)r4   closer   s   &r?   r   DirtyArbiter._shutdownR  s     <<<LL  rB   c                  "   \         P                  ! 4       V n        \        P                  P                  V P                  4      '       d!   \        P                  ! V P                  4       \         P                  ! V P                  V P                  R7      G Rj  xL
 V n
        \        P                  ! V P                  R4       V P                  P                  RV P                  4       V P                  4       G Rj  xL
  \         P                  ! V P!                  4       4      p V P                  ;_uu_4       GRj  xL
  V P                  P#                  4       G Rj  xL
  RRR4      GRj  xL
  TP)                  4         TG Rj  xL
  T P+                  4       G Rj  xL
  R#  EL L Lp LP LB  + GRj  xL 
 '       g   i     LY; i  \         P$                  \&        3 d     Lyi ; i Lf  \         P$                   d     L{i ; i Lk  TP)                  4         TG Rj  xL 
  M  \         P$                   d     Mi ; iT P+                  4       G Rj  xL 
  i ; i5i)z/Main async loop - start server, manage workers.)r'   Ni  zDirty arbiter listening on %s)rv   get_running_loopr5   r    r'   existsr)   unlinkstart_unix_serverhandle_clientr4   chmodr   rm   r   r   _worker_monitorserve_foreverCancelledErrorRuntimeErrorcancelstop)r>   monitor_tasks   & r?   rx   DirtyArbiter._run_asyncW  s    --/
 77>>$**++IId&&' %66!!
 
 	!!5)5t7G7GH !!### **4+?+?+AB	||||ll00222 $| !""" ))+;
 	$ $2 $|||&&5 		 #))   !"""))  ))+s?  BI*F-A#I*?F0 (I*)G F2G F8#F4$F8(G 3F64G 8I*	G7 G5G7 I*&H'I*0I*2G 4F86G 8G	>G?
G	
G	G H G G2/H 1G22H 5G7 7HI*HI*I'&H2+H.,H21I'2I
I'	I

I' I#!I''I*c                  "   V P                   '       d   \        P                  ! R4      G Rj  xL
  \        P                  ! 4       V P
                  8w  d5   V P                  P                  R4       RV n         V P                  4        R# V P                  4       G Rj  xL
  V P                  4       G Rj  xL
  K  R#  L L" L5i)z1Periodically check worker health and manage pool.g      ?Nz+Parent changed, shutting down dirty arbiterF)r1   rv   sleepr    getppidr"   r   rI   r   murder_workersr   r   s   &r?   r   DirtyArbiter._worker_monitor  s     jjj--$$$ zz|tyy(  !NO"
 %%'''%%''' $ ('s9   CCB?A/CCC6C7	CCCc                   "   V P                  4        V P                  '       d   V P                  4       G Rj  xL
  R# R#  L5i)z#Handle SIGCHLD - reap dead workers.N)reap_workersr1   r   r   s   &r?   r   DirtyArbiter._handle_sigchld  s4     :::%%''' 's   6AA	Ac                  "   V P                   P                  R4        V P                  '       d    \        P                  ! V4      G Rj  xL
 pTP                  R4      pT\        P                  8X  d   T P                  Y24      G Rj  xL
  Kr  T\        P                  8X  d   T P                  Y24      G Rj  xL
  K  T\        P                  8X  d   T P                  Y24      G Rj  xL
  K  T P                  Y24      G Rj  xL
  K   VP#                  4         VP%                  4       G Rj  xL
  R#  L  \
        P                   d     KE  i ; i L L Lo LV  \         d'   pT P                   P!                  RT4        Rp?L}Rp?ii ; i L`  \         d     R# i ; i  TP#                  4         TP%                  4       G Rj  xL 
  i   \         d     i i ; i; i5i)z
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   debugr1   r	   read_message_asyncrv   IncompleteReadErrorrW   MSG_TYPE_STASHhandle_stash_requestMSG_TYPE_STATUShandle_status_requestMSG_TYPE_MANAGEhandle_manage_requestroute_requestrH   errorr   wait_closed)r>   readerwritermessagemsg_typerL   s   &&&   r?   r   DirtyArbiter.handle_client  s     	?@	***$1$D$DV$LLG #;;v. };;;33GDDD!>!>>44WEEE!>!>>44WEEE ,,W===' . LLN((***/ M22  E F F > 	=HHNN8!<<	=
 +  LLN((*** s#  G&E D: D8D: :E 
E/E :E;/E *E+E EE F& G&F 1F2F 6G&8D: :EE F& EE E E E F)F
F& 
FF& F F#G&"F##G&&G#8GGGG#G G#G  G##G&c           	     F  "   VP                  RR4      pVP                  R4      pV P                  V4      G Rj  xL
 pVf{   V P                  '       g   \        R4      pM1V'       d   V P                  '       d   \        V4      pM\        R4      p\        W64      p\        P                  ! W'4      G Rj  xL
  R# WPP                  9  d   V P                  V4      G Rj  xL
  V P                  V,          p\        P                  ! 4       P                  4       p	VP                  WV	34      G Rj  xL
   V	G Rj  xL
  R#  EL
 L Lg L L  \         dE   p
\        T\!        RT
 2TR7      4      p\        P                  ! Y'4      G Rj  xL 
   Rp
?
R# Rp
?
ii ; i5i)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unknownrb   NzNo dirty workers availablezRequest failed: 	worker_id)rW   _get_available_workerr*   r   r7   r   r
   r	   write_message_asyncr-   _start_worker_consumerrv   r   create_futureputrH   r   )r>   requestclient_writer
request_idrb   ra   r   responsequeuefuturerL   s   &&&        r?   r   DirtyArbiter.route_request  se     [[y1
;;z*  55h??
<<<"#?@dnnn4X>"#?@*:=H33MLLL ///--j999"":.))+99; ii8999	MLL5 @ M
 : 	:  	M* #3A3!7:NH  33MLLL	Ms   8F!EF!F!)F!;;F!6E7*F!!E	"AF!2E3F!8E =E>E F!F!	F!F!E F3FFFF!FF!c                   a aa"   \         P                  ! 4       oSS P                  S&   VV V3R lp\         P                  ! V! 4       4      pVS P                  S&   R# 5i)z3Start a consumer task for a worker's request queue.c                    <"   SP                   '       dq    SP                  4       G R j  xL
 w  rp SP                  SW4      G R j  xL
  VP                  4       '       g   VP	                  R 4       SP                  4        K  R #  L] LA  \
         d2   pTP                  4       '       g   TP                  T4        R p?LOR p?ii ; i  SP                  4        i ; i  \        P                   d     R # i ; i5ir   )
r1   rW   _execute_on_workerdone
set_resultrH   set_exception	task_donerv   r   )r   r   r   rL   r   r>   ra   s       r?   consumer5DirtyArbiter._start_worker_consumer.<locals>.consumer  s     ***;@99;5F2GF
*"55&    &{{}}"--d3
 ) 5F
 % 4%{{}}"0034 )-- s   C<C  BC  B B
	B #B 4C  C<C  
B C'C>C CC CC   C95C<8C99C<N)rv   Queuer-   r   r.   )r>   ra   r   taskr   s   ff  @r?   r   #DirtyArbiter._start_worker_consumer  sJ     ).:&	$ ""8:.,0j)s   AAc           	       "   VP                  RR4      p V P                  V4      G Rj  xL
 w  rV\        P                  ! Wb4      G Rj  xL
    \        P
                  ! \        P                  ! V4      V P                  P                  R7      G Rj  xL
 pTP                  R4      p	T	\        P                  8X  d!   \        P                  ! Y74      G Rj  xL
  K  T	\        P                  8X  d!   \        P                  ! Y74      G Rj  xL
  R# T	\        P                  \        P                  39   d!   \        P                  ! Y74      G Rj  xL
  R# T P                   P#                  RT	4       EK)   ELN EL1 L  \        P                   dN    \        T\        RT P                  P                  4      4      p\        P                  ! Y84      G Rj  xL 
   R# i ; i EL L L  \$         dr   p
T P                   P'                  RY4       T P)                  T4       \        T\+        R	T
 2TR
7      4      p\        P                  ! Y84      G Rj  xL 
   Rp
?
R# Rp
?
ii ; i5i)z
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   N)timeoutzWorker timeoutr   z$Unknown message type from worker: %sz Error executing on worker %s: %szWorker communication failed: r   )rW   _get_worker_connectionr	   r   rv   wait_forr   r   dirty_timeoutTimeoutErrorr
   r   MSG_TYPE_CHUNKMSG_TYPE_ENDMSG_TYPE_RESPONSEMSG_TYPE_ERRORr   rI   rH   r   _close_worker_connectionr   )r>   ra   r   r   r   r   r   r   r   r   rL   s   &&&&       r?   r   DirtyArbiter._execute_on_worker  s     [[y1
0	M#'#>#>z#JJNF33FDDD $+$4$4%88@ $ 6 6% G #;;v. };;;';;MSSS }999';;MSSS  ? ? - < < > >';;MSSS   !GRK KD
 ++ 2")*:DHH<R<RS H (;;MTTT T
 T T  	MHHNN=zM))*5* #@!D+57H
  33MLLL	Ms   I+G, E8G, 
E;G, AF  E>F  ?G, G%4G, G(G, I+>G, G*G, I+ G, ;G, >F   AG"GG"G, I+!G""G, (G, *G, ,I(7A I#II#I+#I((I+c                4  "   V'       dB   V P                   '       d0   WP                  9   d   \        V P                  V,          4      pM%R# \        V P                  P	                  4       4      pV'       g   R# V'       dV   V P                   '       dD   V P
                  P                  V^ 4      pV^,           \        V4      ,          V P
                  V&   M*V P                  pV^,           \        V4      ,          V n        W#\        V4      ,          ,          # 5i)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.
N)	r7   r8   r^   r*   keysr:   rW   rV   r/   )r>   rb   eligible_pidsidxs   &&  r?   r   "DirtyArbiter._get_available_workerG  s        ... $T%8%8%B C  !!2!2!45M &&**8Q7C.1Ag]9K-KD  *''C%(1WM0B$BD!3}#5566s   DAD7	DDBDc                  "   WP                   9   d   V P                   V,          # V P                  P                  V4      pV'       g   \        RV 24      h\	        ^24       FH  p\
        P                  P                  V4      '       d    M0\        P                  ! R4      G Rj  xL
  KJ  	  \        RV 24      h\        P                  ! V4      G Rj  xL
 w  rEWE3V P                   V&   WE3#  LI L5i)z%Get or create connection to a worker.zNo socket for worker 皙?NzWorker socket not ready: )r,   r+   rW   r   ranger    r'   r   rv   r   open_unix_connection)r>   ra   r)   _r   r   s   &&    r?   r   #DirtyArbiter._get_worker_connectionq  s     000**:66))--j94ZLABB rAww~~k**--$$$ 
 8FGG&;;KHH/5.>
+~ % Is+   AC3	AC3%C/&/C3C1C31C3c                    WP                   9   d0   V P                   P                  V4      w  r#VP                  4        R# R# )zClose connection to a worker.N)r,   rf   r   )r>   ra   _readerr   s   &&  r?   r   %DirtyArbiter._close_worker_connection  s4    000"5599*EOGLLN 1rB   c                  "   VP                  RR4      p\        P                  ! 4       p. pV P                  P	                  4        Fm  w  rg VP
                  P                  4       p\        WH,
          ^4      p	VP                  RVRVP                  R\        VR. 4      R\        VRR	4      R
V	/4       Ko  	  VP                  R R7       RV P                  RTR\!        V4      RV P"                  '       d$   \%        V P"                  P'                  4       4      M. /p
\)        W:4      p\*        P,                  ! W+4      G Rj  xL
  R#   \        \        \        3 d    Rp	 Li ; i L$5i)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   ageappsrY   bootedFlast_heartbeatc                     V R ,          # )r   )rk   s   &r?   r   4DirtyArbiter.handle_status_request.<locals>.<lambda>  s    %rB   keyarbiter_pidr*   rE   )rW   time	monotonicr*   rU   tmplast_updateroundOSError
ValueErrorAttributeErrorrX   r  getattrsortr   rV   r7   r^   r   r   r	   r   )r>   r   r   r   nowworkers_infor   workerr  r	  resultr   s   &&&         r?   r   "DirtyArbiter.handle_status_request  sD     [[y1
nn<<--/KC&$jj446!&s'8!!< svzzR8'&(E: .!  0 	01 488|C-4>>>D,,./r	
 !4//HHH+ Z8 &!%&* 	Is7   A	E',E8CE' E%E'E"E'!E""E'c                  a "   VP                  RR4      pVP                  R4      p\        ^\        VP                  R^4      4      4      p V\        8X  d   ^ p\	        V4       FW  pS P                  4       pVe#   S ;P                  ^,          un        V^,          p\        P                  ! R4      G Rj  xL
  KY  	  V^ 8X  d0   RRR	R
RVR^ RRR\        S P                  4      RS P                  /pEMzRRR	R
RVRVR\        S P                  4      RS P                  /pEMMV\        8X  Ed	   S P                  4       p	^ p
\	        V4       F  pS P                  V	8:  d    M\        S P                  4      ^8:  d    MS ;P                  ^,          un        \        S P                  P                  4       V 3R lR7      pS P                  V\         P"                  4       V
^,          p
\        P                  ! R4      G Rj  xL
  K  	  RRR	RRVRV
R\        S P                  4      RS P                  /pM9\%        RV 24      p\'        W<4      p\(        P*                  ! W-4      G Rj  xL
  R# S P,                  P/                  RV\        8X  d   R
MRVVP                  RVP                  R^ 4      4      4       \1        W84      p\(        P*                  ! W-4      G Rj  xL
  R#  EL/ L L L  \2         de   pS P,                  P5                  RT4       \'        T\%        \7        T4      4      4      p\(        P*                  ! Y-4      G Rj  xL 
   Rp?R# Rp?ii ; i5i)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   opcountNr   successT	operationr_   	requestedspawnedreasonz)All apps have reached their worker limitstotal_workerstarget_workersc                 >   < SP                   V ,          P                  # r   r*   r  pr>   s   &r?   r   4DirtyArbiter.handle_manage_request.<locals>.<lambda>  s    4<<?3F3FrB   r  removeremovedzUnknown manage operation: z6Worker management: %s %d workers (spawned/removed: %d)zManage operation error: %s)rW   rP   intr   r   spawn_workerr3   rv   r   rV   r*   r   rR   minr   kill_workerr   r   r   r
   r	   r   r   rm   r   rH   r   rp   )r>   r   r   r   r   r!  r%  r   r  r   r/  
oldest_pidr   r   rL   s   f&&            r?   r   "DirtyArbiter.handle_manage_request  s     [[y1
[[As7;;w234N	M]"uA!..0F)((A-(1!--,,, & a<!4#U#U!1 "M'T\\):($*:*:F "4#U#U!7'T\\):($*:*:F ''"779uA'';64<<(A-$$)$ "%T\\%6%6%8)F"HJ$$Z@qLG!--,,, &  tw#S%6$d&6&6 #%?t#DE.zA#77PPPHHMMR#%#6%H **Y

9a0HIK
 %Z8H33MLLLA -R - Q M 	MHHNN7;*:z#a&7IJH33MLLL	Ms   A	M!A*K/ 7K&8E
K/ K)A&K/ )K+*K/ .M!0A/K/ K- K/ $M!&K/ )K/ +K/ -K/ /M:AMMMM!MM!c           	     T	  "   VP                  RR4      pVP                  R4      pVP                  RR4      pVP                  R4      pVP                  R4      pVP                  R4      p R	p	V\        8X  d9   WPP                  9  d   / V P                  V&   WpP                  V,          V&   R
p	EMV\        8X  dP   WPP                  9  d   RR/p	EMW`P                  V,          9  d   RR/p	EMxV P                  V,          V,          p	EM\V\        8X  dD   WPP                  9   d0   W`P                  V,          9   d   V P                  V,          V R
p	EMRp	EMV\
        8X  d   WPP                  9  d   . p	EM\        V P                  V,          P                  4       4      p
V'       d:   V
 Uu. uF-  p\        P                  ! \        V4      V4      '       g   K+  VNK/  	  p
pT
p	EMV\        8X  d6   WPP                  9   d"   V P                  V,          P                  4        R
p	EM@V\        8X  d8   WPP                  9  d   RR/p	EMR\        V P                  V,          4      RV/p	MV\        8X  d#   WPP                  9  d   / V P                  V&   R
p	MV\        8X  d$   WPP                  9   d   V P                  V R
p	MRp	MV\         8X  d%   \        V P                  P                  4       4      p	MtV\"        8X  d1   WPP                  9  d   Rp	MVVf   R
p	MOW`P                  V,          9   p	M9\%        RV 24      p\'        W<4      p\(        P*                  ! W-4      G R	j  xL
  R	# \-        V	\.        4      '       d   RV	9   d   V	R,          pVR8X  d   \%        RV 24      pM*VR8X  d   \%        RV 24      pM\%        \        V	4      4      pRVP1                  4       P3                  RR4       R2Vn        \'        W<4      pM\7        W94      p\(        P*                  ! W-4      G R	j  xL
  R	# u upi  L L  \8         de   pT P:                  P=                  RT4       \'        T\%        \        T4      4      4      p\(        P*                  ! Y-4      G R	j  xL 
   R	p?R	# R	p?ii ; i5i)z
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_foundFtable_not_foundsizezUnknown stash operation: zTable not found: zKey not found: Stashr   ErrorzStash operation error: %s)rW   r   r<   r   r   r   r^   r   fnmatchrp   r   clearr   rV   r   r   r   r   r   r
   r	   r   
isinstancedicttitlereplace
error_typer   rH   r   r   )r>   r   r   r   r   r7  r  r9  r:  r  all_keyskr   r   rF  rL   s   &&&             r?   r   !DirtyArbiter.handle_stash_request  s     [[y1
[[GR(kk% G$++i(a	MF\! 1 11/1D%%e,05!!%(-|# 1 11%7F 1 1% 88%7F!..u5c:F&---#9J9J59Q2Q))%05!F"F}$ 1 11F#D$5$5e$<$A$A$CDH/7 $Ix!'.s1vw'G %&Ax $I%F~%---%%e,224}$ 1 11%'89F D$5$5e$< =F
 & 1 11/1D%%e,,,---))%0!F"F&d//4467& 1 11"F[!F $5$5e$<<F #%>rd#CD.zA#77PPP &$''Gv,=#G_
!22&):5''BCE?2&'>?E&s6{3E%*:+;+;+=+E+Ec2+N*Ou#U .zA(<33MLLL{$IX Q" M 	MHHNN6:*:z#a&7IJH33MLLL	Ms   A)R(,EP6 .(P-P-!E?P6  P2!P6 %R('B?P6 &P4'P6 +R(-P6 4P6 6R%AR RR R( R%%R(c                   a "   S P                   '       g   R# S P                  pS P                   '       dP   \        S P                  4      V8  d6   S P	                  4       pVf   M \
        P                  ! R4      G Rj  xL
  Ka  \        S P                  4      V8  dj   \        S P                  P                  4       V 3R lR7      pS P                  V\        P                  4       \
        P                  ! R4      G Rj  xL
  K  R#  L L
5i)z%Maintain the number of dirty workers.Nr   c                 >   < SP                   V ,          P                  # r   r*  r+  s   &r?   r   -DirtyArbiter.manage_workers.<locals>.<lambda>  s    4<<?+>+>rB   r  )r1   r3   rV   r*   r1  rv   r   r2  r   r3  r   r   )r>   r3   r  r4  s   f   r?   r   DirtyArbiter.manage_workers  s     zzz&& jjjS.<&&(F~--$$$ $,,+-T\\..0!>@JZ8--$$$ . % %s*   2DAD>D
?BDD	DDc           	        V P                   '       d   V P                   P                  ^ 4      pM<V'       d%   \        V P                  P	                  4       4      pMV P                  4       pV'       g   V P                  P                  R4       R# V ;P                  ^,          un        \        P                  P                  V P                  RV P                   R24      p\        V P                  V P                  VV P                  V P                  VR7      p\        P                   ! 4       pV^ 8w  dm   WTn        W@P"                  V&   W0P$                  V&   V P'                  WR4       V P                  P)                  W4       V P                  P+                  RWR4       V# \        P,                  ! 4       Vn         \.        P0                  ! RV P                  P2                   R24       VP5                  4        \        P6                  ! ^ 4       R#   \8         d<   p\        P6                  ! TP:                  e   TP:                  M^ 4        Rp?R# Rp?i\<         dh    T P                  P?                  R	4       TP@                  '       g!   \        P6                  ! T PB                  4       \        P6                  ! ^4        R# i ; i)
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
z)No apps need more workers, skipping spawnNzworker-z.sock)r  r"   rY   r   r   r)   z,Spawned dirty worker (pid: %s) with apps: %szdirty-worker []z!Exception in dirty worker process)"r;   rf   r^   r7   r   r[   r   r   r0   r    r'   r(   r&   r   r   r   forkr*   r+   rc   dirty_post_forkrm   r!   r   ru   	proc_nameinit_process_exit
SystemExitcoderH   	exceptionr  WORKER_BOOT_ERROR)r>   force_all_appsrY   r)   r  r   rL   s   &&     r?   r1  DirtyArbiter.spawn_worker  s     !!!..2215IT^^0023I 557IHHNNFG1ggllKK74??"359
 #
 ggi!8J &LL'2$ &&s6HH$$T2HHMMH*J YY[

	0B0B/C1EF!HHQK 	:HHqvv1QVVq99 	HHBC===//0HHQK		s+   =AH K	0IK	!-K	6K	K	c                     \         P                  ! W4       R#   \         dB   pTP                  \        P                  8X  d   T P                  T4        Rp?R#  Rp?R# Rp?ii ; i)zKill a worker by PID.N)r    killr  errnoESRCH_cleanup_worker)r>   r   r   rL   s   &&& r?   r3  DirtyArbiter.kill_worker  sI    	*GGC 	*ww%++%$$S)) &	*s    A&0A!!A&c                   V P                  V4       WP                  9   d/   V P                  V,          P                  4        V P                  V V P                  P	                  VR4       WP
                  9   d@   \        V P
                  V,          4      pV'       d   V P                  P                  V4       V P                  V4       V P                  P	                  VR4      pV'       d   V P                  P                  W4       V P                  P	                  VR4      pV'       dA   \        P                  P!                  V4      '       d    \        P"                  ! V4       R# R# R#   \$         d     R# i ; i)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   r.   r   r-   rf   r9   r^   r;   rX   rh   r*   r   dirty_worker_exitr+   r    r'   r   r   r  )r>   r   	dead_appsr  r)   s   &&   r?   r_  DirtyArbiter._cleanup_worker  s+    	%%c* '''!!#&--/%%c* 	sD) %%%T0056I&&--i8 	$!!#t,HH&&t4))--c48277>>+66		+& 7;  s   E1 1F ?F c                b  "   V P                   P                  '       g   R# \        V P                  P	                  4       4       F  w  r \
        P                  ! 4       VP                  P                  4       ,
          V P                   P                  8:  d   KU   TP                  '       gF   T P                  P                  RT4       RTn        T P                  T\        P                   4       K  T P                  T\        P"                  4       K  	  R#   \        \        3 d     K  i ; i5i)z!Kill workers that have timed out.NzDIRTY WORKER TIMEOUT (pid:%s)T)r   r   r^   r*   rU   r  r  r  r  r  r  abortedr   criticalr3  r   SIGABRTSIGKILL)r>   r   r  s   &  r?   r   DirtyArbiter.murder_workers  s     xx%%% 2 2 45KC>>#fjj&<&<&>>$((BXBXX Y
 >>>!!"A3G!%  fnn5  fnn5 6 Z( s2   AD/
ADD/,A+D/D,(D/+D,,D/c                     \         P                  ! R\         P                  4      w  rV'       g   R# Rp\         P                  ! V4      '       d   \         P                  ! V4      pMN\         P
                  ! V4      '       d3   \         P                  ! V4      pV P                  P                  RW4       W0P                  8X  d   V P                  P                  RV4       V P                  V4       V P                  P                  RV4       EK    \         d,   pTP                  \        P                  8w  d   h  Rp?R# Rp?ii ; i)zReap dead worker processes.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   rI   rX  r   r_  rm   r  r]  ECHILD)r>   wpidstatusexitcoder   rL   s   &     r?   r   DirtyArbiter.reap_workers*  s    	!zz"bjj9<<''!~~f5H^^F++++f-CHH$$%P%)0 555HHNN#I4P$$T*<dC 	ww%,,& '	s)   0D D 2D BD E	 EE	c                  "   V P                   P                  R4       \        V P                  P                  4       F1  pV P                  4        \        P                  ! R4      G Rj  xL
  K3  	  \        V P                  P                  4       4      pW P                  P                  R  F#  pV P                  V\        P                  4       K%  	  R#  Ll5i)z!Reload workers (SIGHUP handling).zReloading dirty workersr   N)r   rm   r   r   r2   r1  rv   r   r^   r*   r   r3  r   r   )r>   r   old_workersr   s   &   r?   r   DirtyArbiter.reloadC  s     /0 txx--.A--$$$ /
 4<<,,./xx5567CS&..1 8	 %s   A'C)C*A-Cc                  "   V P                   P                  4        F  pVP                  4        K  	  V'       d   \        P                  M\        P
                  p\        P                  ! 4       V P                  P                  ,           p\        V P                  P                  4       4       F  pV P                  WS4       K  	  V P                  '       dK   \        P                  ! 4       V8  d1   V P                  4        \        P                  ! R4      G Rj  xL
  K\  \        V P                  P                  4       4       F#  pV P                  V\        P                   4       K%  	  V P                  4        R#  Lb5i)zStop all workers.r   N)r.   rO   r   r   r   r   r  r   dirty_graceful_timeoutr^   r*   r   r3  r   rv   r   ri  )r>   gracefulr   r   limitr   s   &&    r?   r   DirtyArbiter.stopQ  s      ))002DKKM 3 !)fnnfnn		dhh=== ))+,CS& - llltyy{U2--$$$ ))+,CS&..1 - %s   9FBFAFE?A#Fc                *   V P                   '       dQ   \        P                  P                  V P                   4      '       d"    \        P                  ! V P                   4       \        P                  P                  V P                  4      '       d"    \        P                  ! V P                  4        \        P                  ! V P                  4       FA  p\        P                  ! \        P                  P                  V P                  V4      4       KC  	  \        P                  ! V P                  4       V P                  P                  RV P                  4       R#   \
         d     ELi ; i  \
         d     Li ; i  \
         d     LXi ; i)zSynchronous cleanup on exit.zDirty arbiter exiting (pid: %s)N)r#   r    r'   r   r   r  r)   listdirr&   r(   rmdirr   rm   r   )r>   r{   s   & r?   rz   DirtyArbiter._cleanup_synch  s    <<<BGGNN4<<88		$,,'
 77>>$**++		$**+
	ZZ,		"'',,t{{A67 -HHT[[! 	7B%      		s7    E!  E3 4BF !E0/E03F FFF)r:   r5   r6   r;   r4   r/   r1   r7   r8   r   r   r3   r   r#   r"   r)   r<   r&   r0   r9   r,   r.   r-   r+   r*   )NNr   )F)T),__name__
__module____qualname____firstlineno____doc__splitr  r   r~   rX  r@   r=   rR   r[   rc   rh   rw   rt   r   r   rx   r   r   r   r   r   r   r   r   r   r   r   r   r   r1  r3  r_  r   r   r   r   rz   __static_attributes____classdictcell__)x__classdict__s   0@r?   r   r   1   s     <AACEC 12wvw{+CEG 5 n 5D"6:$B"!@<8<t!
&P((&P2Mh14:Mx(7T*'IR\M|sMj%.FP*"H6&22.C CY!Es    B1r   )%r  rv   r]  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  rB   r?   <module>r     s]   
    	     @     "  OC OCrB   