o
    <‘ði¥:  ã                   @   sÔ   d dl Z d dlZd dl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 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ƒZG dd„ de
ƒZG dd„ deƒZdS )é    N)ÚOptional)ÚRedis)ÚSentinelCommands)Ú
ConnectionÚConnectionPoolÚSSLConnection)ÚConnectionErrorÚReadOnlyErrorÚResponseErrorÚTimeoutErrorc                   @   ó   e Zd ZdS )ÚMasterNotFoundErrorN©Ú__name__Ú
__module__Ú__qualname__© r   r   úM/root/parts/websockify/install/lib/python3.10/site-packages/redis/sentinel.pyr      ó    r   c                   @   r   )ÚSlaveNotFoundErrorNr   r   r   r   r   r      r   r   c                       sf   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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   sR   | j }dt| ƒj› dt| ƒj› d|j› d�}| jr'd| j› d| j› �}|| }|S )Nú<Ú.ú	(service=z%s)>z,host=z,port=)r   Útyper   r   Úservice_nameÚhostÚport)r   ÚpoolÚsÚ	host_infor   r   r   Ú__repr__   s   ÿÿz"SentinelManagedConnection.__repr__c                 C   s"   |\| _ | _| j| jjdd� 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              	   C   s\   | j rd S | jjr|  | j ¡ ¡ d S | j ¡ D ]}z|  |¡W   S  ty+   Y qw t‚©N)Ú_sockr   Ú	is_masterr/   Úget_master_addressÚrotate_slavesr   r   )r   Úslaver   r   r   Ú_connect_retry0   s   ÿz(SentinelManagedConnection._connect_retryc                 C   s   | j  | jdd„ ¡S )Nc                 S   s   d S r0   r   )Úerrorr   r   r   Ú<lambda>>   s    z3SentinelManagedConnection.connect.<locals>.<lambda>)ÚretryÚcall_with_retryr6   ©r   r   r   r   Úconnect=   s   z!SentinelManagedConnection.connectF)Údisconnect_on_errorÚpush_requestr=   r>   c                   s>   z
t ƒ j|||d�W S  ty   | jjr|  ¡  tdƒ‚‚ w )N)Údisable_decodingr=   r>   z"The previous master is now a slave)r   Úread_responser	   r   r2   Ú
disconnectr   )r   r?   r=   r>   r   r   r   r@   @   s   ý÷z'SentinelManagedConnection.read_response)F)r   r   r   r   r)   r/   r6   r<   r   Úboolr@   Ú__classcell__r   r   r   r   r      s    þûüûr   c                   @   r   )ÚSentinelManagedSSLConnectionNr   r   r   r   r   rD   Y   r   rD   c                   @   s,   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	S )
ÚSentinelConnectionPoolProxyc                 C   s0   t  |¡| _|| _|| _|| _|| _|  ¡  d S r0   )ÚweakrefÚrefÚconnection_pool_refr2   r-   r#   Úsentinel_managerÚreset)r   r   r2   r-   r#   rI   r   r   r   r   ^   s   z$SentinelConnectionPoolProxy.__init__c                 C   s   d | _ d | _d S r0   )Úmaster_addressÚslave_rr_counterr;   r   r   r   rJ   m   s   
z!SentinelConnectionPoolProxy.resetc                 C   sD   | j  | j¡}| jr | j|kr || _|  ¡ }|d ur |jdd� |S )NF)Úinuse_connections)rI   Údiscover_masterr#   r2   rK   rH   rA   )r   rK   r   r   r   r   r3   q   s   z.SentinelConnectionPoolProxy.get_master_addressc                 c   sœ   � | j  | j¡}|r5| jd u rt dt|ƒd ¡| _tt|ƒƒD ]}| jd t|ƒ | _|| j }|V  q z|  ¡ V  W n	 t	yE   Y nw t
d| j›�ƒ‚)Nr   é   zNo slave found for )rI   Údiscover_slavesr#   rL   ÚrandomÚrandintÚlenÚranger3   r   r   )r   ÚslavesÚ_r5   r   r   r   r4   |   s   €

ÿz)SentinelConnectionPoolProxy.rotate_slavesN)r   r   r   r   rJ   r3   r4   r   r   r   r   rE   ]   s
    rE   c                       s\   e Zd ZdZ‡ fdd„Zdd„ Z‡ fdd„Zedd	„ ƒZ‡ fd
