
    AHj ;                        d dl 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
mZmZ d dlmZmZmZmZ d dlmZ  G d d	e      Z G d
 de      Z G d de
      Z G d dee      Z G d d      Z G d de      Z G d de      Zy)    N)OptionalUnion)Redis)SentinelCommands)
ConnectionConnectionPoolSSLConnection)ConnectionErrorReadOnlyErrorResponseErrorTimeoutError)SENTINELc                       e Zd Zy)MasterNotFoundErrorN__name__
__module____qualname__     F/root/tools/cai/cai_env/lib/python3.12/site-packages/redis/sentinel.pyr   r          r   r   c                       e Zd Zy)SlaveNotFoundErrorNr   r   r   r   r   r      r   r   r   c            	       r     e Zd Z fdZd Zd Zd Zd Z	 dedddde	e
ef   d	ee   d
ee   f fdZ xZS )SentinelManagedConnectionc                 P    |j                  d      | _        t        |   di | y )Nconnection_poolr   )popr   super__init__)selfkwargs	__class__s     r   r!   z"SentinelManagedConnection.__init__   s%    %zz*;<"6"r   c                     | j                   }dt        |       j                   dt        |       j                   d|j                   d}| j
                  r!d| j
                   d| j                   }||z  }|S )N<.	(service=z%s)>z,host=z,port=)r   typer   r   service_namehostport)r"   pools	host_infos       r   __repr__z"SentinelManagedConnection.__repr__   s{    ##T
%%&aT
(;(;'<))*$0 	
 99 6$))=IIAr   c                 p    |\  | _         | _        | j                  | j                  j                  d       y )NF)check_healthretry_socket_connect)r+   r,   connect_check_healthr   check_connection)r"   addresss     r   
connect_toz$SentinelManagedConnection.connect_to)   s5    &	49!!-->>!& 	" 	
r   c                 *   | j                   ry | j                  j                  r*| j                  | j                  j	                                y | j                  j                         D ]  }	 | j                  |      c S  t        # t        $ r Y )w xY wN)_sockr   	is_masterr7   get_master_addressrotate_slavesr
   r   )r"   slaves     r   _connect_retryz(SentinelManagedConnection._connect_retry1   s    ::))OOD00CCEF--;;= ??511
 %$ ' s   ,B	BBc                 P    | j                   j                  | j                  d       S )Nc                      y r9   r   )errors    r   <lambda>z3SentinelManagedConnection.connect.<locals>.<lambda>?   s    r   )retrycall_with_retryr?   r"   s    r   connectz!SentinelManagedConnection.connect>   s     zz))$*=*=?QRRr   F)timeoutdisconnect_on_errorpush_requestrH   rI   rJ   c                    	 t         |   ||||      S # t        $ r3 | j                  j                  r| j                          t        d       w xY w)N)disable_decodingrH   rI   rJ   z"The previous master is now a slave)r    read_responser   r   r;   
disconnectr
   )r"   rL   rH   rI   rJ   r$   s        r   rM   z'SentinelManagedConnection.read_responseA   sf    	7(!1$7)	 )    		##-- !%&JKK		s	    <A)F)r   r   r   r!   r0   r7   r?   rG   r   r   floatobjectr   boolrM   __classcell__r$   s   @r   r   r      sk    #	
%S
  )1.3', uf}%	
 &d^ tn r   r   c                       e Zd Zy)SentinelManagedSSLConnectionNr   r   r   r   rU   rU   \   r   r   rU   c                   $    e Zd Zd Zd Zd Zd Zy)SentinelConnectionPoolProxyc                     t        j                  |      | _        || _        || _        || _        || _        | j                          y r9   )weakrefrefconnection_pool_refr;   r5   r*   sentinel_managerreset)r"   r   r;   r5   r*   r\   s         r   r!   z$SentinelConnectionPoolProxy.__init__a   s=     $+;;#? " 0( 0

r   c                      d | _         d | _        y r9   )master_addressslave_rr_counterrF   s    r   r]   z!SentinelConnectionPoolProxy.resetp   s    " $r   c                     | j                   j                  | j                        }| j                  r:| j                  |k7  r+|| _        | j                         }||j                  d       |S )NF)inuse_connections)r\   discover_masterr*   r;   r_   r[   rN   )r"   r_   r   s      r   r<   z.SentinelConnectionPoolProxy.get_master_addresst   sg    ..>>t?P?PQ>>d11^C"0D #668O***U*Cr   c              #     K   | j                   j                  | j                        }|r| j                  't	        j
                  dt        |      dz
        | _        t        t        |            D ]5  }| j                  dz   t        |      z  | _        || j                     }| 7 	 | j                          t        d| j                        # t        $ r Y #w xY ww)Nr      zNo slave found for )r\   discover_slavesr*   r`   randomrandintlenranger<   r   r   )r"   slaves_r>   s       r   r=   z)SentinelConnectionPoolProxy.rotate_slaves   s     &&66t7H7HI$$,(.q#f+/(J%3v;' )-)>)>)Bc&k(Q%t445
	))++ !#6t7H7H6K!LMM # 		s*   B'C#*C <C#	C C#C  C#N)r   r   r   r!   r]   r<   r=   r   r   r   rW   rW   `   s    %	Nr   rW   c                   X     e Zd ZdZ fdZd Z fdZed        Z fdZ	d Z
