o
    rPf_7                     @   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 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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TimeoutError)str_if_bytesc                   @      e Zd ZdS )MasterNotFoundErrorN__name__
__module____qualname__ r   r   O/var/www/html/humari/django-venv/lib/python3.10/site-packages/redis/sentinel.pyr          r   c                   @   r   )SlaveNotFoundErrorNr   r   r   r   r   r      r   r   c                       sj   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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   sD   | j }t| j d|j d}| jr d| j d| j }|| }|S )N	<service=z%s>z,host=z,port=)r   typer   service_namehostport)r   pools	host_infor   r   r   __repr__   s   z"SentinelManagedConnection.__repr__c                    sH   |\| _ | _t   | jjr | d t|  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              	   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_masterr0   get_master_addressrotate_slavesr   r   )r   slaver   r   r   _connect_retry)   s   z(SentinelManagedConnection._connect_retryc                 C   s   | j | jdd S )Nc                 S   s   d S r1   r   )errorr   r   r   <lambda>7   s    z3SentinelManagedConnection.connect.<locals>.<lambda>)retrycall_with_retryr7   r   r   r   r   r+   6   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   r.   r	   r   r3   
disconnectr   )r   r?   r=   r>   r   r   r   r.   9   s   z'SentinelManagedConnection.read_response)F)r   r   r   r   r(   r0   r7   r+   r   boolr.   __classcell__r   r   r   r   r      s    r   c                   @   r   )SentinelManagedSSLConnectionNr   r   r   r   r   rC   R   r   rC   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 r1   )weakrefrefconnection_pool_refr3   r,   r"   sentinel_managerreset)r   r   r3   r,   r"   rH   r   r   r   r   W   s   z$SentinelConnectionPoolProxy.__init__c                 C   s   d | _ d | _d S r1   )master_addressslave_rr_counterr<   r   r   r   rI   f   s   
z!SentinelConnectionPoolProxy.resetc                 C   sD   | j | j}| jr | j|kr || _|  }|d ur |jdd |S )NF)inuse_connections)rH   discover_masterr"   r3   rJ   rG   r@   )r   rJ   r   r   r   r   r4   j   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 )rH   discover_slavesr"   rK   randomrandintlenranger4   r   r   )r   slaves_r6   r   r   r   r5   u   s   

z)SentinelConnectionPoolProxy.rotate_slavesN)r   r   r   r   rI   r4   r5   r   r   r   r   rD   V   s
    rD   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sslFr3   Tr,   )r   r3   r,   r"   rH   r   r   )getr   rC   r   r3   r,   rD   proxyr   r   connection_kwargsr"   rH   )r   r"   rH   r   r   r   r   r      s&   

zSentinelConnectionPool.__init__c                 C   s,   | j rdnd}t| j d| j d| dS )Nmasterr6   r    ())r3   r!   r   r"   )r   roler   r   r   r(      s   zSentinelConnectionPool.__repr__c                    s   t    | j  d S r1   )r   rI   rZ   r<   r   r   r   rI      s   
zSentinelConnectionPool.resetc                 C   s   | j jS r1   )rZ   rJ   r<   r   r   r   rJ      s   z%SentinelConnectionPool.master_addressc                    s4   | j  p| j o| j|j|jfk}t }|o||S r1   )r3   rJ   r#   r$   r   owns_connection)r   
connectioncheckparentr   r   r   r`      s
   z&SentinelConnectionPool.owns_connectionc                 C   
   | j  S r1   )rZ   r4   r<   r   r   r   r4      s   
z)SentinelConnectionPool.get_master_addressc                 C   rd   )zRound-robin slave balancer)rZ   r5   r<   r   r   r   r5      s   
z$SentinelConnectionPool.rotate_slaves)r   r   r   __doc__r   r(   rI   propertyrJ   r`   r4   r5   rB   r   r   r   r   rV      s    
rV   c                   @   sj   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                    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 ||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[   )r   rr   rs   rn   r[   r   r<   r   r      s   	

zSentinel.__init__c                 O   sf   t |dd}d| v r|d |r#t| jj|i | dS | jD ]
}|j|i | q&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.
        onceFT)rA   rY   keysr   rP   choicerr   execute_command)r   argsr   rt   sentinelr   r   r   rw      s   

zSentinel.execute_commandc                 C   s@   g }| j D ]}|d|jj qt| j dd| dS )Nz{host}:{port}z<sentinels=[,z]>)rr   append
format_mapr   r[   r!   r   join)r   sentinel_addressesry   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 )Nr3   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 ]N\}}z| }W n ttfy0 } z|| d| W Y d}~qd}~ww ||}|rV| ||rV|| jd | jd< | j|< |d |d f  S qd}t	|dkrgd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   r{   rY   r   rR   r}   r   )	r   r"   collected_errorssentinel_nory   masterser   
error_infor   r   r   rM     s(   
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$   )r{   )r   rT   slaves_aliver6   r   r   r   filter_slaves/  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"   ry   rT   r   r   r   rO   8  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.

        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.
        Tr3   dictr[   update	from_poolr   r"   redis_classconnection_pool_classr   r[   r   r   r   
master_forD  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.
        Fr3   r   r   r   r   r   	slave_forh  s   

zSentinel.slave_for)r   N)r   r   r   re   r   rw   r(   r   rM   r   rO   r   rV   r   r   r   r   r   r   rg      s"    
	
'rg   )rP   rE   typingr   redis.clientr   redis.commandsr   redis.connectionr   r   r   redis.exceptionsr   r	   r
   r   redis.utilsr   r   r   r   rC   rD   rV   rg   r   r   r   r   <module>   s    >08