o
    ix!                     @  s   U d Z ddlmZ ddlZddlZddlZddlmZmZ ddlm	Z	m
Z
mZ eeZdZdadd Zd7ddZ											d8d9d*d+ZG d,d- d-Zdad.ed/< d:d0d1Zd;d2d3Zd<d5d6ZdS )=a  
Sentence Store Service - Supabase storage for TTS requests.

Stores all request text + metadata in Supabase for analytics and auditing.
Non-blocking writes (fire-and-forget) to avoid impacting TTFB.

Graceful degradation: if env vars missing, storage is skipped silently.
    )annotationsN)datetimetimezone)AnyDictOptionaltts_requestsc                  C  sB   t du rzddlm}  | a W t S  ty   td Y dS w t S )zLazy import supabase client.Nr   create_clientz9supabase package not installed, sentence storage disabled)_supabase_client_classsupabaser
   ImportErrorloggerwarningr	    r   >/home/ubuntu/veenaModal/veena3modal/services/sentence_store.py_get_supabase_client   s   
r   urlstrkeyc                 C  s   t  }|du r	dS || |S )z1Create Supabase client (wrapper for lazy import).N)r   )r   r   client_funcr   r   r   r
   (   s   
r
   Fwav皙?2         ?   ?
request_idtextspeakerstreamboolformattemperaturefloattop_kinttop_p
max_tokensrepetition_penaltyseedOptional[int]text_chunkedttfb_msaudio_duration_secondsOptional[float]returnDict[str, Any]c                 C  st   i d| d|dt |d|d|d|d|d|d	|d
|d|	d|
d|d|d|dttj S )a3  
    Create a sentence record dictionary for storage.
    
    Args:
        request_id: Unique request identifier (X-Request-ID)
        text: Input text for TTS
        speaker: Speaker name (resolved internal name)
        stream: Whether streaming was enabled
        format: Audio format (wav, opus, mp3, etc.)
        temperature: Sampling temperature
        top_k: Top-k sampling parameter
        top_p: Nucleus sampling parameter
        max_tokens: Maximum tokens to generate
        repetition_penalty: Repetition penalty
        seed: Random seed (if specified)
        text_chunked: Whether text was chunked for generation
        ttfb_ms: Time to first byte in milliseconds
        audio_duration_seconds: Duration of generated audio
    
    Returns:
        Dictionary ready for Supabase insertion
    r   r   text_lengthr   r    r"   r#   r%   r'   r(   r)   r*   r,   r-   r.   
created_at)lenr   nowr   utc	isoformatr   r   r   r    r"   r#   r%   r'   r(   r)   r*   r,   r-   r.   r   r   r   create_sentence_record0   sB   &	
r9   c                   @  sN   e Zd ZdZdd Zd(ddZ				
								d)d*d#d$Zd+d&d'ZdS ),SentenceStorez
    Service for storing TTS request text and metadata in Supabase.
    
    Graceful degradation: if env vars missing, all operations are no-ops.
    Non-blocking: use store_fire_and_forget() for async background writes.
    c              
   C  s   t jdd}t jdpt jdpd}d| _|r|s#td dS zt||| _| jdur?td|dd  d	 W dS W dS  ty_ } zt	d
|  d| _W Y d}~dS d}~ww )z6Initialize Supabase client from environment variables.SUPABASE_URL SUPABASE_SERVICE_KEYSUPABASE_KEYNz>Supabase credentials not configured, sentence storage disabledzSentenceStore initialized:    z...z&Failed to initialize Supabase client: )
osenvirongetclientr   debugr
   info	Exceptionr   )selfsupabase_urlsupabase_keyer   r   r   __init__r   s(   


 zSentenceStore.__init__r0   r!   c                 C  s
   | j duS )z/Check if Supabase is configured and accessible.N)rC   )rG   r   r   r   is_configured   s   
zSentenceStore.is_configuredFr   r   r   r   r   r   Nr   r   r   r   r    r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   c                   s     std|  dS z/t|||||||||	|
||||d t }|d fddI dH  td|  W dS  ty\ } ztd	| d
|  W Y d}~dS d}~ww )z
        Store a TTS request record in Supabase.
        
        Args:
            ... (see create_sentence_record for details)
        
        Returns:
            True if stored successfully, False otherwise
        z,Supabase not configured, skipping store for Fr8   Nc                     s   j t  S )N)rC   table
TABLE_NAMEinsertexecuter   recordrG   r   r   <lambda>   s    z%SentenceStore.store.<locals>.<lambda>zStored sentence for request TzFailed to store sentence for : )	rL   r   rD   r9   asyncioget_event_looprun_in_executorrF   r   )rG   r   r   r   r    r"   r#   r%   r'   r(   r)   r*   r,   r-   r.   looprJ   r   rQ   r   store   sB   
zSentenceStore.storeOptional[asyncio.Task]c                   sZ     sdS  fdd}zt }|| }|W S  ty,   td Y dS w )aZ  
        Store a TTS request record without blocking.
        
        Creates a background task that completes independently.
        Does not block the calling coroutine.
        
        Args:
            ... (see store() for details)
        
        Returns:
            asyncio.Task if storage was initiated, None if not configured
        Nc               
     sd   zj dd I d H  W d S  ty1 }  ztd d|   W Y d } ~ d S d } ~ ww )N)r   r   r   zBackground store failed for rT   r   )rY   rF   r   r   )rJ   kwargsr   rG   r   r   r   r   _background_store   s   $z>SentenceStore.store_fire_and_forget.<locals>._background_storez'No event loop for fire-and-forget store)rL   rU   rV   create_taskRuntimeErrorr   rD   )rG   r   r   r   r\   r]   rX   taskr   r[   r   store_fire_and_forget   s   
z#SentenceStore.store_fire_and_forgetr0   r!   Fr   r   r   r   r   r   NFNN)r   r   r   r   r   r   r    r!   r"   r   r#   r$   r%   r&   r'   r$   r(   r&   r)   r$   r*   r+   r,   r!   r-   r+   r.   r/   r0   r!   )r   r   r   r   r   r   r0   rZ   )__name__
__module____qualname____doc__rK   rL   rY   ra   r   r   r   r   r:   j   s"    
	?r:   zOptional[SentenceStore]_sentence_storec                   C  s   t du rt a t S )z)Get the singleton SentenceStore instance.N)rh   r:   r   r   r   r   get_sentence_store   s   ri   c                   C  s   t du rdS t  S )z3Check if the singleton SentenceStore is configured.NF)rh   rL   r   r   r   r   is_sentence_store_configured  s   rj   Nonec                   C  s   da dS )z6Reset singleton for testing. Do not use in production.N)rh   r   r   r   r   _reset_singleton  s   rl   )r   r   r   r   rc   )r   r   r   r   r   r   r    r!   r"   r   r#   r$   r%   r&   r'   r$   r(   r&   r)   r$   r*   r+   r,   r!   r-   r+   r.   r/   r0   r1   )r0   r:   rb   )r0   rk   )rg   
__future__r   r@   loggingrU   r   r   typingr   r   r   	getLoggerrd   r   rN   r   r   r
   r9   r:   rh   __annotations__ri   rj   rl   r   r   r   r   <module>   s<    	

: 

