bG4ddlZddlZddlZddlmZmZmZmZmZm Z ddl m Z ddl m Z mZmZmZddlmZddlmZmZmZmZddlmZGdd eZGd d eZGd d e ZGddeeZGddeZGddeZy)N) AsyncIteratorIterableMappingSequenceTupleType)Redis) ConnectionConnectionPool EncodableT SSLConnection)AsyncSentinelCommands)ConnectionError ReadOnlyError ResponseError TimeoutError) str_if_bytesc eZdZy)MasterNotFoundErrorN__name__ __module__ __qualname__8/usr/lib/python3/dist-packages/redis/asyncio/sentinel.pyrrrrc eZdZy)SlaveNotFoundErrorNrrrrrrrrrcFeZdZfdZdZfdZdZddeffd ZxZ S)SentinelManagedConnectionc P|jd|_t| di|y)Nconnection_poolr)popr#super__init__)selfkwargs __class__s rr&z"SentinelManagedConnection.__init__s%%zz*;< "6"rc|j}|jjd|j}|jr!d|jd|j }||z }|dzS)N )r#r)r service_namehostport)r'pools host_infos r__repr__z"SentinelManagedConnection.__repr__sb##~~&&'y1B1B0C D 99  6$))=I NA3wrc"K|\|_|_t| d{|jj rI|j dd{t|jd{dk7r tdyy7d777w)NPINGPONGz PING failed) r.r/r%connectr#check_connection send_commandr read_responser)r'addressr)s r connect_toz$SentinelManagedConnection.connect_to's& 49go    0 0##F+ + +$"4"4"6676A%m44B 1 +6s3!BB .BB B0B 1B B Bc~K|jry|jjr:|j|jj d{d{y|jj 23d{} |j|d{cS7P7F7$7 #t $rY8wxYw6twN)_readerr# is_masterr<get_master_address rotate_slavesrr)r'slaves rr7z!SentinelManagedConnection.connect/s <<     ) )//(<(<(O(O(Q"QR R R#33AAC  e!%!777 #R R 7& D % $sxA B=B B=B!B=:B6>B#?B6B=B'B%B'B=!B=#B6%B'' B30B=2B33 B=disable_decodingcK t||d{S7#t$r<|jjr$|j d{7t dwxYww)N)rDz"The previous master is now a slave)r%r:rr#r@ disconnectr)r'rDr)s rr:z'SentinelManagedConnection.read_response<sd .@P.QQ QQ ##-- oo'''%&JKK  s1A'A'2A$AA$$A')F) rrrr&r3r<r7boolr: __classcell__r)s@rr!r!s(#5 % D  rr!c eZdZy)SentinelManagedSSLConnectionNrrrrrKrKKrrrKcTeZdZdZfdZdZfdZdeffd ZdZ de fd Z xZ 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 ^|jd|jddrtnt|d<|jdd|_|jdd|_t |di|tj||jd<||_ ||_ d|_ d|_y) Nconnection_classsslFr@Tr8r#r)getr$rKr!r@r8r%r&weakrefproxyconnection_kwargsr-sentinel_managermaster_addressslave_rr_counter)r'r-rUr(r)s rr&zSentinelConnectionPool.__init__Ws%+ZZ zz%' )* & !"  K6 & +=u E "6"4;MM$4G01( 0" $rcx|jjd|jd|jxrdxsddS)Nr+(masterrCz)>)r)rr-r@)r's rr3zSentinelConnectionPool.__repr__gsC~~&&'))*!DNN,Gx,R7+SSU W rc>t|d|_d|_yr>)r%resetrVrW)r'r)s rr\zSentinelConnectionPool.resetms  " $r connectionc|j xs3|jxr%|j|j|jfk(}|xrt||Sr>)r@rVr.r/r%owns_connection)r'r]checkr)s rr_z&SentinelConnectionPool.owns_connectionrsRNN" NN Xt22z 6XX <0<>""n4&4#ooo>>>X ?s!)A2A.;A2'A0(A20A2returncK|jj|jd{}|r|j't j dt |dz |_tt |D]6}|jdzt |z|_||j}|8 |jd{td|j77!#t$rY'wxYww)zRound-robin slave balancerNrzNo slave found for ) rUdiscover_slavesr-rWrandomrandintlenrangerArr)r'slaves_rCs rrBz$SentinelConnectionPool.rotate_slavess,,<)>)Bc&k(Q%t445    //11 1!#6t7H7H6K!LMMP2"   sF)C9C&BC93C*C(C*C9(C** C63C95C66C9) rrr__doc__r&r3r\r r_rArrBrHrIs@rrMrMOs6%  % =*= N]NrrMceZdZdZ ddZdZdZdedede fd Z defd Z d e e deeeeffd Zdedeeeeffd ZeefdedeedeefdZeefdedeedeefdZy)Sentinela~ 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) >>> await master.set('foo', 'bar') >>> slave = sentinel.slave_for('mymaster', socket_timeout=0.1) >>> await 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]\}}td||d|jc}}|_||_||_ycc}}wcc}}w)Nsocket_)r.r/r)items startswithsentinel_kwargsr sentinelsmin_other_sentinelsrT) r'rvrwrurTkvhostnamer/s rr&zSentinel.__init__s  "!2!8!8!:Aall9>U1O /#, $  Cxd Cd.B.B C $7 !2  sA>A>"Bc Kt|jdd}d|jvr|jd|rW|jDcgc]'}t j |j|i|)}}t j|d{ytj|jj|i|d{ycc}w7B7 w)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. onceFNT) rGrQkeysr$rvasyncioTaskexecute_commandgatherrhchoice)r'argsr(r|sentineltaskss rrzSentinel.execute_commands FJJvu-. V[[] " JJv  !% 5X55tFvFGE..%( ( (@&--/??PP P P ) Ps0AC,C=CC7C C CCcg}|jD]F}|j|jjdd|jjdH|jj ddj |dS)Nr.:r/z )rvappendr#rTr)rjoin)r'sentinel_addressesrs rr3zSentinel.__repr__s H  % %++==fEFa++==fEFH   ..))*,sxx@R7S6TTVWWrstater-rdcJ|dr |ds|dry|d|jkryy)Nr@is_sdownis_odownFznum-other-sentinelsT)rw)r'rr-s rcheck_master_statezSentinel.check_master_states5[!U:%6% :K & '$*B*B Brc|Kt|jD]|\}} |jd{}|j |}|s3|j ||sF||jdc|jd<|j|<|d|dfcStd|7r#ttf$rYwxYww)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. Nripr/zNo master found for ) enumeratervsentinel_mastersrrrQrr)r'r- sentinel_normastersrs rrczSentinel.discover_masters&/t~~%> 2 !K  ( 9 9 ;;KK -E00 ENN1%?q!4>>+#>T{E&M11 2"$88H"IJJ<#\2  sDB<B'B%B'B< B<AB<%B''B96B<8B99B<rlc`g}|D]&}|ds|dr|j|d|df(|S)z1Remove slaves that are in an ODOWN or SDOWN staterrrr/)r)r'rl slaves_aliverCs r filter_slaveszSentinel.filter_slavessM  >EZ E*$5   teFm < = >rcK|jD]3} |j|d{}|j |}|s1|cSgS7#tttf$rYPwxYww)z;Returns a list of alive slaves for service ``service_name``N)rvsentinel_slavesrrrr)r'r-rrls rrgzSentinel.discover_slavessr H '77 EE''/F   F#]LA  s=A#A AA A#A#A  A A#A  A# redis_classconnection_pool_classc 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. Tr@r#dictrTupdater'r-rrr(rTs r master_forzSentinel.master_forsO:#{ !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. Fr@rrrs r slave_forzSentinel.slave_forBsO0${ !7!78  (1d&7  r)rN)rrrrnr&rr3rstrrGrrcrrrrr rrgr rMrrrrrrrprps> 3,(XCDK#K. w'  % J./ 0    % J./ 0 "$)>T $ $ %[$  $$:; $ R$)>T   %[  $$:;  rrp) r~rhrRtypingrrrrrrredis.asyncio.clientr redis.asyncio.connectionr r r r redis.commandsrredis.exceptionsrrrr redis.utilsrrrr!rKrMrprrrrs JJ& 1XX$ /   . .b #