
    ph:                         S SK r S SKrS SKJ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JrJr   " S S\5      r " S	 S
\5      r " S S\	5      r " S S\\5      r " S S5      r " S S\
5      r " S S\5      rg)    N)Optional)Redis)SentinelCommands)
ConnectionConnectionPoolSSLConnection)ConnectionErrorReadOnlyErrorResponseErrorTimeoutErrorc                       \ rS rSrSrg)MasterNotFoundError    N__name__
__module____qualname____firstlineno____static_attributes__r       H/home/james-whalen/.local/lib/python3.13/site-packages/redis/sentinel.pyr   r          r   r   c                       \ rS rSrSrg)SlaveNotFoundError   r   Nr   r   r   r   r   r      r   r   r   c                   t   ^  \ rS rSrU 4S jrS rS rS rS r SSSS.S	\	\
   S
\	\
   4U 4S jjjjrSrU =r$ )SentinelManagedConnection   c                 R   > UR                  S5      U l        [        TU ]  " S0 UD6  g )Nconnection_poolr   )popr!   super__init__)selfkwargs	__class__s     r   r$   "SentinelManagedConnection.__init__   s%    %zz*;<"6"r   c                     U R                   nS[        U 5      R                   S[        U 5      R                   SUR                   S3nU R
                  (       a   SU R
                   SU R                   3nX#-  nU$ )N<.	(service=z%s)>z,host=z,port=)r!   typer   r   service_namehostport)r%   pools	host_infos       r   __repr__"SentinelManagedConnection.__repr__   sy    ##T
%%&aT
(;(;'<))*$0 	
 99 6$))=IAr   c                 j    Uu  U l         U l        U R                  U R                  R                  SS9  g )NF)check_healthretry_socket_connect)r/   r0   connect_check_healthr!   check_connection)r%   addresss     r   
connect_to$SentinelManagedConnection.connect_to(   s5    &	49!!-->>!& 	" 	
r   c                 D   U R                   (       a  g U R                  R                  (       a*  U R                  U R                  R	                  5       5        g U R                  R                  5        H  n U R                  U5      s  $    [        e! [         a     M,  f = fN)_sockr!   	is_masterr<   get_master_addressrotate_slavesr	   r   )r%   slaves     r   _connect_retry(SentinelManagedConnection._connect_retry0   s    ::))OOD00CCEF--;;=??511 >
 %$ ' s   6B
BBc                 P    U R                   R                  U R                  S 5      $ )Nc                     g r?   r   )errors    r   <lambda>3SentinelManagedConnection.connect.<locals>.<lambda>>   s    Tr   )retrycall_with_retryrE   r%   s    r   connect!SentinelManagedConnection.connect=   s     zz))$*=*=?QRRr   F)disconnect_on_errorpush_requestrQ   rR   c                   >  [         TU ]  UUUS9$ ! [         a8    U R                  R                  (       a  U R                  5         [        S5      ee f = f)N)disable_decodingrQ   rR   z"The previous master is now a slave)r#   read_responser
   r!   rA   
disconnectr	   )r%   rT   rQ   rR   r'   s       r   rU   'SentinelManagedConnection.read_response@   sc    	7(!1$7) )  
  		##-- !%&JKK		s
    AA)r!   r/   r0   )F)r   r   r   r   r$   r4   r<   rE   rO   r   boolrU   r   __classcell__r'   s   @r   r   r      sU    #	
