ó
    Ú°›jß)  ã                  óæ   • % S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	J
r
  SSKJr  \" 5       rSSS jjr/ rS\S	'   SS
 jrSS jrSSS.rS\S'   SS jrSrSS jrSS jrSS jrSS jrg)am  
Fitness check system for worker startup validation.

Fitness checks run before handler initialization on the actual RunPod serverless
platform to validate the worker environment. Any check failure force-kills the
worker via os._exit(1), signaling unhealthy state to the container orchestrator.

Fitness checks do NOT run in local development mode or testing mode.
é    )ÚannotationsN)ÚCallableé   )ÚRunPodLoggerc                ó  • [         R                  [         R                  4 H6  n[        R                  " [
        5         UR                  5         SSS5        M8     [        R                  " U 5        g! , (       d  f       M`  = f)a¨  
Force-kill the worker after a fitness check failure.

Uses os._exit rather than sys.exit because a fitness failure means the
environment is broken and the worker must die immediately so the
orchestrator can restart it. sys.exit only raises SystemExit, which
triggers cooperative interpreter shutdown and blocks joining non-daemon
threads. Workers routinely have such threads alive by the time checks run
(e.g. vLLM's AsyncLLMEngine, constructed at import before the checks), so
sys.exit can hang forever and the worker keeps serving jobs. os._exit
bypasses thread joins, atexit handlers, and asyncgen cleanup.

Args:
    code: Process exit code (default 1, signaling unhealthy).
N)	ÚsysÚstdoutÚstderrÚ
contextlibÚsuppressÚ	ExceptionÚflushÚosÚ_exit)ÚcodeÚstreams     Úa/home/mande/repo/quber/.venv/lib/python3.13/site-packages/runpod/serverless/modules/rp_fitness.pyÚ_terminate_unhealthyr      sP   € ô& —:‘:œsŸz™zÓ*ˆÜ× Ò ¤Õ+Ø�L‰LŒN÷ ,Ñ+ñ +ô ‡H‚HˆT…N÷ ,Ö+ús   ¾A2Á2
B	zlist[Callable]Ú_fitness_checksc                ót   • [         R                  U 5        [        R                  SU R                   35        U $ )ab  
Decorator to register a fitness check function.

Fitness checks validate worker health at startup before handler initialization.
If any check fails, the worker is force-killed with os._exit(1).

Supports both sync and async functions (auto-detected via inspect.iscoroutinefunction()).

Example:
    @runpod.serverless.register_fitness_check
    def check_gpu():
        import torch
        if not torch.cuda.is_available():
            raise RuntimeError("GPU not available")

    @runpod.serverless.register_fitness_check
    async def check_model_files():
        import aiofiles.os
        if not await aiofiles.os.path.exists("/models/model.safetensors"):
            raise RuntimeError("Model file not found")

Args:
    func: Function to register as fitness check. Can be sync or async.

Returns:
    Original function unchanged (allows decorator stacking).
zRegistered fitness check: )r   ÚappendÚlogÚdebugÚ__name__)Úfuncs    r   Úregister_fitness_checkr   6   s/   € ô8 ×Ñ˜4Ô Ü‡I�IÐ*¨4¯=©=¨/Ð:Ô;Ø€Kó    c                 ó,   • [         R                  5         g)z�
Clear all registered fitness checks.

Used primarily for testing to reset global state between test cases.
Not intended for production use.
N)r   Úclear© r   r   Úclear_fitness_checksr!   W   s   € ô ×ÑÕr   F)Ú	gpu_checkÚsystem_checkszdict[str, bool]Ú_registration_statec                 ó(   • S[         S'   S[         S'   g)zY
Reset global registration state.

Used for testing to ensure clean state between tests.
Fr"   r#   N)r$   r    r   r   Ú_reset_registration_stater&   g   s   € ð (-Ô˜Ñ$Ø+0Ô˜Ò(r   é   c                óä  • [         R                  R                  S5      n[         R                  R                  S5      nU(       a  US:X  d  U(       d  g SSKJn  SSKJn  SSKJn  UR                  S	U5      nS
U USS US.nU" 5       n UR                  R                  SU05        UR                  X'[        S9  UR                  5         g! UR                  5         f = f! [         a     gf = f)u<  
Best-effort report of a fitness-check failure to the host before exit.

Sends a single GET to the ping URL (same URL/credentials the heartbeat
uses) with status=unhealthy plus the failing check name and reason, so the
host can emit a queryable worker.fitness_failed event. Any failure â€” no
ping URL, no API key, HTTP error, timeout â€” is swallowed, so this can never
prevent the os._exit that follows. It is synchronous, so it may delay that
exit by up to _REPORT_TIMEOUT_SECONDS (network phases only; it adds no
delay when there is no ping URL/API key to report to).
ÚRUNPOD_WEBHOOK_PINGÚRUNPOD_AI_API_KEYÚPING_NOT_SETNr   )ÚSyncClientSession)Ú	WORKER_ID)Ú__version__z$RUNPOD_POD_IDÚ	unhealthyé   )ÚstatusÚcheckÚreasonÚrunpod_versionÚAuthorization)ÚparamsÚtimeout)r   ÚenvironÚgetÚrunpod.http_clientr,   Ú&runpod.serverless.modules.worker_stater-   Úrunpod.versionr.   ÚreplaceÚheadersÚupdateÚ_REPORT_TIMEOUT_SECONDSÚcloser   )	r2   r3   Úping_urlÚapi_keyr,   r-   r4   r6   Úsessions	            r   Ú_report_unhealthyrE   u   sÎ   € ô �z‰z�~‰~Ð3Ó4€HÜ�j‰j�n‰nÐ0Ó1€GÞ�x >Ó1¾Øðå8ÝDÝ@à×#Ñ#Ð$4°iÓ@ˆà!ØØ˜T˜c�lØ,ñ	
ˆñ $Ó%ˆð	Ø�O‰O×"Ñ" O°WÐ#=Ô>Ø�K‰K˜Ô9PˆKÑQà�M‰M�OøˆG�M‰M�OûÜó áðús*   Á5C" Â1C Â<C" ÃCÃC" Ã"
C/Ã.C/c                 óš   • [         S   (       a  gS[         S'    SSKJn   U " 5         g! [         a    [        R                  S5         gf = f)z·
Ensure GPU fitness check is registered.

Deferred until first run to avoid circular import issues during module
initialization. Called from run_fitness_checks() on first invocation.
r"   NTr   ©Úauto_register_gpu_checkz>GPU fitness check module not found, skipping auto-registration)r$   Úrp_gpu_fitnessrH   ÚImportErrorr   r   rG   s    r   Ú_ensure_gpu_check_registeredrK   ž   sG   € ô ˜;×'Øà'+Ô˜Ñ$ðTÝ;áÕ!øÜó TÜ�	‰	ÐRÖSðTús   š( ¨A
Á	A
c                 ó<  • SSK n [        S   (       a  gU R                  R                  SS5      R	                  5       S:X  a  [
        R                  S5        S[        S'   gS[        S'    S	S
KJn  U" 5         g! [         a    [
        R                  S5         gf = f)zÅ
Ensure system resource fitness checks are registered.

Deferred until first run to avoid circular import issues during module
initialization. Called from run_fitness_checks() on first invocation.
r   Nr#   ÚRUNPOD_SKIP_AUTO_SYSTEM_CHECKSÚ ÚtruezOSystem fitness checks disabled via environment (RUNPOD_SKIP_AUTO_SYSTEM_CHECKS)Tr   )Úauto_register_system_checkszASystem fitness check module not found, skipping auto-registration)
r   r$   r8   r9   Úlowerr   r   Úrp_system_fitnessrP   rJ   )r   rP   s     r   Ú _ensure_system_checks_registeredrS   ²   sŒ   € ó ä˜?×+Øð 
‡z�z‡~�~Ð6¸Ó;×AÑAÓCÀvÓMÜ�	‰	Ø]ô	
ð 04Ô˜OÑ,Øà+/Ô˜Ñ(ðWÝBá#Õ%øÜó WÜ�	‰	ÐUÖVðWús   Á+A9 Á9BÂBc            
   ƒ  óH  #   • [        5         [        5         [        (       d  [        R	                  S5        g[        R                  S[        [        5       S35        [        R                  " 5       n [         H§  nUR                  n [        R	                  SU 35        [        R                  " 5       n[        R                  " U5      (       a  U" 5       I Sh  v•N   OU" 5         [        R                  " 5       U-
  S-  n[        R	                  SU SUS	 S
35        M©     [        R                  " 5       U -
  S-  n	[        R                  SU	S	 S
35        g N~! [         a¹  n[        U5      R                  n[        U5      n[        R                   " 5       n[        R#                  SU SU SU 35        [        R	                  SU 35         [%        X& SU 35        O! [         a     Of = f[        R#                  S5        ['        S5         SnAGM¡  SnAff = f7f)ai  
Execute all registered fitness checks sequentially at startup.

Execution flow:
1. Auto-register GPU check on first run (deferred to avoid circular imports)
2. Check if registry is empty (early return if no checks)
3. Log start of fitness check phase
4. For each registered check:
   - Auto-detect sync vs async using inspect.iscoroutinefunction()
   - Execute check with timing instrumentation (await if async, call if sync)
   - Log success or failure with check name and execution time
5. On any exception:
   - Log detailed error with check name, exception type, and message
   - Log traceback at DEBUG level
   - Force-kill the worker via os._exit(1) immediately (fail-fast). This is
     a hard exit, not a cooperative sys.exit/SystemExit: it does not unwind
     the stack or run cleanup, so callers cannot catch it and it cannot be
     blocked by live non-daemon threads.
6. On successful completion of all checks:
   - Log completion message with total execution time

Note:
    Checks run in registration order (list preserves order).
    Sequential execution (not parallel) ensures clear error reporting
    and handles checks with dependencies correctly.
    Timing uses high-precision perf_counter for accurate measurements.

Note:
    A failing check terminates the process via os._exit(1); this function
    does not return in that case and does not raise SystemExit.
z'No fitness checks registered, skipping.NzRunning z fitness check(s)...zExecuting fitness check: iè  zFitness check passed: z (z.2fzms)zFitness check failed: z | z: zTraceback:
zWorker is unhealthy, exiting.r   zAll fitness checks passed. ()rK   rS   r   r   r   ÚinfoÚlenÚtimeÚperf_counterr   ÚinspectÚiscoroutinefunctionr   ÚtypeÚstrÚ	tracebackÚ
format_excÚerrorrE   r   )
Útotal_start_timeÚ
check_funcÚ
check_nameÚcheck_start_timeÚcheck_elapsed_msÚexcÚ
error_typeÚerror_messageÚfull_tracebackÚtotal_elapsed_mss
             r   Úrun_fitness_checksrj   Ð   sá  é € ôD !Ô"ô %Ô&çŠ?Ü�	‰	Ð;Ô<Øä‡H�HˆxœœOÓ,Ð-Ð-AÐBÔCä×(Ò(Ó*Ðç%ˆ
Ø×(Ñ(ˆ
ð#	$Ü�I‰IÐ1°*°Ð>Ô?Ü#×0Ò0Ó2Ðô ×*Ò*¨:×6Ñ6Ù “l×"Ñ"á”ä $× 1Ò 1Ó 3Ð6FÑ FÈ$ÑNÐÜ�I‰IÐ.¨z¨l¸"Ð=MÈcÐ<RÐRUÐVÖWñ &ôP ×)Ò)Ó+Ð.>Ñ>À$ÑFÐÜ‡H�HÐ+Ð,<¸SÐ+AÀÐEÕFñA #øô ó 	$ä˜c›×+Ñ+ˆJÜ ›HˆMÜ&×1Ò1Ó3ˆNä�I‰IØ(¨¨°C¸
°|À2ÀmÀ_ÐUôô �I‰I˜ ^Ð$4Ð5Ô6ð
Ü! *°¸B¸}¸oÐ.NÕOøÜó Ùðúô
 �I‰IÐ5Ô6Ü  ×#Ó#ûð-	$üsi   ‚BH"Â	AEÃEÃAEÄ :H"ÅEÅ
HÅ&A+HÇG#Ç"HÇ#
G0Ç-HÇ/G0Ç0#HÈH"ÈHÈH")r   )r   ÚintÚreturnÚNone)r   r   rl   r   )rl   rm   )r2   r\   r3   r\   rl   rm   )Ú__doc__Ú
__future__r   r   rY   r   r   rW   r]   Úcollections.abcr   Ú	rp_loggerr   r   r   r   Ú__annotations__r   r!   r$   r&   r@   rE   rK   rS   rj   r    r   r   Ú<module>rs      s‡   ðòõ #ã Û Û 	Û 
Û Û Ý $å #áƒn€öð2 #%€�Ó $ôôBð Øñ(Ð �_ó ô1ð Ð ô&ôRTô(Wõ<XGr   