
    BCh4%                         d Z ddlZddlZddlZddlmZmZmZ ddlmZm	Z	 ddl
mZ ddlmZ ddlZ ej                  e      Z G d d      Zdd	Zdd
Zy)z
Redis-based cache utilities for SQLGenAI application.
This module provides Redis-based caching mechanisms to reduce API calls to AI models.
    N)DictAnyOptional)datetime	timedeltawraps)current_appc                       e Zd ZdZdZdZed        Zedede	ee
f   dee	ee
f      fd       Ze	 ddede	ee
f   d	e	ee
f   d
eddf
d       Zedede	ee
f   defd       Zedefd       Zede	ee
f   fd       Zy)
RedisCachez@Redis-based cache for AI-generated SQL queries and explain plansNFc                 N   | j                   ry	 t        j                  j                  dd      }t	        j
                  |      | _        d| _         t        j                  d|        y# t        $ r2}t        j                  dt        |              d| _         Y d}~yd}~ww xY w)zInitialize the Redis connectionN	REDIS_URLzredis://localhost:6379/0Tz/Redis cache initialized successfully with URL: z Error initializing Redis cache: F)_initializedr
   configgetredisfrom_url_redis_clientloggerinfo	Exceptionerrorstr)cls	redis_urles      &/var/www/html/app/utils/redis_cache.py
initializezRedisCache.initialize   s     	%#**..{<VWI %y 9C#CKKI)UV 	%LL;CF8DE$C	%s   AA) )	B$2(BB$
key_prefixkey_datareturnc                    | j                   s| j                          | j                   r| j                  st        j	                  d       y| j                  ||      }	 | j                  j                  |      }|r3t        j                  |      }t        j                  d|dd  d       |S 	 t        j                  d|dd  d       y# t        $ r+}t        j                  dt        |              Y d}~Ld}~ww xY w)zGet cached result if availablez5Redis cache not initialized, cannot get cached resultNzCache hit for key:    ...z(Error retrieving data from Redis cache: zCache miss for key: )r   r   r   r   warning_generate_cache_keyr   jsonloadsr   r   r   r   )r   r   r    	cache_keycached_dataresultr   s          r   get_cached_resultzRedisCache.get_cached_result%   s     NNs'8'8NNRS ++JA		N++//	:KK01)BQ-DE  	*9Ra=/=>	  	NLLCCF8LMM	Ns   AC 	D !C;;D r+   ttl_secondsc                    | j                   s| j                          | j                   r| j                  st        j	                  d       y| j                  ||      }	 | j                  j                  ||t        j                  |             t        j                  d|dd  d       y# t        $ r+}t        j                  dt        |              Y d}~yd}~ww xY w)z+Cache the result with TTL (default 30 days)z0Redis cache not initialized, cannot cache resultNzCached result for key: r#   r$   z#Error storing data in Redis cache: )r   r   r   r   r%   r&   setexr'   dumpsr   r   r   r   )r   r   r    r+   r-   r)   r   s          r   cache_resultzRedisCache.cache_result?   s     NNs'8'8NNMN ++JA			I##

6"
 KK1)BQ-DE 	ILL>s1vhGHH	Is   AB+ +	C4!CCc                     t        j                  |d      }t        j                  |j	                               j                         }|  d| S )z5Generate a unique cache key based on input parametersT	sort_keys:)r'   r0   hashlibsha256encode	hexdigest)r   r    data_strhash_keys       r   r&   zRedisCache._generate_cache_keyX   sC     ::h$7>>(//"34>>@Qxj))    c                 f   | j                   s| j                          | j                   r| j                  st        j	                  d       y	 | j                  j                          t        j                  d       y# t        $ r+}t        j                  dt        |              Y d}~yd}~ww xY w)zFlush the entire cachez/Redis cache not initialized, cannot flush cacheFz Redis cache flushed successfullyTzError flushing Redis cache: N)
