o
    <‘ði:  ã                   @   sê   d dl Z d dlZd dlZd dlmZmZmZmZmZm	Z	m
Z
 d dlmZ d dlmZmZmZmZ d dlmZ d dlmZmZmZmZ G dd„ deƒZG d	d
„ d
eƒZG dd„ deƒZG dd„ deeƒZG dd„ deƒZG dd„ deƒZdS )é    N)ÚAsyncIteratorÚIterableÚMappingÚOptionalÚSequenceÚTupleÚType)ÚRedis)Ú
ConnectionÚConnectionPoolÚ
EncodableTÚSSLConnection)ÚAsyncSentinelCommands)ÚConnectionErrorÚReadOnlyErrorÚResponseErrorÚTimeoutErrorc                   @   ó   e Zd ZdS )ÚMasterNotFoundErrorN©Ú__name__Ú
__module__Ú__qualname__© r   r   úU/root/parts/websockify/install/lib/python3.10/site-packages/redis/asyncio/sentinel.pyr      ó    r   c                   @   r   )ÚSlaveNotFoundErrorNr   r   r   r   r   r      r   r   c                       st   e Zd Z‡ fdd„Zdd„ Zdd„ Zdd„ Zd	d
„ Z		ddddœdede	e
 de	e
 de	e f‡ fdd„Z‡  ZS )ÚSentinelManagedConnectionc                    s"   |  d¡| _tƒ jdi |¤Ž d S )NÚconnection_poolr   )Úpopr   ÚsuperÚ__init__)ÚselfÚkwargs©Ú	__class__r   r   r!      s   z"SentinelManagedConnection.__init__c                 C   sB   d| j j› d| j j› �}| jrd| j› d| j› �}||7 }|d S )Nú<Ú.z,host=z,port=z)>)r%   r   r   ÚhostÚport)r"   ÚsÚ	host_infor   r   r   Ú__repr__#   s
   z"SentinelManagedConnection.__repr__c                 Ã   s*   �|\| _ | _| j| jjdd�I d H  d S )NF)Úcheck_healthÚretry_socket_connect)r(   r)   Úconnect_check_healthr   Úcheck_connection)r"   Úaddressr   r   r   Ú
connect_to*   s   €þz$SentinelManagedConnection.connect_toc              	   Ã   sz   �| j rd S | jjr|  | j ¡ I d H ¡I d H  d S | j ¡ 2 z3 d H W }z|  |¡I d H W   S  ty9   Y qw 6 t‚©N)Ú_readerr   Ú	is_masterr2   Úget_master_addressÚrotate_slavesr   r   )r"   Úslaver   r   r   Ú_connect_retry1   s   € ÿýz(SentinelManagedConnection._connect_retryc                 Ã   s   �| j  | jdd„ ¡I d H S )Nc                 S   s
   t  d¡S )Nr   )ÚasyncioÚsleep)Úerrorr   r   r   Ú<lambda>A   s   
 z3SentinelManagedConnection.connect.<locals>.<lambda>)ÚretryÚcall_with_retryr9   ©r"   r   r   r   Úconnect>   s
   €