d Z xZS )	SentinelConnectionPoolz
    Sentinel backed connection pool.

    If ``check_connection`` flag is set to True, SentinelManagedConnection
    sends a PING command right after establishing the connection.
    c                    |j                  d|j                  dd      rt        nt              |d<   |j                  dd      | _        |j                  dd      | _        t        | | j                  | j
                  ||      | _        t        | $  d	i | | j                  | j                  d<   || _        || _        y )
Nconnection_classsslFr;   Tr5   )r   r;   r5   r*   r\   r   r   )getr   rU   r   r;   r5   rW   proxyr    r!   connection_kwargsr*   r\   )r"   r*   r\   r#   r$   s       r   r!   zSentinelConnectionPool.__init__   s    %+ZZ ::eU+ -.&
!"  K6 &

+=u E0 nn!22%-

 	"6"48JJ01( 0r   c           	          | j                   rdnd}dt        |       j                   dt        |       j                   d| j                   d| d	S )Nmasterr>   r&   r'   r(   (z))>)r;   r)   r   r   r*   )r"   roles     r   r0   zSentinelConnectionPool.__repr__   sR    >>xwT
%%&aT
(;(;'<))*!D66	
r   c                 V    t         |           | j                  j                          y r9   )r    r]   rs   )r"   r$   s    r   r]   zSentinelConnectionPool.reset   s    