%S
  /4', &d^	
 tn r   r   c                       \ rS rSrSrg)SentinelManagedSSLConnectionY   r   Nr   r   r   r   r\   r\   Y   r   r   r\   c                   ,    \ rS rSrS rS rS rS rSrg)SentinelConnectionPoolProxy]   c                     [         R                  " U5      U l        X l        X0l        X@l        XPl        U R                  5         g r?   )weakrefrefconnection_pool_refrA   r:   r.   sentinel_managerreset)r%   r!   rA   r:   r.   re   s         r   r$   $SentinelConnectionPoolProxy.__init__^   s5     $+;;#? " 0( 0

r   c                      S U l         S U l        g r?   )master_addressslave_rr_counterrN   s    r   rf   !SentinelConnectionPoolProxy.resetm   s    " $r   c                     U R                   R                  U R                  5      nU R                  (       a8  U R                  U:w  a(  Xl        U R                  5       nUb  UR                  SS9  U$ )NF)inuse_connections)re   discover_masterr.   rA   ri   rd   rV   )r%   ri   r!   s      r   rB   .SentinelConnectionPoolProxy.get_master_addressq   se    ..>>t?P?PQ>>d11^C"0 #668O***U*Cr   c              #     #    U R                   R                  U R                  5      nU(       a  U R                  c(  [        R
                  " S[        U5      S-
  5      U l        [        [        U5      5       H5  nU R                  S-   [        U5      -  U l        XR                     nUv   M7      U R                  5       v   [        SU R                  < 35      e! [         a     N%f = f7f)Nr      zNo slave found for )re   discover_slavesr.   rj   randomrandintlenrangerB   r   r   )r%   slaves_rD   s       r   rC   )SentinelConnectionPoolProxy.rotate_slaves|   s     &&66t7H7HI$$,(.q#f+/(J%3v;')-)>)>)Bc&k(Q%445 (
	))++ !#6t7H7H6K!LMM # 		s*   B/C-2C C-
C*'C-)C**C-)r:   rd   rA   ri   re   r.   rj   N)	r   r   r   r   r$   rf   rB   rC   r   r   r   r   r_   r_   ]   s    %	Nr   r_   c                   f   ^  \ rS rSrSrU 4S jrS rU 4S jr\S 5       r	U 4S jr
S rS	 rS
rU =r$ )SentinelConnectionPool   z
Sentinel backed connection pool.

