bR1ddlZddlZddlmZddlmZddlmZmZm Z ddl m Z m Z m Z mZddlmZGdde ZGd d e ZGd d eZGd dee ZGddeZGddeZy)N)Redis)SentinelCommands) ConnectionConnectionPool SSLConnection)ConnectionError ReadOnlyError ResponseError TimeoutError) str_if_bytesc eZdZy)MasterNotFoundErrorN__name__ __module__ __qualname__0/usr/lib/python3/dist-packages/redis/sentinel.pyrr rrc eZdZy)SlaveNotFoundErrorNrrrrrrrrrcFeZdZfdZdZfdZdZdZdfd ZxZ S)SentinelManagedConnectionc P|jd|_t| di|y)Nconnection_poolr)poprsuper__init__)selfkwargs __class__s rrz"SentinelManagedConnection.__init__s%%zz*;< "6"rc|j}t|jd|jd}|jr!d|jd|j }||z}|S)N z,host=z,port=)rtyper service_namehostport)r pools host_infos r__repr__z"SentinelManagedConnection.__repr__s`##Dz""#9T->->,?s C 99  6$))=II Arc|\|_|_t| |jj r9|j dt|jdk7r tdyy)NPINGPONGz PING failed) r'r(rconnectrcheck_connection send_commandr read_responser)r addressr"s r connect_toz$SentinelManagedConnection.connect_to sc& 49     0 0   f %D..01V;%m44< 1rc*|jry|jjr*|j|jj y|jj D]} |j|cSt#t $rY)wxYwN)_sockr is_masterr5get_master_address rotate_slavesrr)r slaves r_connect_retryz(SentinelManagedConnection._connect_retry(s ::     ) ) OOD00CCE F--;;= ??511  % $'s,B BBcP|jj|jdS)Ncyr7r)errors rz3SentinelManagedConnection.connect..6sr)retrycall_with_retryr=)r s rr0z!SentinelManagedConnection.connect5s zz))$*=*=?QRRrc t||S#t$r3|jjr|j t dwxYw)N)disable_decodingz"The previous master is now a slave)rr3r rr9 disconnectr)r rEr"s rr3z'SentinelManagedConnection.read_response8sU 7(:J(K K ##-- !%&JKK  s >xwt*%%&i0A0A/B!D6KKrc>t|d|_d|_yr7)rresetmaster_addressslave_rr_counter)r r"s rr[zSentinelConnectionPool.resetes  " $rc|j xs3|jxr%|j|j|jfk(}t }|xr|j |Sr7)r9r\r'r(rowns_connection)r connectioncheckparentr"s rr_z&SentinelConnectionPool.owns_connectionjsZNN" NN Xt22z 6XX ;// ;;rc|jj|j}|jr(|j|k7r||_|j d|S)NF)inuse_connections)rTdiscover_masterr&r9r\rF)r r\s rr:z)SentinelConnectionPool.get_master_addressqsQ..>>t?P?PQ >>""n4&4#%8rc#K|jj|j}|r|j't j dt |dz |_tt |D]5}|jdzt |z|_||j}|7 |jtd|j#t$rY#wxYww)zRound-robin slave balancerrzNo slave found for ) rTdiscover_slavesr&r]randomrandintlenranger:rr)r slaves_r<s rr;z$SentinelConnectionPool.rotate_slaves{s&&66t7H7HI $$,(.q#f+/(J%3v;' )-)>)>)Bc&k(Q%t445    ))+ +!#6t7H7H6K!LMM#   s*B'C#*C<C# C C#C  C#) rrr__doc__rr,r[r_r:r;rGrHs@rrLrLKs( 1L% <NrrLcXeZdZdZ d dZdZdZdZdZdZ d Z e e fd Z e e fd Zy) 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|jDcic]\}}|jds||}}}||_|Dcgc]\}}t||fi|jc}}|_||_||_ycc}}wcc}}w)Nsocket_)items startswithsentinel_kwargsr sentinelsmin_other_sentinelsrS) r rwrxrvrSkvhostnamer(s rrzSentinel.__init__s  "!2!8!8!:Aall9>U1O /#, $ (D 9D$8$8 9 $7 !2  sA=A=!Bc*t|jdd}d|jvr|jd|r$|jD]}|j |i|yt j|jj |i|y)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. onceFT)boolrPkeysrrwexecute_commandrichoice)r argsr!r}sentinels rrzSentinel.execute_commands FJJvu-. V[[] " JJv   NN :((($9&9 : :FMM$.. ) 9 94 J6 Jrcg}|jD]6}|jdj|jj8t |j ddj|dS)Nz {host}:{port}z )rwappend format_maprrSr%rjoin)r sentinel_addressesrs rr,zSentinel.__repr__so H  % %**8+C+C+U+UV  t*%%&l388||jdc|jd<|j|<|d|dfcStd|#ttf$rYwxYw)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. ripr(zNo master found for ) enumeraterwsentinel_mastersrr rPrr)r r& sentinel_normastersrs rrezSentinel.discover_masters&/t~~%> 2 !K "335KK -E00 ENN1%?q!4>>+#>T{E&M11 2"$88H"IJJ$\2  sBB-,B-c`g}|D]&}|ds|dr|j|d|df(|S)z1Remove slaves that are in an ODOWN or SDOWN staterrrr()r)r rm slaves_aliver<s r filter_slaveszSentinel.filter_slavessK  >EZ E*$5   teFm < = >rc|jD]+} |j|}|j |}|s)|cSgS#tttf$rYFwxYw)z;Returns a list of alive slaves for service ``service_name``)rwsentinel_slavesrr r r)r r&rrms rrhzSentinel.discover_slavessf H !11,?''/F   $]LA  s=AAc zd|d<t|j}|j|||||fi|S)a Returns a redis client instance for the ``service_name`` master. 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. Tr9rdictrSupdater r& redis_classconnection_pool_classr!rSs r master_forzSentinel.master_for sO:#{ !7!78  (1d&7  rc zd|d<t|j}|j|||||fi|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. Fr9rrrs r slave_forzSentinel.slave_for3sO0${ !7!78  (1d&7  r)rN)rrrrorrr,rrerrhrrLrrrrrrqrqsO> 3,"TK. 4 $ R4  rrq)rirQ redis.clientrredis.commandsrredis.connectionrrrredis.exceptionsrr r r redis.utilsr rrrrJrLrqrrrrsr +FFXX$ /   1 1h #