þz!SentinelManagedConnection.connectFNT)Údisconnect_on_errorÚpush_requestÚdisable_decodingÚtimeoutrB   rC   c                ƒ   sN   �zt ƒ j||||d�I d H W S  ty&   | jjr%|  ¡ I d H  tdƒ‚‚ w )N)rD   rE   rB   rC   z"The previous master is now a slave)r    Úread_responser   r   r5   Ú
disconnectr   )r"   rD   rE   rB   rC   r$   r   r   rF   D   s   €ü÷z'SentinelManagedConnection.read_response)FN)r   r   r   r!   r,   r2   r9   rA   Úboolr   ÚfloatrF   Ú__classcell__r   r   r$   r   r      s(    ýúþýûúr   c                   @   r   )ÚSentinelManagedSSLConnectionNr   r   r   r   r   rK   _   r   rK   c                       s\   e Zd ZdZ‡ fdd„Zdd„ Z‡ fdd„Zdef‡ fd	d
„Zdd„ Z	de
fdd„Z‡  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                    sz   |  d| dd¡rtnt¡|d< | dd¡| _| dd¡| _tƒ jdi |¤Ž t 	| ¡| j
d< || _|| _d | _d | _d S )	NÚconnection_classÚsslFr5   Tr0   r   r   )Úgetr   rK   r   r5   r0   r    r!   ÚweakrefÚproxyÚconnection_kwargsÚservice_nameÚsentinel_managerÚmaster_addressÚslave_rr_counter)r"   rS   rT   r#   r$   r   r   r!   k   s   
ÿû
zSentinelConnectionPool.__init__c              	   C   s2   d| j j› d| j j› d| j› d| jrdpd› d�	S )Nr&   r'   z	(service=ú(Úmasterr8   z))>)r%   r   r   rS   r5   r@   r   r   r   r,   }   s   ÿÿÿzSentinelConnectionPool.__repr__c                    s   t ƒ  ¡  d | _d | _d S r3   )r    ÚresetrU   rV   r@   r$   r   r   rY   ƒ   s   

zSentinelConnectionPool.resetÚ
connectionc                    s0   | j  p| j o| j|j|jfk}|otƒ  |¡S r3   )r5   rU   r(   r)   r    Úowns_connection)r"   rZ   Úcheckr$   r   r   r[   ˆ   s   ÿz&SentinelConnectionPool.owns_connectionc                 Ã   sB   �| j  | j¡I d H }| jr| j|kr|| _| jdd�I d H  |S )NF)Úinuse_connections)rT   Údiscover_masterrS   r5   rU   rG   )r"   rU   r   r   r   r6   Ž   s   €
z)SentinelConnectionPool.get_master_addressÚreturnc                 C  s¨   �| j  | j¡I dH }|r8| jdu rt dt|ƒd ¡| _tt|ƒƒD ]}| jd t|ƒ | _|| j }|V  q#z
|  ¡ I dH V  W n	 t	yK   Y nw t
d| j›�ƒ‚)zRound-robin slave balancerNr   é   zNo slave found for )rT   Údiscover_slavesrS   rV   ÚrandomÚrandintÚlenÚranger6   r   r   )r"   ÚslavesÚ_r8   r   r   r   r7   ˜   s   €

ÿz$SentinelConnectionPool.rotate_slaves)r   r   r   Ú__doc__r!   r,   rY   r
   r[   r6   r   r7   rJ   r   r   r$   r   rL   c   s    
rL   c                   @   sÜ   e Zd ZdZ			ddd„Zdd„ Zdd	„ Zd
edede	fdd„Z
defdd„Zdee deeeef  fdd„Zdedeeeef  fdd„Zeefdedee dee fdd„Zeefdedee dee fdd„ZdS )Ú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.
    r   Nc                    sJ   |d u rdd„ |  ¡ D ƒ}|ˆ _‡ fdd„|D ƒˆ _|ˆ _|ˆ _|ˆ _d S )Nc                 S   s    i | ]\}}|  d ¡r||“qS )Úsocket_)Ú
startswith)Ú.0ÚkÚvr   r   r   Ú
<dictcomp>Ò   s
    ÿÿz%Sentinel.__init__.<locals>.<dictcomp>c                    s&   g | ]\}}t d||d œˆ j¤Ž‘qS ))r(   r)   r   )r	   Úsentinel_kwargs)rl   Úhostnamer)   r@   r   r   Ú
