
    ng\jVB                     j    S SK r S SKrS SKrS SKJrJrJr   " S S5      rS\ R                  S\4S jr	g)    N)AnyCallable	Coroutinec                      \ rS rSrSrS rS rS rS\S\	4S jr
S	\S\	4S
 jrS	\S\	S\\\\4   4   4S jrSS.S\	S\\\\4   4   S\S-  S\4S jjrS\	S\\\\4   4   SS4S jrSS\4S jjrS rS\R(                  S	\S\	S\\\\4   4   4S jrS\R(                  S	\S\	S\\\\4   4   4S jrS	\S\	S\\\\4   4   4S jrS\R(                  S\S\	4S jrS\R(                  S	\S\	4S jrS\R(                  S	\S\	4S jrSrg) BackgroundScheduler   z^
Schedules background tasks execution either in separate thread or in the running event loop.
c                     S U l         / U l        [        R                  " 5       U l        SU l        S U l        S U l        [        R                  " 5       U l	        g )NF)
_next_timer_event_loops	threadingLock_lock_stopped_health_check_loop_health_check_threadEvent_health_check_loop_readyselfs    K/home/edenadmin/noVNC/venv/lib/python3.13/site-packages/redis/background.py__init__BackgroundScheduler.__init__   sF    ^^%
DH=A!(1(9%    c                 $    U R                  5         g N)stopr   s    r   __del__BackgroundScheduler.__del__   s    		r   c                    U R                      U R                  (       a
   SSS5        gSU l        U R                  (       a!  U R                  R                  5         SU l        U R                   H5  nUR                  5       (       d  M  UR                  UR                  5        M7     U R                  R                  5         SSS5        g! , (       d  f       g= f)z2
Stop all scheduled tasks and clean up resources.
NT)	r   r   r
   cancelr   
is_runningcall_soon_threadsafer   clear)r   loops     r   r   BackgroundScheduler.stop   s     ZZ}} Z !DM  '')#'  ))??$$--dii8 * ##% ZZs   C
AC
9C


Cdelaycallbackc                    U R                      U R                  (       a
   SSS5        g SSS5        [        R                  " 5       nU R                      U R                  R                  U5        SSS5        [        R                  " [        X@R                  X/UQ7SS9nUR                  5         g! , (       d  f       N= f! , (       d  f       NY= f)z9
Runs callable task once after certain delay in seconds.
NTtargetargsdaemon)r   r   asyncionew_event_loopr   appendr   Thread_start_event_loop_in_thread_call_laterstart)r   r&   r'   r+   r$   threads         r   run_onceBackgroundScheduler.run_once.   s     ZZ}} Z 
 %%'ZZ$$T*  !!.((%ADA

 	 Z Z   B1C1
B?
Cintervalc                    U R                      U R                  (       a
   SSS5        g SSS5        [        R                  " 5       nU R                      U R                  R                  U5        SSS5        [        R                  " [        X@R                  X/UQ7SS9nUR                  5         g! , (       d  f       N= f! , (       d  f       NY= f)z>
Runs recurring callable task with given interval in seconds.
NTr)   )r   r   r-   r.   r   r/   r   r0   r1   _call_later_recurringr3   )r   r8   r'   r+   r$   r4   s         r   run_recurring!BackgroundScheduler.run_recurringC   s     ZZ}} Z 
 %%'ZZ$$T*  !!.22HNN

 	 Z Zr7   coro.c                 J   U R                      U R                  (       a
   SSS5        g SSS5        U R                  5         U R                      U R                  nSSS5        WR                  " U R
                  XAU/UQ76   g! , (       d  f       N_= f! , (       d  f       N?= f)z
Runs recurring coroutine with given interval in seconds in a background thread.
Uses a shared event loop to ensure connection pools remain valid across calls.

This is useful for sync code that needs to run async health checks.
N)r   r   _ensure_health_check_loopr   r"   _call_later_recurring_coro)r   r8   r=   r+   r$   s        r   run_recurring_coro&BackgroundScheduler.run_recurring_coroX   s~     ZZ}} Z 
 	&&(ZZ**D  	!!++TT	
DH	
 Z Zs   BB
B
B"g      $@timeoutrD   Nreturnc                   U R                      U R                  (       a  [        S5      e SSS5        U R                  5         U R                      U R                  nSSS5        [
        R                  " U" U6 W5      n UR                  US9$ ! , (       d  f       Ni= f! , (       d  f       NI= f! [         a    UR                  5         e f = f)a  
Runs a coroutine synchronously and returns its result.
Uses the shared health check event loop to ensure connection pools
created here remain valid for subsequent recurring health checks.

This is useful for running the initial health check before starting
recurring checks.

Args:
    coro: Coroutine function to execute
    *args: Arguments to pass to the coroutine
    timeout: Maximum seconds to wait for the result. None means wait
        forever. Default is 10 seconds to avoid blocking indefinitely
        if the event loop is busy with long-running health checks.

Returns:
    The result of the coroutine

Raises:
    TimeoutError: If the coroutine doesn't complete within timeout
    Any exception raised by the coroutine
zScheduler is stoppedNrC   )
r   r   RuntimeErrorr?   r   r-   run_coroutine_threadsaferesultTimeoutErrorr    )r   r=   rD   r+   r$   futures         r   run_coro_sync!BackgroundScheduler.run_coro_syncp   s    : ZZ}}"#9::  
 	&&(ZZ**D  11$+tD	===11 Z Z  	MMO	s#   BB?B0 
B
B-0Cc                    U R                      U R                  (       a
   SSS5        g SSS5        U R                  5         U R                      U R                  nSSS5        S[        R
                  4S jn[        R                  " U" U6 W5      nUR                  U5        g! , (       d  f       N= f! , (       d  f       N`= f)ai  
Schedule a coroutine for execution on the shared health check loop
without waiting for the result. Exceptions are logged but not raised.

This is useful for HALF_OPEN recovery health checks that need to run
on the same event loop where connection pools were created.

Args:
    coro: Coroutine function to execute
    *args: Arguments to pass to the coroutine
NrK   c                    U R                  5       (       a*  [        R                  " [        5      R	                  S5        gU R                  5       b7  [        R                  " [        5      R	                  SU R                  5       S9  gg)z&Log any exceptions from the coroutine.z#Fire-and-forget coroutine cancelledNz*Fire-and-forget coroutine raised exceptionexc_info)	cancelledlogging	getLogger__name__debug	exception)rK   s    r   on_completeABackgroundScheduler.run_coro_fire_and_forget.<locals>.on_complete   sl    !!!!(+112WX!!#/!!(+11@#--/ 2  0r   )r   r   r?   r   r-   FuturerH   add_done_callback)r   r=   r+   r$   rX   rK   s         r   run_coro_fire_and_forget,BackgroundScheduler.run_coro_fire_and_forget   s     ZZ}} Z 
 	&&(ZZ**D 	 	 11$+tD  -- Z Zs   B$B5$
B25
Cc                    U R                   R                  5       (       aK  U R                     U R                  b)  U R                  R	                  5       (       a
   SSS5        gSSS5        U R                     U R                  b)  U R                  R	                  5       (       a
   SSS5        gU R                   R                  5         [        R                  " 5       U l        U R                  R                  U R                  5        [        R                  " U R                  SS9U l        U R                  R                  5         U R                   R                  US9(       d]  U R                  nSU l        X R                  ;   a  U R                  R!                  U5         UR#                  5         ['        SU S35      e SSS5        g! , (       d  f       GNn= f! [$         a     N7f = f! , (       d  f       g= f)z
Ensure the shared health check loop and thread are running.

Args:
    timeout: Maximum seconds to wait for the loop to start.

Raises:
    RuntimeError: If the loop fails to start within the timeout.
NT)r*   r,   rC   z/Health check event loop failed to start within z seconds)r   is_setr   r   r!   r#   r-   r.   r   r/   r   r0   _run_health_check_loopr   r3   waitremoveclose	ExceptionrG   )r   rD   failed_loops      r   r?   -BackgroundScheduler._ensure_health_check_loop   s    ((//11++7//::<<  ZZ ''3++6688 Z ))//1 '.&<&<&>D#$$T%<%<= )2(8(822)D% %%++- 0055g5F #55*.'"3"33%%,,[9%%' #EgYhW  G5 Z T ! G ZsB   .G
7.G,.C2G,!G1G,

G
G)&G,(G))G,,
G:c           	         [         R                  " U R                  5        U R                  R                  U R                  R
                  5         U R                  R                  5          [         R                  " U R                  5      nU H  nUR                  5         M     U R                  R                  [         R                  " USS065        U R                  R                  5         g! [         a     N'f = f! U R                  R                  5         f = f!  [         R                  " U R                  5      nU H  nUR                  5         M     U R                  R                  [         R                  " USS065        O! [         a     Of = fU R                  R                  5         f ! U R                  R                  5         f = f= f)z'Run the shared health check event loop.return_exceptionsTN)r-   set_event_loopr   	call_soonr   setrun_forever	all_tasksr    run_until_completegatherrd   rc   )r   pendingtasks      r   r`   *BackgroundScheduler._run_health_check_loop  sm   t667 	))$*G*G*K*KL	0##//1
0!++D,C,CD#DKKM $''::NNGDtD ''--/   ''--/
0!++D,C,CD#DKKM $''::NNGDtD   ''--/''--/sh   D ,A(C/ /
C<9C? ;C<<C? ?DG A(F	F4	
FF4FF4G4GGr$   c                     U R                      U R                  (       a
   SSS5        g SSS5        U R                  " XU R                  XU/UQ76   g! , (       d  f       N/= f)z0Schedule first execution of recurring coroutine.N)r   r   r2   _execute_recurring_coro)r   r$   r8   r=   r+   s        r   r@   .BackgroundScheduler._call_later_recurring_coro  sS     ZZ}} Z  	D88$$	
QU	
 Z   A
A!c           	        ^ ^^^^ T R                      T R                  (       a
   SSS5        g SSS5        S[        R                  4UUUUU 4S jjn [        R                  " T" T6 5      nUR                  U5        g! , (       d  f       NV= f! [         ai    T R                      T R                  (       a   SSS5         g SSS5        O! , (       d  f       O= fT R                  " TTT R                  TTT/TQ76    gf = f)z
Executes recurring coroutine with given interval in seconds.
Schedules next execution only after current one completes to prevent overlap.
Nrq   c                   > U R                  5       (       a  OGU R                  5       b6  [        R                  " [        5      R                  SU R                  5       S9  TR                     TR                  (       a
   SSS5        g SSS5        TR                  " TTTR                  TTT/TQ76   g! , (       d  f       N1= f)<Callback when coroutine completes - schedule next execution.Nz%Background coroutine raised exceptionrP   )
rR   rW   rS   rT   rU   rV   r   r   r2   rt   )rq   r+   r=   r8   r$   r   s    r   rX   @BackgroundScheduler._execute_recurring_coro.<locals>.on_complete7  s     ~~!-!!(+11;!^^- 2  ==    ,, 	 s   +B33
C)	r   r   r-   Taskensure_futurer[   rd   r2   rt   )r   r$   r8   r=   r+   rX   rq   s   `````  r   rt   +BackgroundScheduler._execute_recurring_coro(  s     ZZ}} Z 	gll 	 	6	((t5D"";/E ZF  	==    ,, 	s;   A?*B ?
BD&C9D	D
C	)DDc                   ^ ^^^^^^#    T R                      T R                  (       a
   SSS5        g SSS5        [        R                  " 5       mUUUU 4S jmUUUU 4S jmTR	                  TT5      T l        g! , (       d  f       NM= f7f)aV  
Runs recurring coroutine with given interval in seconds in the current event loop.
To be used only from an async context. No additional threads are created.

Prevents overlapping executions by scheduling the next run only after
the current one completes.

Raises:
    RuntimeError: If called without a running event loop (programming error)
Nc                     > TR                      TR                  (       a
   SSS5        g SSS5        TR                  TT 5      Tl        g! , (       d  f       N&= f)z<Schedule the next execution after the current one completes.Nr   r   
call_laterr
   )execute_and_rescheduler8   r$   r   s   r   schedule_next>BackgroundScheduler.run_recurring_async.<locals>.schedule_next{  sA    ==     $x9OPD s   A
Ac                    > TR                      TR                  (       a
   SSS5        g SSS5        S[        R                  4U4S jjn  [        R                  " T" T6 5      nUR                  U 5        g! , (       d  f       NR= f! [         a2    [        R                  " [        5      R                  SSS9  T" 5          gf = f)z=Execute the coroutine and schedule next run after completion.Nrq   c                    > U R                  5       (       a  OGU R                  5       b6  [        R                  " [        5      R                  SU R                  5       S9  T" 5         g)ry   Nz*Recurring async coroutine raised exceptionrP   )rR   rW   rS   rT   rU   rV   )rq   r   s    r   rX   \BackgroundScheduler.run_recurring_async.<locals>.execute_and_reschedule.<locals>.on_complete  sT     >>##^^%1%%h/55D!%!1 6 
 r   z,Failed to schedule recurring async coroutineTrP   )r   r   r-   r{   r|   r[   rd   rS   rT   rU   rV   )rX   rq   r+   r=   r   r   s     r   r   GBackgroundScheduler.run_recurring_async.<locals>.execute_and_reschedule  s    ==    ',,   ,,T4[9&&{3' (   !!(+11BT 2   s   A7*B 7
B9CC)r   r   r-   get_running_loopr   r
   )r   r8   r=   r+   r   r$   r   s   ````@@@r   run_recurring_async'BackgroundScheduler.run_recurring_asynce  sl      ZZ}} Z  '')	Q 	Q	  	 <  ??85KL] Zs!   BA:	BAB:
BBc                     U R                      U R                  (       a
   S S S 5        g  S S S 5        UR                  " X#/UQ76 U l        g ! , (       d  f       N'= fr   r   )r   r$   r&   r'   r+   s        r   r2   BackgroundScheduler._call_later  sD     ZZ}} Z   ??5BTB Zs   A
Ac                     U R                      U R                  (       a
   S S S 5        g  S S S 5        U R                  " XU R                  XU/UQ76   g ! , (       d  f       N/= fr   )r   r   r2   _execute_recurringr   r$   r8   r'   r+   s        r   r:   )BackgroundScheduler._call_later_recurring  sS     ZZ}} Z  	D33TX	
PT	
 Zrv   c                 x   U R                      U R                  (       a
   SSS5        g SSS5         U" U6   U R                      U R                  (       a
   SSS5        g SSS5        U R                  " XU R                  XU/UQ76   g! , (       d  f       Nf= f! [         a     Nof = f! , (       d  f       NP= f)zB
Executes recurring callable task with given interval in seconds.
N)r   r   rd   r2   r   r   s        r   r   &BackgroundScheduler._execute_recurring  s     ZZ}} Z 	dO
 ZZ}} Z  	D33TX	
PT	
 Z  		 Zs(   B
B B+

B
B('B(+
B9)r   r   r   r   r   r
   r   )g      @)rU   
__module____qualname____firstlineno____doc__r   r   r   floatr   r5   r;   r   r   rA   rL   r\   r?   r`   r-   AbstractEventLoopr@   rt   r   r2   r:   r   __static_attributes__ r   r   r   r      s   	:&(e x *e x *

%-c9S#s]3K.K%L
8 !%	.sIc3m445. 	.
 
.`$.S)CcM"::;$.	$.L: :x0.
''
 
 sIc3m445	
;''; ; sIc3m445	;z;M;M%-c9S#s]3K.K%L;MzC--C6;CGOC
''
 
 	

''
 
 	
r   r   
event_loopcall_soon_cbc           	         [         R                  " U 5        U R                  " X/UQ76    U R                  5          [         R                  " U 5      nU H  nUR                  5         M     U R                  [         R                  " USS065        U R                  5         g! [         a     Nf = f! U R                  5         f = f!  [         R                  " U 5      nU H  nUR                  5         M     U R                  [         R                  " USS065        O! [         a     Of = fU R                  5         f ! U R                  5         f = f= f)z
Starts event loop in a thread and schedule callback as soon as event loop is ready.
Used to be able to schedule tasks using loop.call_later.

:param event_loop:
:return:
rh   TN)
r-   ri   rj   rl   rm   r    rn   ro   rd   rc   )r   r   r+   rp   rq   s        r   r1   r1     s(    :&9D9 	''
3G   ))@4@   		 	''
3G   ))@4@  		 Jsf   C AB! !
B.+B1 -B..B1 1CEADD>
D*'D>)D**D>-E>EE)
r-   rS   r   typingr   r   r   r   r   r1   r   r   r   <module>r      s<       + +K
 K
\))9Ar   