o
    Š¨Êh=8  ã                   @   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 d dl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ÚTimeoutError)Ústr_if_bytesc                   @   ó   e Zd ZdS )ÚMasterNotFoundErrorN©Ú__name__Ú
__module__Ú__qualname__© r   r   úH/var/www/html/env/lib/python3.10/site-packages/redis/asyncio/sentinel.pyr      ó    r   c                   @   r   )ÚSlaveNotFoundErrorNr   r   r   r   r   r      r   r   c                       sx   e Zd Z‡ fdd„Zdd„ Z‡ f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   sP   | j }d| jj› d| jj› d|j› �}| jr$d| j› d| j› �}||7 }|d S )Nú<Ú.ú	(service=z,host=z,port=z)>)r   r&   r   r   Úservice_nameÚhostÚport)r#   ÚpoolÚsÚ	host_infor   r   r   Ú__repr__   s   ÿÿz"SentinelManagedConnection.__repr__c                 ƒ   s\   �|\| _ | _tƒ  ¡ I d H  | jjr*|  d¡I d H  t|  ¡ I d H ƒdkr,t	dƒ‚d S d S )NÚPINGÚPONGzPING failed)
r+   r,   r!   Úconnectr   Úcheck_connectionÚsend_commandr   Úread_responser   )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_masterr8   Úget_master_addressÚrotate_slavesr   r   )r#   Úslaver   r   r   Ú_connect_retry2   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>B   s   
 z3SentinelManagedConnection.connect.<locals>.<lambda>)ÚretryÚcall_with_retryr?   ©r#   r   r   r   r3   ?   s
   €
þz!SentinelManagedConnection.connectFNT)Údisconnect_on_errorÚpush_requestÚdisable_decodingÚtimeoutrG   rH   c                ƒ   sN   �zt ƒ j||||d�I d H W S  ty&   | jjr%|  ¡ I d H  tdƒ‚‚ w )N)rI   rJ   rG   rH   z"The previous master is now a slave)r!   r6   r   r   r;   Ú
disconnectr   )r#   rI   rJ   rG   rH   r%   r   r   r6   E   s   €ü÷z'SentinelManagedConnection.read_response)FN)r   r   r   r"   r0   r8   r?   r3   Úboolr   Úfloatr6   Ú__classcell__r   r   r%   r   r      s(    ýúþýûúr   c                   @   r   )ÚSentinelManagedSSLConnectionNr   r   r   r   r   rO   `   r   rO   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ÚsslFr;   Tr4   r   r   )Úgetr    rO   r   r;   r4   r!   r"   ÚweakrefÚproxyÚconnection_kwargsr*   Úsentinel_managerÚmaster_addressÚslave_rr_counter)r#   r*   rW   r$   r%   r   r   r"   l   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(   r)   ú(Úmasterr>   z))>)r&   r   r   r*   r;   rF   r   r   r   r0   ~   s   ÿÿÿzSentinelConnectionPool.__repr__c                    s   t ƒ  ¡  d | _d | _d S r9   )r!   ÚresetrX   rY   rF   r%   r   r   r\   „   s   

zSentinelConnectionPool.resetÚ
connectionc                    s0   | j  p| j o| j|j|jfk}|otƒ  |¡S r9   )r;   rX   r+   r,   r!   Úowns_connection)r#   r]   Ú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)rW   Údiscover_masterr*   r;   rX   rK   )r#   rX   r   r   r   r<   �   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 )rW   Údiscover_slavesr*   rY   ÚrandomÚrandintÚlenÚranger<   r   r   )r#   ÚslavesÚ_r>   r   r   r   r=   ™   s   €

ÿz$SentinelConnectionPool.rotate_slaves)r   r   r   Ú__doc__r"   r0   r\   r
   r^   r<   r   r=   rN   r   r   r%   r   rP   d   s    
rP   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                    sD   |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)ro   Úhostnamer,   rF   r   r   Ú
<listcomp>×   s    ÿÿz%Sentinel.__init__.<locals>.<listcomp>)Úitemsrs   Ú	sentinelsÚmin_other_sentinelsrV   )r#   rw   rx   rs   rV   r   rF   r   r"   È   s   	ÿ
þ
zSentinel.__init__c                 �   sx   �t ˆ dd¡ƒ}dˆ ¡ v rˆ d¡ |r't | j¡jˆ i ˆ¤ŽI dH  dS ‡ ‡fdd„| jD ƒ}tj	|Ž I dH  d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.
        ÚonceFNc                    s"   g | ]}t  |jˆ i ˆ¤Ž¡‘qS r   )r@   ÚTaskÚexecute_command)ro   Úsentinel©Úargsr$   r   r   ru   ë   s    ÿÿz,Sentinel.execute_command.<locals>.<listcomp>T)
rL   rS   Úkeysr    re   Úchoicerw   r{   r@   Úgather)r#   r~   r$   ry   Útasksr   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])>)rw   Úappendr   rV   r&   r   Újoin)r#   Úsentinel_addressesr|   r   r   r   r0   ò   s   

ÿÿÿÿzSentinel.__repr__Ústater*   rb   c                 C   s2   |d r|d s|d rdS |d | j k rdS dS )Nr;   Úis_sdownÚis_odownFznum-other-sentinelsT)rx   )r#   rˆ   r*   r   r   r   Úcheck_master_stateþ   s
   zSentinel.check_master_statec           	      Ã   sè   �t ƒ }t| jƒD ]Q\}}z	| ¡ I dH }W n ttfy4 } z| |› d|›�¡ W Y d}~q	d}~ww | |¡}|rZ|  ||¡rZ|| jd | jd< | j|< |d |d f  S q	d}t	|ƒdkrkd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Ú	enumeraterw   Úsentinel_mastersr   r   r…   rS   r‹   rg   r†   r   )	r#   r*   Úcollected_errorsÚsentinel_nor|   ÚmastersÚerˆ   Ú
error_infor   r   r   ra     s*   €€þ
þ€zSentinel.discover_masterri   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#   ri   Úslaves_aliver>   r   r   r   Úfilter_slaves#  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)rw   Úsentinel_slavesr   r   r   r—   )r#   r*   r|   ri   r   r   r   rd   .  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.

        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;   ©ÚdictrV   ÚupdateÚ	from_pool©r#   r*   r™   rš   r$   rV   r   r   r   r   Ú
master_for<  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.
        Fr;   rœ   r    r   r   r   Ú	slave_fora  s
   


zSentinel.slave_for)r   N)r   r   r   rk   r"   r{   r0   r�   ÚstrrL   r‹   ra   r   r   r   r   r   r—   rd   r	   rP   r   r¡   r¢   r   r   r   r   rl   «   sJ    
üÿ
þÿ
þüþý
ü(üþýürl   )!r@   re   rT   Útypingr   r   r   r   r   r   r   Úredis.asyncio.clientr	   Úredis.asyncio.connectionr
   r   r   r   Úredis.commandsr   Úredis.exceptionsr   r   r   r   Úredis.utilsr   r   r   r   rO   rP   rl   r   r   r   r   Ú<module>   s    $FG