If ``check_connection`` flag is set to True, SentinelManagedConnection
sends a PING command right after establishing the connection.
c                   > UR                  SUR                  SS5      (       a  [        O[        5      US'   UR                  SS5      U l        UR                  SS5      U l        [        U U R                  U R
                  UUS9U l        [        TU ]$  " S	0 UD6  U R                  U R                  S'   Xl        X l        g )
Nconnection_classsslFrA   Tr:   )r!   rA   r:   r.   re   r!   r   )getr"   r\   r   rA   r:   r_   proxyr#   r$   connection_kwargsr.   re   )r%   r.   re   r&   r'   s       r   r$   SentinelConnectionPool.__init__   s    %+ZZ ::eU++ -.&
!"  K6 &

+=u E0 nn!22%-

 	"6"48JJ01( 0r   c           	          U R                   (       a  SOSnS[        U 5      R                   S[        U 5      R                   SU R                   SU S3	$ )NmasterrD   r*   r+   r,   (z))>)rA   r-   r   r   r.   )r%   roles     r   r4   SentinelConnectionPool.__repr__   sR    >>xwT
%%&aT
(;(;'<))*!D66	
r   c                 V   > [         TU ]  5         U R                  R                  5         g r?   )r#   rf   r   )r%   r'   s    r   rf   SentinelConnectionPool.reset   s    

r   c                 .    U R                   R                  $ r?   )r   ri   rN   s    r   ri   %SentinelConnectionPool.master_address   s    zz(((r   c                    > U R                   (       + =(       d8    U R                   =(       a%    U R                  UR                  UR                  4:H  n[	        5       nU=(       a    UR                  U5      $ r?   )rA   ri   r/   r0   r#   owns_connection)r%   
connectioncheckparentr'   s       r   r   &SentinelConnectionPool.owns_connection   sZ    NN" 
NNXt22z
6XX 	 ;//
;;r   c                 6    U R                   R                  5       $ r?   )r   rB   rN   s    r   rB   )SentinelConnectionPool.get_master_address   s    zz,,..r   c                 6    U R                   R                  5       $ )zRound-robin slave balancer)r   rC   rN   s    r   rC   $SentinelConnectionPool.rotate_slaves   s    zz''))r   )r:   rA   r   re   r.   )r   r   r   r   __doc__r$   r4   rf   propertyri   r   rB   rC   r   rY   rZ   s   @r   r{   r{      s?    1.
 ) )</* *r   r{   c                   h    \ rS rSrSr   SS jrS rS rS rS r	S	 r
S
 r\\4S jr\\4S jrSrg)Sentinel   a  
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           	      *   Uc<  UR                  5        VVs0 s H  u  pgUR                  S5      (       d  M  Xg_M!     nnnX0l        U VV	s/ s H  u  p[        X40 U R                  D6PM     sn	nU l        X l        XPl        X@l        g s  snnf s  sn	nf )Nsocket_)items
startswithsentinel_kwargsr   	sentinelsmin_other_sentinelsr   _force_master_ip)
r%   r   r   r   force_master_ipr   kvhostnamer0   s
             r   r$   Sentinel.__init__   s     "!2!8!8!:!:all9>U!:    / #,
"+ (9D$8$89"+
 $7 !2 /

s   B	B	"Bc                    [        UR                  SS5      5      n[        UR                  SS5      5      nU(       aE  [        R                  " U R                  5      R
                  " U0 UD6nU(       a  U/$ U(       a  S$ S$ / nU R                   H$  nUR                  UR
                  " U0 UD65        M&     U(       a  U$ [        U5      $ )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)rX   r"   rs   choicer   execute_commandappendall)r%   argsr&   r   r   response	responsessentinels           r   r   Sentinel.execute_command   s     FJJvu-.  

+=u EF}}T^^4DDdUfUH z!'t2U2	HX55tFvFG ' 9~r   c                    / nU R                    H7  nUR                  SR                  UR                  R                  5      5        M9     S[        U 5      R                   S[        U 5      R                   SSR                  U5       S3$ )Nz{host}:{port}r*   r+   z(sentinels=[,z])>)	r   r   
format_mapr!   r   r-   r   r   join)r%   sentinel_addressesr   s      r   r4   Sentinel.__repr__  s    H%%**8+C+C+U+UV '
 T
%%&aT
(;(;'<388$678=	
r   c                 j    US   (       a  US   (       d
  US   (       a  gUS   U R                   :  a  gg)NrA   is_sdownis_odownFznum-other-sentinelsT)r   )r%   stater.   s      r   check_master_stateSentinel.check_master_state&  s5    [!U:%6%
:K&'$*B*BBr   c                 N   [        5       n[        U R                  5       H  u  p4 UR                  5       nUR                  U5      nU(       d  M0  U R                  Xq5      (       d  MH  UU R                  S   sU R                  S'   U R                  U'   U R                  b  U R                  OUS   nXS   4s  $    Sn	[        U5      S:  a  SSR                  U5       3n	[        S	U< U	 35      e! [        [
        4 a"  nUR                  U SU< 35         SnAM  SnAff = f)
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   ipr0    z : z, zNo master found for )list	enumerater   sentinel_mastersr	   r   r   r   r   r   ru   r   r   )
r%   r.   collected_errorssentinel_nor   masterser   r   
error_infos
             r   rn   Sentinel.discover_master.  s1     6%.t~~%>!K"335 KK-Eu00EE NN1% ?q!4>>+#> ,,8 ))t 
 =((' &?* 
 1$tyy)9:;<J!$88H"UVV+ $\2  ''8*Cu(=>s   C22D$DD$c                 z    / nU H2  nUS   (       d
  US   (       a  M  UR                  US   US   45        M4     U$ )z1Remove slaves that are in an ODOWN or SDOWN stater   r   r   r0   )r   )r%   rw   slaves_aliverD   s       r   filter_slavesSentinel.filter_slavesQ  sF    EZ E*$5teFm <=  r   c                     U R                    H1  n UR                  U5      nU R                  U5      nU(       d  M/  Us  $    / $ ! [        [        [        4 a     MO  f = f)z;Returns a list of alive slaves for service ``service_name``)r   sentinel_slavesr	   r   r   r   )r%   r.   r   rw   s       r   rr   Sentinel.discover_slavesZ  sc    H!11,? ''/Fv ' 	 $]LA s   AAAc                     SUS'   [        U R                  5      nUR                  U5        UR                  U" X40 UD65      $ )am  
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.
TrA   dictr   update	from_poolr%   r.   redis_classconnection_pool_classr&   r   s         r   
master_forSentinel.master_forf  sN    > #{ !7!78  ($$!,J8IJ
 	
r   c                     SUS'   [        U R                  5      nUR                  U5        UR                  U" X40 UD65      $ )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.
FrA   r   r   s         r   	slave_forSentinel.slave_for  sN    0 ${ !7!78  ($$!,J8IJ
 	
r   )r   r   r   r   r   )r   NN)r   r   r   r   r   r$   r   r4   r   rn   r   rr   r   r{   r   r   r   r   r   r   r   r      sR    > 008	
!WF
 4	$
R 4	
r   r   )rs   rb   typingr   redis.clientr   redis.commandsr   redis.connectionr   r   r   redis.exceptionsr	   r
   r   r   r   r   r   r\   r_   r{   r   r   r   r   <module>r      s        + F F 	/ 		 	>
 >B	#<m 	-N -N`:*^ :*z_
 _
r   