
    %hu                     h    S SK r S SKrS SKrS SKrSSKJr  \R                  " \5      r " S S5      r	g)    N   )guarantee_single_callablec                   V    \ rS rSrSrSrSS jrS rS rS r	S r
S	 rS
 rS rS rSrg)StatelessServer   a  
Base server class that handles basic concepts like application instance
creation/pooling, exception handling, and similar, for stateless protocols
(i.e. ones without actual incoming connections to the process)

Your code should override the handle() method, doing whatever it needs to,
and calling get_or_create_application_instance with a unique `scope_id`
and `scope` for the scope it wants to get.

If an application instance is found with the same `scope_id`, you are
given its input queue, otherwise one is made for you with the scope provided
and you are given that fresh new input queue. Either way, you should do
something like:

input_queue = self.get_or_create_application_instance(
    "user-123456",
    {"type": "testprotocol", "user_id": "123456", "username": "andrew"},
)
input_queue.put_nowait(message)

If you try and create an application instance and there are already
`max_application` instances, the oldest/least recently used one will be
reclaimed and shut down to make space.

Application coroutines that error will be found periodically (every 100ms
by default) and have their exceptions printed to the console. Override
application_exception() if you want to do more when this happens.

If you override run(), make sure you handle things like launching the
application checker.
g?c                 *    Xl         X l        0 U l        g N)applicationmax_applicationsapplication_instances)selfr
   r   s      @/var/www/html/env/lib/python3.13/site-packages/asgiref/server.py__init__StatelessServer.__init__.   s    & 0%'"    c                     [         R                  " 5       n[         R                  " U R                  5       5         UR	                  U R                  5       5        g! [         a    [        R                  S5         gf = f)z4
Runs the asyncio event loop with our handler loop.
zExiting due to Ctrl-C/interruptN)	asyncioget_event_loopensure_futureapplication_checkerrun_until_completehandleKeyboardInterruptloggerinfo)r   
event_loops     r   runStatelessServer.run7   s^     ++-
d6689	;))$++-8  	;KK9:	;s   A A=<A=c                     #    [        S5      e7f)NzYou must implement handle()NotImplementedError)r   s    r   r   StatelessServer.handleB   s     !"?@@   c                     #    [        S5      e7f)z=
Receives outbound sends from applications and handles them.
z%You must implement application_send()r    )r   scopemessages      r   application_send StatelessServer.application_sendE   s      ""IJJr#   c                 @  ^ ^ UT R                   ;   a7  [        R                  " 5       T R                   U   S'   T R                   U   S   $ [        T R                   5      T R                  :  a5  T R	                  5         [        T R                   5      T R                  :  a  M5  [
        R                  " 5       n[        T R                  5      n[
        R                  " U" TUR                  UU 4S jS95      nUUT[        R                  " 5       S.T R                   U'   U$ )z8
Creates an application instance and returns its queue.
	last_usedinput_queuec                 (   > TR                  TU 5      $ r	   )r'   )r&   r%   r   s    r   <lambda>DStatelessServer.get_or_create_application_instance.<locals>.<lambda>_   s    T%:%:5'%Jr   )r%   receivesend)r+   futurer%   r*   )r   timelenr   "delete_oldest_application_instancer   Queuer   r
   r   get)r   scope_idr%   r+   application_instancer1   s   ` `   r   "get_or_create_application_instance2StatelessServer.get_or_create_application_instanceM   s     t111@D		D&&x0=--h7FF$,,-0E0EE335 $,,-0E0EE mmo89I9IJ&& #J
 '	0
""8, r   c                     [        S U R                  R                  5        5       5      nU R                  R                  5        H!  u  p#US   U:X  d  M  U R	                  U5          g   g)z3
Finds and deletes the oldest application instance
c              3   *   #    U  H	  oS    v   M     g7f)r*   N ).0detailss     r   	<genexpr>EStatelessServer.delete_oldest_application_instance.<locals>.<genexpr>n   s      
0SWK 0Ss   r*   N)minr   valuesitemsdelete_application_instance)r   oldest_timer7   r?   s       r   r4   2StatelessServer.delete_oldest_application_instancej   si      
040J0J0Q0Q0S
 
 "&!;!;!A!A!CH{#{200:  "Dr   c                     U R                   U   nU R                   U	 US   R                  5       (       d  US   R                  5         gg)zh
Removes an application instance (makes sure its task is stopped,
then removes it from the current set)
r1   N)r   donecancel)r   r7   r?   s      r   rE   +StatelessServer.delete_application_instancex   sL    
 ,,X6&&x0x %%''H$$& (r   c                   #     [         R                  " U R                  5      I Sh  vN   [        U R                  R                  5       5       H`  u  pUS   R                  5       (       d  M  US   R                  5       nU(       a  U R                  X25      I Sh  vN    U R                  U	 Mb     M   N N! [         a     Mw  f = f7f)z
Goes through the set of current application instance Futures and cleans up
any that are done/prints exceptions for any that errored.
Nr1   )
r   sleepapplication_checker_intervallistr   rD   rI   	exceptionapplication_exceptionKeyError)r   r7   r?   rP   s       r   r   #StatelessServer.application_checker   s     
 -- A ABBB%)$*D*D*J*J*L%M!8$))++ ' 1 ; ; =I "88LLL 66x@ &N B
 M $ sL   %C
B5AC
..C
B7C
"B9/C
7C
9
CC
CC
c           	         #    [         R                  " SUSR                  [        R                  " UR
                  5      5      SU 35        g7f)z<
Called whenever an application coroutine has an exception.
z%Exception inside application: %s
%s%s z  N)loggingerrorjoin	traceback	format_tb__traceback__)r   rP   application_detailss      r   rQ   %StatelessServer.application_exception   s@      	4GGI''	(?(?@A		
s   AA)r
   r   r   N)i  )__name__
__module____qualname____firstlineno____doc__rN   r   r   r   r'   r9   r4   rE   r   rQ   __static_attributes__r=   r   r   r   r      s?    @ $' (	;AK:'$	
r   r   )
r   rV   r2   rY   compatibilityr   	getLoggerr^   r   r   r=   r   r   <module>rf      s0        4			8	$R
 R
r   