d„Z	dd„ Z
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                    s‚   |  d| dd¡rtnt¡|d< | dd¡| _| dd¡| _t| | j| j||d�| _tƒ j	d	i |¤Ž | j| j
d< || _|| _d S )
NÚconnection_classÚsslFr2   Tr-   )r   r2   r-   r#   rI   r   r   )Úgetr   rD   r   r2   r-   rE   Úproxyr   r   Úconnection_kwargsr#   rI   )r   r#   rI   r   r   r   r   r   •   s&   
ÿûû
zSentinelConnectionPool.__init__c              	   C   s:   | j rdnd}dt| ƒj› dt| ƒj› d| j› d|› d�	S )NÚmasterr5   r   r    r!   ú(z))>)r2   r"   r   r   r#   )r   Úroler   r   r   r)   ¬   s   ÿÿÿzSentinelConnectionPool.__repr__c                    s   t ƒ  ¡  | j ¡  d S r0   )r   rJ   r[   r;   r   r   r   rJ   ³   s   
zSentinelConnectionPool.resetc                 C   s   | j jS r0   )r[   rK   r;   r   r   r   rK   ·   s   z%SentinelConnectionPool.master_addressc                    s4   | j  p| j o| j|j|jfk}tƒ }|o| |¡S r0   )r2   rK   r$   r%   r   Úowns_connection)r   Ú
connectionÚcheckÚparentr   r   r   r`   »   s
   ÿz&SentinelConnectionPool.owns_connectionc                 C   ó
   | j  ¡ S r0   )r[   r3   r;   r   r   r   r3   Â   s   
z)SentinelConnectionPool.get_master_addressc                 C   rd   )zRound-robin slave balancer)r[   r4   r;   r   r   r   r4   Å   s   
z$SentinelConnectionPool.rotate_slaves)r   r   r   Ú__doc__r   r)   rJ   ÚpropertyrK   r`   r3   r4   rC   r   r   r   r   rW   �   s    
rW   c                   @   sl   e Zd ZdZ			ddd„Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Z	dd„ Z
eefdd„Zeefdd„ZdS )Ú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.
    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 ||fi ˆ j¤Ž‘qS r   )r   Úsentinel_kwargs)rj   Úhostnamer%   r;   r   r   Ú
<listcomp>÷   s    ÿÿz%Sentinel.__init__.<locals>.<listcomp>)Úitemsrn   Ú	sentinelsÚmin_other_sentinelsr\   Ú_force_master_ip)r   rr   rs   rn   Úforce_master_ipr\   r   r;   r   r   ç   s   
ÿ
þ
zSentinel.__init__c                 O   sˆ   t | dd¡ƒ}t | dd¡ƒ}|r)t | j¡j|i |¤Ž}|r#|gS |r'dS dS g }| jD ]}| |j|i |¤Ž¡ q.|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)rB   r   rQ   Úchoicerr   Úexecute_commandÚappendÚall)r   Úargsr   rv   rw   ÚresponseÚ	responsesÚsentinelr   r   r   ry   ÿ   s   
zSentinel.execute_commandc                 C   sN   g }| j D ]}| d |jj¡¡ qdt| ƒj› dt| ƒj› dd |¡› d�S )Nz{host}:{port}r   r    z(sentinels=[ú,z])>)	rr   rz   Ú
format_mapr   r\   r"   r   r   Újoin)r   Úsentinel_addressesr   r   r   r   r)     s   
ÿÿÿzSentinel.__repr__c                 C   s2   |d r|d s|d rdS |d | j k rdS dS )Nr2   Úis_sdownÚis_odownFznum-other-sentinelsT)rs   )r   Ústater#   r   r   r   Úcheck_master_state&  s
   zSentinel.check_master_statec           
      C   sô   t ƒ }t| jƒD ]X\}}z| ¡ }W n ttfy0 } z| |› d|›�¡ W Y d}~qd}~ww | |¡}|r`|  ||¡r`|| jd | jd< | j|< | j	durT| j	n|d }||d f  S qd}	t
|ƒdkrqd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.
        z - Nr   Úipr%   Ú z : z, zNo master found for )ÚlistÚ	enumeraterr   Úsentinel_mastersr   r   rz   rZ   r‡   rt   rS   r‚   r   )
r   r#   Úcollected_errorsÚsentinel_nor   ÚmastersÚer†   rˆ   Ú
error_infor   r   r   rN   .  s0   €þ
þ
ÿý€zSentinel.discover_masterc                 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%   )rz   )r   rU   Úslaves_aliver5   r   r   r   Úfilter_slavesQ  s   zSentinel.filter_slavesc                 C   sN   | j D ]!}z| |¡}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``)rr   Úsentinel_slavesr   r
   r   r“   )r   r#   r   rU   r   r   r   rP   Z  s   
ÿ
ÿzSentinel.discover_slavesc                 K   ó4   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.
        Tr2   ©Údictr\   ÚupdateÚ	from_pool©r   r#   Úredis_classÚconnection_pool_classr   r\   r   r   r   Ú
master_forf  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.
        Fr2   r–   rš   r   r   r   Ú	slave_forŒ  s   

ÿzSentinel.slave_for)r   NN)r   r   r   re   r   ry   r)   r‡   rN   r“   rP   r   rW   r�   rž   r   r   r   r   rg   Ê   s$    
û#	
ü)ürg   )rQ   rF   Útypingr   Úredis.clientr   Úredis.commandsr   Úredis.connectionr   r   r   Úredis.exceptionsr   r	   r
   r   r   r   r   rD   rE   rW   rg   r   r   r   r   Ú<module>   s    A0=