o
    iH                     @   s  U d Z ddlZddlmZ ddlmZmZmZ ddlm	Z	 e	e
ZG dd deeZi ejdejdejd	ejd
ejdejdejdejdejdejdejdejdejdejdejdejdejdZeee f e!d< 	d/dedededeeeef  deeef f
ddZ"dede fddZ#da$de%de&fddZ'de%deddfddZ(de&fd d!Z)d0d"d#Z*		$d1d%ed&ed'edefd(d)Z+d%ed*edee fd+d,Z,G d-d. d.Z-dS )2aD  
Error handling and GPU fault recovery for Veena3 TTS.

Features:
- Standardized error responses
- GPU fault detection and container draining
- Graceful degradation for missing configs

Usage:
    from veena3modal.api.error_handlers import (
        handle_gpu_fault,
        create_error_response,
        ErrorCode,
    )
    N)Enum)DictAnyOptional)
get_loggerc                   @   sT   e 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ZdZdZdS )	ErrorCodez!Standard error codes for TTS API.INVALID_API_KEYEXPIRED_API_KEYINSUFFICIENT_CREDITSRATE_LIMIT_EXCEEDEDVALIDATION_ERRORTEXT_TOO_LONGINVALID_SPEAKERINVALID_FORMATMODEL_NOT_LOADED	GPU_FAULTGPU_OOMGENERATION_FAILEDGENERATION_TIMEOUTSTREAMING_ERRORSERVICE_UNAVAILABLEINTERNAL_ERRORFORMAT_NOT_IMPLEMENTEDN)__name__
__module____qualname____doc__r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r   r   9/home/ubuntu/veenaModal/veena3modal/api/error_handlers.pyr      s&    r   i  i  i  i  i    i  i  ERROR_STATUS_CODEScodemessage
request_iddetailsreturnc                 C   s&   d| j ||di}|r||d d< |S )a$  
    Create a standardized error response body.
    
    Args:
        code: Error code enum
        message: Human-readable error message
        request_id: Request identifier for tracking
        details: Optional additional details
    
    Returns:
        Error response dictionary
    error)r!   r"   r#   r$   )value)r!   r"   r#   r$   responser   r   r   create_error_responseO   s   r)   c                 C   s   t | dS )z'Get HTTP status code for an error code.r   )r    get)r!   r   r   r   get_error_statuso   s   r+   F	exceptionc                    s*   t |   g d}t fdd|D S )z
    Check if an exception indicates a GPU fault.
    
    Args:
        exception: The caught exception
    
    Returns:
        True if this is a GPU-related fault
    )z
cuda errorzcudnn errorzout of memoryoomzillegal memory accesszdevice-side assertz
nccl errorgpuc                 3   s    | ]}| v V  qd S Nr   ).0	indicator	error_msgr   r   	<genexpr>   s    zis_gpu_fault.<locals>.<genexpr>)strlowerany)r,   gpu_fault_indicatorsr   r2   r   is_gpu_faultx   s   
r9   c              
   C   s   t jd|t| t| jdd daz&ddl}t|dr3t|jdr6|j	  t j
d	d
|id W dS W dS W dS  tyB   Y dS  ty` } zt jd|t|dd W Y d}~dS d}~ww )aF  
    Handle a GPU fault by logging and signaling container drain.
    
    In Modal, this should call `modal.experimental.stop_fetching_inputs()`
    to prevent the container from accepting more requests while it drains.
    
    Args:
        exception: The GPU fault exception
        request_id: Request ID for logging
    gpu_fault_detected)r#   r,   exception_typeextraTr   Nexperimentalstop_fetching_inputscontainer_drain_initiatedr#   container_drain_failed)r#   r&   )loggerr&   r5   typer   _gpu_fault_detectedmodalhasattrr>   r?   infoImportError	Exceptionwarning)r,   r#   rE   er   r   r   handle_gpu_fault   s8   	
rL   c                   C   s   t S )z9Check if a GPU fault has been detected in this container.rD   r   r   r   r   has_gpu_fault   s   rN   c                   C   s   da dS )z#Reset GPU fault flag (for testing).FNrM   r   r   r   r   reset_gpu_fault_flag   s   rO    env_vardefaultrequired_forc                 C   sB   t j| }|du r|rtjd| |t|dd |dur|S |S )a[  
    Get an optional configuration value with graceful degradation.
    
    Logs a warning if the config is missing but doesn't crash.
    
    Args:
        env_var: Environment variable name
        default: Default value if not set
        required_for: Feature name (for warning message)
    
    Returns:
        Config value or default
    Noptional_config_missing)rQ   featureusing_defaultr<   )osenvironr*   rB   rJ   r5   )rQ   rR   rS   r'   r   r   r   get_optional_config   s   	rY   feature_namec                 C   s,   t j| }|du rtjd| |dd |S )a_  
    Check if a required config is available.
    
    Unlike get_optional_config, this doesn't provide a default.
    Returns None if missing, allowing the caller to handle gracefully.
    
    Args:
        env_var: Environment variable name
        feature_name: Feature that requires this config
    
    Returns:
        Config value or None
    Nrequired_config_missing)rQ   rU   r<   )rW   rX   r*   rB   rJ   )rQ   rZ   r'   r   r   r   check_required_config   s   r\   c                   @   sj   e Zd ZdZedefddZedefddZedefddZedefd	d
Z	edefddZ
dS )FeatureFlagszx
    Feature flags for graceful degradation.
    
    Checks environment to determine which features are available.
    r%   c                  C   s0   t jd} t jdpt jd}t| o|S )z Check if Supabase is configured.SUPABASE_URLSUPABASE_SERVICE_KEYSUPABASE_KEY)rW   rX   r*   bool)urlkeyr   r   r   is_supabase_enabled  s   z FeatureFlags.is_supabase_enabledc                   C   s   t tjdS )zCheck if Redis is configured.	REDIS_URL)ra   rW   rX   r*   r   r   r   r   is_redis_enabled  s   zFeatureFlags.is_redis_enabledc                  C   s   t jdd } | dkS )z#Check if authentication is enabled.AUTH_BYPASS_MODEfalsetruerW   rX   r*   r6   )bypassr   r   r   is_auth_enabled      zFeatureFlags.is_auth_enabledc                  C   s   t jdd } | dkS )z"Check if rate limiting is enabled.RATE_LIMIT_ENABLEDri   rj   )enabledr   r   r   is_rate_limiting_enabled&  rm   z%FeatureFlags.is_rate_limiting_enabledc                   C   s   t jdd dkS )z(Check if Prometheus metrics are enabled.PROMETHEUS_ENABLEDri   rj   r   r   r   r   is_metrics_enabled,  s   zFeatureFlags.is_metrics_enabledN)r   r   r   r   staticmethodra   rd   rf   rl   rp   rr   r   r   r   r   r]     s    r]   r/   )r%   N)NrP   ).r   rW   enumr   typingr   r   r   veena3modal.shared.loggingr   r   rB   r5   r   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    int__annotations__r)   r+   rD   rI   ra   r9   rL   rN   rO   rY   r\   r]   r   r   r   r   <module>   s     	


 .


!