<listcomp>×   s    ÿÿz%Sentinel.__init__.<locals>.<listcomp>)Úitemsrp   Ú	sentinelsÚmin_other_sentinelsrR   Ú_force_master_ip)r"   rt   ru   rp   Úforce_master_iprR   r   r@   r   r!   Ç   s   
ÿ
þ
zSentinel.__init__c                 �   s�   �t ˆ dd¡ƒ}t ˆ dd¡ƒ}|r-t | j¡jˆ i ˆ¤ŽI dH }|r'|gS |r+dS dS ‡ ‡fdd„| jD ƒ}tj|Ž I dH }|rD|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_responsesNTc                    s"   g | ]}t  |jˆ i ˆ¤Ž¡‘qS r   )r:   ÚTaskÚexecute_command)rl   Úsentinel©Úargsr#   r   r   rr   ô   s    ÿÿz,Sentinel.execute_command.<locals>.<listcomp>)	rH   r   rb   Úchoicert   r{   r:   ÚgatherÚall)r"   r~   r#   rx   ry   ÚresponseÚtasksÚ	responsesr   r}   r   r{   ß   s&   €ÿÿþzSentinel.execute_commandc                 C   sX   g }| j D ]}| |jjd › d|jjd › �¡ qd| j› d| jj› dd |¡› d�S )	Nr(   ú:r)   r&   r'   z(sentinels=[ú,z])>)rt   Úappendr   rR   r%   r   Újoin)r"   Úsentinel_addressesr|   r   r   r   r,   ÿ   s   

ÿÿÿÿzSentinel.__repr__ÚstaterS   r_   c                 C   s2   |d r|d s|d rdS |d | j k rdS dS )Nr5   Úis_sdownÚis_odownFznum-other-sentinelsT)ru   )r"   rŠ   rS   r   r   r   Úcheck_master_state  s
   zSentinel.check_master_statec           
      Ã   sü   �t ƒ }t| jƒD ][\}}z	| ¡ I dH }W n ttfy4 } z| |› d|›�¡ W Y d}~q	d}~ww | |¡}|rd|  ||¡rd|| jd | jd< | j|< | j	durX| j	n|d }||d f  S q	d}	t
|ƒdkrudd |¡› �}	td	|›|	› �ƒ‚)
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.
        Nz - r   Úipr)   Ú z : z, zNo master found for )ÚlistÚ	enumeratert   Úsentinel_mastersr   r   r‡   rO   r�   rv   rd   rˆ   r   )
r"   rS   Úcollected_errorsÚsentinel_nor|   ÚmastersÚerŠ   rŽ   Ú
error_infor   r   r   r^     s2   €€þ
þ
ÿý€zSentinel.discover_masterrf   c                 C   s:   g }|D ]}|d s|d rq|  |d |d f¡ q|S )z1Remove slaves that are in an ODOWN or SDOWN staterŒ   r‹   rŽ   r)   )r‡   )r"   rf   Úslaves_aliver8   r   r   r   Úfilter_slaves6  s   zSentinel.filter_slavesc                 Ã   sV   �| j D ]$}z
| |¡I dH }W n tttfy   Y qw |  |¡}|r(|  S qg S )z;Returns a list of alive slaves for service ``service_name``N)rt   Úsentinel_slavesr   r   r   r™   )r"   rS   r|   rf   r   r   r   ra   A  s   €
ÿ
ÿzSentinel.discover_slavesÚredis_classÚconnection_pool_classc                 K   ó8   d|d< t | 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.
        Tr5   ©ÚdictrR   ÚupdateÚ	from_pool©r"   rS   r›   rœ   r#   rR   r   r   r   r   Ú
master_forO  s
   


zSentinel.master_forc                 K   r�   )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.
        Fr5   rž   r¢   r   r   r   Ú	slave_forv  s
   


zSentinel.slave_for)r   NN)r   r   r   rh   r!   r{   r,   rŸ   ÚstrrH   r�   r^   r   r   r   r   r   r™   ra   r	   rL   r   r£   r¤   r   r   r   r   ri   ª   sL    
û #ÿ
þÿ
þüþý
ü*üþýüri   )r:   rb   rP   Útypingr   r   r   r   r   r   r   Úredis.asyncio.clientr	   Úredis.asyncio.connectionr
   r   r   r   Úredis.commandsr   Úredis.exceptionsr   r   r   r   r   r   r   rK   rL   ri   r   r   r   r   Ú<module>   s    $AG