o
    iX8                     @   sh   d Z ddlZddlmZmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ G dd	 d	Zed
dZdS )z~
FIXED Call Manager for Handling Multiple Concurrent Calls
Manages call sessions with proper concurrency limits and isolation
    N)DictOptional)	WebSocket)Log)CallSession)Configc                   @   s   e Zd ZdZddefddZdededee	 fd	d
Z
deddfddZdedee	 fddZdefddZdefddZdeeef fddZdddZdeddfddZdS )CallManagerz
    Manages multiple concurrent call sessions with proper isolation.
    Each call gets its own completely isolated session.
    2   max_concurrent_callsc                 C   s6   || _ i | _t|| _t | _td|  d S )Nz1Call Manager initialized - Max concurrent calls: )	r
   active_sessionsasyncio	Semaphorecall_semaphoreLocksession_lockr   info)selfr
    r   :/var/www/html/live_calls/homebook/services/call_manager.py__init__   s
   
zCallManager.__init__
session_id	websocketreturnc              
      s  zpt | j| jkr#td| j d|  |jdddI dH  W dS t||}| I dH s:td|  W dS | j	4 I dH  || j|< W d  I dH  n1 I dH sWw   Y  t
d| d	t | j d
| j d |W S  ty } z.t|}d|v sd|v rtd| d W Y d}~dS td| d|  W Y d}~dS d}~w ty } ztd| d|  W Y d}~dS d}~ww )z
        Create a new isolated call session with proper error handling.
        Returns None if max concurrent calls reached or if creation fails.
        u"   ❌ Max concurrent calls reached (z). Rejecting session i  z.Service overloaded - too many concurrent calls)codereasonNu!   ❌ Failed to initialize session u   ✅ Created call session 
 (Active: /)different loopattached to a different loopu7   ⚠️ Event loop mismatch during session creation for z - retrying...u(   ❌ Runtime error creating call session : u    ❌ Error creating call session )lenr   r
   r   warningcloser   
initializeerrorr   r   RuntimeErrorstr	Exception)r   r   r   sessione	error_msgr   r   r   create_call_session   s8   
(&zCallManager.create_call_sessionNc              
      s(  d}zt d|  | j4 I dH 5 || jv r(| j|}t d|  nt d| d 	 W d  I dH  W dS W d  I dH  n1 I dH sNw   Y  |rz| I dH  t d|  W nP ty } z(t|}d|v szd|v rt 	d	| d
 nt 
d| d|   W Y d}~n!d}~w ty } zt 
d| d|  W Y d}~nd}~ww t d| dt| j d| j d W dS W dS  ty } z7t|}d|v sd|v rt 	d| d nt 
d| d|  ddl}|  W Y d}~dS W Y d}~dS d}~ww )zBRemove and cleanup a call session with proper event loop handling.Nu'   🔄 Attempting to remove call session u!   🧹 Calling cleanup for session zSession z( already removed (likely race condition)u#   ✅ Cleanup successful for session r   r   .   ⚠️ Event loop mismatch during cleanup for z& - resources will be garbage collectedu-   ❌ Runtime error during cleanup for session r    u%   ❌ Error during cleanup for session u   🗑️ Removed call session r   r   r   u1   ⚠️ Event loop mismatch when removing session z  - session removed from trackingu    ❌ Error removing call session r   )r   r   r   r   popdebugcleanupr&   r'   r"   r%   r(   r!   r
   	traceback	print_exc)r   r   r)   cleanup_errorr+   r*   r1   r   r   r   remove_call_session   sR   
(
",zCallManager.remove_call_sessionc                 C   s   | j |S )zGet an active call session.)r   get)r   r   r   r   r   get_session   s   zCallManager.get_sessionc                 C   s
   t | jS )zGet number of active sessions.)r!   r   r   r   r   r   get_active_sessions_count   s   
z%CallManager.get_active_sessions_countc                 C   s>   t | j| jt | j| j d | jt | j t| j dS )z&Get system-wide status for monitoring.d   )r   r
   utilization_percentavailable_slotssession_ids)r!   r   r
   listkeysr7   r   r   r   get_system_status   s   zCallManager.get_system_statusc                 C   s   dd | j  D S )z"Get status of all active sessions.c                 S   s   i | ]	\}}||  qS r   )
get_status).0r   r)   r   r   r   
<dictcomp>  s    z4CallManager.get_session_statuses.<locals>.<dictcomp>)r   itemsr7   r   r   r   get_session_statuses  s   z CallManager.get_session_statusesc           	   
      s  zat | j}td| d g }| j D ]\}}|| || q|r[tj|ddiI dH }dd |D }t |t | }|rRt	d| d	t | d
 n	td| d | j
  W dS  ty } ztd|  | j
  W Y d}~dS d}~ww )zFCleanup all active sessions (for shutdown) with proper error handling.u   🧹 Cleaning up z active sessionsreturn_exceptionsTNc                 S   s   g | ]	}t |tr|qS r   )
isinstancer(   )rA   rr   r   r   
<listcomp>  s    z4CallManager.cleanup_all_sessions.<locals>.<listcomp>u   ⚠️ Cleanup completed: z succeeded, z failedu   ✅ All z! sessions cleaned up successfullyu    ❌ Error cleaning up sessions: )r!   r   r   r   rC   append_safe_cleanup_sessionr   gatherr"   clearr(   r%   )	r   session_countcleanup_tasksr   r)   resultserrors	successesr*   r   r   r   cleanup_all_sessions  s(   
z CallManager.cleanup_all_sessionsc              
      s   z
|  I dH  W dS  ty5 } zt|}d|v sd|v r)td| d n W Y d}~dS d}~w tyL } ztd| d|   d}~ww )z8Safely cleanup a session with event loop error handling.Nr   r   r-   z - allowing garbage collectionu   ❌ Error cleaning up session r    )r0   r&   r'   r   r"   r(   r%   )r   r)   r   r*   r+   r   r   r   rJ   +  s   z!CallManager._safe_cleanup_session)r	   )r   N)__name__
__module____qualname____doc__intr   r'   r   r   r   r,   r4   r6   r8   r   r?   rD   rR   rJ   r   r   r   r   r      s    ),

r   r	   )r
   )rV   r   typingr   r   fastapir   services.log_utilsr   services.call_sessionr   configr   r   call_managerr   r   r   r   <module>   s     -