
    $i                         S r SSKrSSKJr  SSKJr  SSKJrJrJ	r	  SSK
JrJr  SSKJr  SSKJr  \" \5      rSqSqS	rS
rS rS rS rSS\4S jjrS rS r\S\\SS4   4S j5       rS rg)z+Database connection and session management.    N)	Generator)contextmanager)create_engineeventtext)Sessionsessionmaker)
get_logger)get_settings   g      ?c            	      >   [         b  g[        5       n U R                  n[        R	                  S[
        5        Sn[        S[
        S-   5       Hh  n [        UR                  UR                  UR                  SSS9q [         R                  5        nUR                  [        S5      5        SSS5        Sn  O   Ub  [)        S[
         SU 35      e[+        [         5        [-        SS[         S9q[        R	                  S5        g! , (       d  f       N`= f! [         a{  nUnU[
        :  aI  [        SUS-
  -  -  n[        R!                  S	U[
        UU5        ["        R$                  " U5         SnAGM(  [        R'                  S
[
        5         SnAGMI  SnAff = f)z@Initialize database engine and session factory with retry logic.Nz1Initializing database connection (max_retries=%d)   TF)	pool_sizemax_overflowpool_pre_pingechozSELECT 1   zBDatabase connection attempt %d/%d failed: %s. Retrying in %.1fs...z+All %d database connection attempts failed.z$Failed to connect to database after z attempts. Last error: )
autocommit	autoflushbindzDatabase connection initialized)_enginer   databaseloggerinfo_MAX_DB_RETRIESranger   urlr   r   connectexecuter   	Exception_INITIAL_RETRY_DELAYwarningtimesleeperrorRuntimeError_setup_slow_query_detectionr	   _SessionLocal)settings	db_configlast_exceptionattemptconnedelays          C/root/tipsharks/tipsharks-elo-api/packages/core/storage/database.pyinit_dbr1      sy    ~H!!I
KKC_U NOa/0	##--&33"G "dT*-. #!N 1B !2?2C D)*,
 	
  ( EUQM
KK12E #"  	N(,gk0BC+# 

5!!A# 	s7   ?DD,
D
D	D
F!AF6FFc                    ^ [        5       R                  R                  m[        R                  " U S5      S 5       n[        R                  " U S5      U4S j5       ng)a  Register SQLAlchemy event listeners for detecting slow queries.

Logs queries that exceed the configured threshold (default: 100ms)
at WARNING level with query text, duration, and sanitized parameters.

Args:
    engine: SQLAlchemy engine to attach listeners to.
before_cursor_executec                 H    [         R                   " 5       U R                  S'   g )Nquery_start_time)r#   r   )r-   cursor	statement
parameterscontextexecutemanys         r0   _before_cursor_execute;_setup_slow_query_detection.<locals>._before_cursor_execute_   s     )-				$%    after_cursor_executec                    > [         R                   " 5       U R                  R                  S[         R                   " 5       5      -
  nUS-  nUT	:  a$  [        U5      n[        R                  SUUU5        g g )Nr5   i  z$Slow query (%.1f ms): %s | params=%s)r#   r   pop_sanitize_paramsr   r"   )
r-   r6   r7   r8   r9   r:   totalduration_ms	sanitizedthreshold_mss
            r0   _after_cursor_execute:_setup_slow_query_detection.<locals>._after_cursor_executee   sc     		diimm,>		LLdl%(4INN6	 &r=   N)r   r   slow_query_threshold_msr   listens_for)enginer;   rF   rE   s      @r0   r'   r'   T   sZ      >**BBL
v674 84
 v56 7r=   c                    U c  g[        U [        5      (       a/  U R                  5        VVs0 s H  u  pU[        U5      _M     snn$ [        U [        [
        45      (       at  U (       a[  [        U S   [        5      (       aC  U  VVVs/ s H1  o3R                  5        VVs0 s H  u  pU[        U5      _M     snnPM3     snnn$ [        S U  5       5      $ [        U 5      $ s  snnf s  snnf s  snnnf )a  Sanitize query parameters for safe logging.

Truncates long string values to prevent log flooding.
Handles dict, list, tuple, and None parameter formats.

Args:
    parameters: Raw SQLAlchemy query parameters.

Returns:
    Sanitized parameters safe for logging.
Nr   c              3   8   #    U  H  n[        U5      v   M     g 7f)N)_trunc).0vs     r0   	<genexpr>#_sanitize_params.<locals>.<genexpr>   s     3
1VAYY
s   )
isinstancedictitemsrM   listtuple)r8   krO   ps       r0   rA   rA   v   s     *d##)3)9)9);<);6!9);<<*tUm,,*Z]D99BLM*Qggi8idaQq	\i8*MM3
333* = 9Ms   C#	C/!C)9C/)C/max_lenc                 J    [        U 5      n[        U5      U:  a  USU S-   $ U$ )z:Truncate a value's string representation for safe logging.Nz...)strlen)valuerY   ss      r0   rM   rM      s,    E
A"%a&7"21Xg;99r=   c                  0    [         c
  [        5         [         $ )zOGet SQLAlchemy engine, initializing if needed.

Returns:
    SQLAlchemy engine
)r   r1    r=   r0   
get_enginera      s     	Nr=   c                  0    [         c
  [        5         [         $ )zKGet session factory, initializing if needed.

Returns:
    Session factory
)r(   r1   r`   r=   r0   get_session_factoryrc      s     	r=   returnc               #      #    [        5       n U " 5       n Uv   UR                  5          UR	                  5         g! [         a    UR                  5         e f = f! UR	                  5         f = f7f)zGet database session context manager.

Yields:
    Database session

Example:
    >>> with get_session() as session:
    >>>     horses = session.query(Horse).all()
N)rc   commitr    rollbackclose)SessionLocalsessions     r0   get_sessionrk      s`      '(LnG
 		   	s%   A/; A/AA A,,A/c                  l    [         b  [         R                  5         Sq Sq[        R	                  S5        g)zLDispose database engine and reset globals.

Useful for testing and cleanup.
NzDatabase connection disposed)r   disposer(   r   r   r`   r=   r0   
dispose_dbrn      s+     
KK./r=   )d   ) __doc__r#   collections.abcr   
contextlibr   
sqlalchemyr   r   r   sqlalchemy.ormr   r	   packages.core.common.loggingr
   packages.core.common.settingsr   __name__r   r   r(   r   r!   r1   r'   rA   intrM   ra   rc   rk   rn   r`   r=   r0   <module>ry      s    1  % % 1 1 0 3 6	H	  :3zD.:3 : Ywd23  ,0r=   