r   c                 .    | j                   j                  S r9   )rs   r_   rF   s    r   r_   z%SentinelConnectionPool.master_address   s    zz(((r   c                     | j                    xs3 | j                   xr% | j                  |j                  |j                  fk(  }t	               }|xr |j                  |      S r9   )r;   r_   r+   r,   r    owns_connection)r"   
connectioncheckparentr$   s       r   r|   z&SentinelConnectionPool.owns_connection   sZ    NN" 
NNXt22z
6XX 	 ;//
;;r   c                 6    | j                   j                         S r9   )rs   r<   rF   s    r   r<   z)SentinelConnectionPool.get_master_address   s    zz,,..r   c                 6    | j                   j                         S )zRound-robin slave balancer)rs   r=   rF   s    r   r=   z$SentinelConnectionPool.rotate_slaves   s    zz''))r   )r   r   r   __doc__r!   r0   r]   propertyr_   r|   r<   r=   rR   rS   s   @r   rn   rn      s:    1.
 ) )</*r   rn   c                   Z    e Zd ZdZ	 	 	 ddZd Zd Zd Zd Zd Z	d	 Z
eefd
ZeefdZy)Sentinelar  
    Redis Sentinel cluster client

    >>> from redis.sentinel import Sentinel
    >>> sentinel = Sentinel([('localhost', 26379)], socket_timeout=0.1)
    >>> master = sentinel.master_for('mymaster', socket_timeout=0.1)
    >>> master.set('foo', 'bar')
    >>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1)
    >>> slave.get('foo')
    b'bar'

    ``sentinels`` is a list of sentinel nodes. Each node is represented by
    a pair (hostname, port).

    ``min_other_sentinels`` defined a minimum number of peers for a sentinel.
    When querying a sentinel, if it doesn't meet this threshold, responses
    from that sentinel won't be considered valid.

    ``sentinel_kwargs`` is a dictionary of connection arguments used when
    connecting to sentinel instances. Any argument that can be passed to
    a normal Redis connection can be specified here. If ``sentinel_kwargs`` is
    not specified, any socket_timeout and socket_keepalive options specified
    in ``connection_kwargs`` will be used.

    ``connection_kwargs`` are keyword arguments that will be used when
    establishing a connection to a Redis server.
    Nc           	          |5|j                         D ci c]  \  }}|j                  d      s|| }}}|| _        |D 	cg c]  \  }}	t        ||	fi | j                   c}	}| _        || _        || _        || _        y c c}}w c c}	}w )Nsocket_)items
startswithsentinel_kwargsr   	sentinelsmin_other_sentinelsrt   _force_master_ip)
r"   r   r   r   force_master_iprt   kvhostnamer,   s
             r   r!   zSentinel.__init__   s     "!2!8!8!:Aall9>U1O   / #,
$ (D9D$8$89
 $7 !2 /

s   BB!B
c                 l   t        |j                  dd            }t        |j                  dd            }|r: t        j                  | j                        j
                  |i |}|r|gS |rdS dS g }| j                  D ]#  }|j                   |j
                  |i |       % |r|S t        |      S )z
        Execute Sentinel command in sentinel nodes.
        once - If set to True, then execute the resulting command on a single
        node at random, rather than across the entire sentinel cluster.
        onceFreturn_responsesT)rQ   r   rg   choicer   execute_commandappendall)r"   argsr#   r   r   response	responsessentinels           r   r   zSentinel.execute_command  s     FJJvu-.  

+=u EFDv}}T^^4DDdUfUH z!'t2U2	 	HH5X55tFvFG	H 9~r   c                    g }| j                   D ]6  }|j                  dj                  |j                  j                               8 dt        |       j                   dt        |       j                   ddj                  |       dS )Nz{host}:{port}r&   r'   z(sentinels=[,z])>)	r   r   
format_mapr   rt   r)   r   r   join)r"   sentinel_addressesr   s      r   r0   zSentinel.__repr__  s     	H%%**8+C+C+U+UV	
 T
%%&aT
(;(;'<388$678=	
r   c                 J    |d   r
|d   s|d   ry|d   | j                   k  ryy)Nr;   is_sdownis_odownFznum-other-sentinelsT)r   )r"   stater*   s      r   check_master_statezSentinel.check_master_state)  s5    [!U:%6%
:K&'$*B*BBr   c                 .   t               }t        | j                        D ]  \  }}	 |j                         }|j                  |      }|s+| j                  ||      s>|| j                  d   c| j                  d<   | j                  |<   | j                  | j                  n|d   }||d   fc S  d}	t        |      dkD  rddj                  |       }	t        d	||	       # t        t
        f$ r }|j                  | d|       Y d}~d}~ww xY w)
z
        Asks sentinel servers for the Redis master's address corresponding
        to the service labeled ``service_name``.

        Returns a pair (address, port) or raises MasterNotFoundError if no
        master is found.
        z - Nr   ipr,    z : z, zNo master found for )list	enumerater   sentinel_mastersr
   r   r   rr   r   r   ri   r   r   )
r"   r*   collected_errorssentinel_nor   masterser   r   
error_infos
             r   rc   zSentinel.discover_master1  s7     6%.t~~%> 	)!K"335 KK-E00E NN1% ?q!4>>+#> ,,8 ))t 
 5=(('	)* 
 1$tyy)9:;<J!$88H"UVV+ $\2  ''8*Cu(=>s   C%%D4DDc                 `    g }|D ]&  }|d   s|d   r|j                  |d   |d   f       ( |S )z1Remove slaves that are in an ODOWN or SDOWN stater   r   r   r,   )r   )r"   rk   slaves_aliver>   s       r   filter_slaveszSentinel.filter_slavesT  sK     	>EZ E*$5teFm <=	> r   c                     | j                   D ]+  }	 |j                  |      }| j                  |      }|s)|c S  g S # t        t        t        f$ r Y Fw xY w)z;Returns a list of alive slaves for service ``service_name``)r   sentinel_slavesr
   r   r   r   )r"   r*   r   rk   s       r   rf   zSentinel.discover_slaves]  sf     	H!11,? ''/F	 	 $]LA s   =AAc                     d|d<   t        | j                        }|j                  |       |j                   ||| fi |      S )a  
        Returns a redis client instance for the ``service_name`` master.
        Sentinel client will detect failover and reconnect Redis clients
        automatically.

        A :py:class:`~redis.sentinel.SentinelConnectionPool` class is
        used to retrieve the master's address before establishing a new
        connection.

        NOTE: If the master's address has changed, any cached connections to
        the old master are closed.

        By default clients will be a :py:class:`~redis.Redis` instance.
        Specify a different class to the ``redis_class`` argument if you
        desire something different.

        The ``connection_pool_class`` specifies the connection pool to
        use.  The :py:class:`~redis.sentinel.SentinelConnectionPool`
        will be used by default.

        All other keyword arguments are merged with any connection_kwargs
        passed to this class and passed to the connection pool as keyword
        arguments to be used to initialize Redis connections.
        Tr;   dictrt   update	from_poolr"   r*   redis_classconnection_pool_classr#   rt   s         r   
master_forzSentinel.master_fori  sP    > #{ !7!78  ($$!,J8IJ
 	
r   c                     d|d<   t        | j                        }|j                  |       |j                   ||| fi |      S )a  
        Returns redis client instance for the ``service_name`` slave(s).

        A SentinelConnectionPool class is used to retrieve the slave's
        address before establishing a new connection.

        By default clients will be a :py:class:`~redis.Redis` instance.
        Specify a different class to the ``redis_class`` argument if you
        desire something different.

        The ``connection_pool_class`` specifies the connection pool to use.
        The SentinelConnectionPool will be used by default.

        All other keyword arguments are merged with any connection_kwargs
        passed to this class and passed to the connection pool as keyword
        arguments to be used to initialize Redis connections.
        Fr;   r   r   s         r   	slave_forzSentinel.slave_for  sP    0 ${ !7!78  ($$!,J8IJ
 	
r   )r   NN)r   r   r   r   r!   r   r0   r   rc   r   rf   r   rn   r   r   r   r   r   r   r      sR    > 008	
!WF
 4	$
R 4	
r   r   )rg   rY   typingr   r   redis.clientr   redis.commandsr   redis.connectionr   r   r	   redis.exceptionsr
   r   r   r   redis.utilsr   r   r   r   rU   rW   rn   r   r   r   r   <module>r      s      "  + F F  !	/ 		 	@
 @F	#<m 	-N -N`:*^ :*z_
 _
r   