r   r   r   r   r%   flushdbr   r   r   r   )r   r   s     r   flush_cachezRedisCache.flush_cache`   s     NNs'8'8NNLM	%%'KK:; 	LL7Ax@A	s   /A< <	B0!B++B0c           	      b   | j                   s| j                          | j                   r| j                  st        j	                  d       ddiS 	 | j                  j                         }t        | j                  j                  d            }t        | j                  j                  d            }||z   |||j                  dd      |j                  dd	      |j                  d
d	      dS # t        $ r8}t        j                  dt        |              dt        |      icY d}~S d}~ww xY w)zGet cache statisticsz-Redis cache not initialized, cannot get statsr   zRedis cache not initializedzsql_query:*zexplain_plan:*used_memory_humanzN/Auptime_in_secondsr   connected_clients)
total_keyssql_query_keysexplain_plan_keysmemory_useduptimerC   z!Error getting Redis cache stats: N)r   r   r   r   r%   r   lenkeysr   r   r   r   )r   r   rE   rF   r   s        r   	get_statszRedisCache.get_statsr   s    NNs'8'8NNJK:;;	%$$))+D !!2!2!7!7!FGN #C$5$5$:$:;K$L M -/@@"0%6#xx(;UC((#6:%)XX.A1%E   	%LL<SVHEFSV$$	%s   BC- -	D.6-D)#D.)D.)i ' )__name__
__module____qualname____doc__r   r   classmethodr   r   r   r   r   r,   intr1   staticmethodr&   boolr?   rK    r<   r   r   r      s'   JML% % 3 $sCx. XVZ[^`c[cVdMe  2 >EIc IT#s(^ IS>I8;IJNI I0 * *tCH~ *# * * D  " %$sCx. % %r<   r   c                       fd}|S )z:Decorator for caching AI query generation results in Redisc                 4     t               d fd	       }|S )Nc           
         t         j                  j                  dd      s 	| ||||      S t        | d| j                  j
                        }||t        j                  t        j                  |d      j                               j                         |t        j                  t        j                  |xs i d      j                               j                         d}t        j                  d|      }|rt        d|        d|d<   |S t        d	|         	| ||||      }|j                  d
d      r*t        j                  d||
dz         t        d|        |S )NENABLE_AI_CACHET
model_typer3   )rY   promptschema_hashdb_typedb_config_hash	sql_queryz0[REDIS CACHE HIT] SQL generation for model_type=
from_cachez1[REDIS CACHE MISS] SQL generation for model_type=successFQ r-   z9[REDIS CACHE STORE] SQL generation result for model_type=)r
   r   r   getattr	__class__rL   r6   r7   r'   r0   r8   r9   r   r,   printr1   )selfrZ   schema_datar\   	db_configrY   r    cached_resultr+   functtl_dayss            r   wrapperz:with_redis_query_cache.<locals>.decorator.<locals>.wrapper   s[    %%))*;TBD&+w	JJ !|T^^5L5LMJ ) &~~djjPT.U.\.\.^_iik"")..IOW[1\1c1c1e"f"p"p"rH '88hOMHUV.2l+$$Ej\RS $WiHF zz)U+'' (5 0	 (  QR\Q]^_Mr<   )Nr   rj   rl   rk   s   ` r   	decoratorz)with_redis_query_cache.<locals>.decorator   s!    	t)	 
)	T r<   rT   rk   rn   s   ` r   with_redis_query_cacherp      s    ,Z r<   c                       fd}|S )z?Decorator for caching AI explain plan analysis results in Redisc                 2     t                fd       }|S )Nc                 X   t         j                  j                  dd      s | |||      S t        | d| j                  j
                        }|t        j                  t        j                  |d      j                               j                         ||d}t        j                  d|      }|rt        d|        d|d<   |S t        d	|         | |||      }t        |t               r;|j                  d
      s*t        j#                  d||	dz         t        d|        |S )NrX   TrY   r3   )rY   explain_hashr\   r^   explain_planz7[REDIS CACHE HIT] Explain plan analysis for model_type=r_   z8[REDIS CACHE MISS] Explain plan analysis for model_type=r   ra   rb   z@[REDIS CACHE STORE] Explain plan analysis result for model_type=)r
   r   r   rc   rd   rL   r6   r7   r'   r0   r8   r9   r   r,   re   
isinstancedictr1   )
rf   explain_datar\   r^   rY   r    ri   r+   rj   rk   s
           r   rl   z<with_redis_explain_cache.<locals>.decorator.<locals>.wrapper   s1    %%))*;TBD,CC !|T^^5L5LMJ ) 'tzz,RV/W/^/^/` a k k m"&	H '88RMOPZ|\].2l+$$LZLYZ $gyAF &$'

70C''" (5 0	 (  XYcXdefMr<   r   rm   s   ` r   rn   z+with_redis_explain_cache.<locals>.decorator   s!    	t(	 
(	R r<   rT   ro   s   ` r   with_redis_explain_cachery      s    +X r<   )   )rO   r'   r6   loggingtypingr   r   r   r   r   	functoolsr	   flaskr
   r   	getLoggerrL   r   r   rp   ry   rT   r<   r   <module>r      sQ       & & (   			8	$~% ~%B/d.r<   