o
    <‘ðif0  ã                   @   sB  d dl mZ d dlmZ d dlmZ d dlmZmZmZm	Z	m
Z
mZ d dlmZ d dlmZ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mZmZmZmZ d d
l m!Z! d dl"m#Z# d dl$m%Z% d dl&m'Z'm(Z( d dl)m*Z+ d dl,m-Z-m.Z. d dl/m0Z0 d dl1m2Z2 d dl3m4Z4 G dd„ de.ƒZ5G dd„ de-e5ƒZ6dS )é    )Úabstractmethod)Úiscoroutinefunction)Údatetime)ÚAnyÚ	AwaitableÚCallableÚListÚOptionalÚUnion)ÚRedisCluster)ÚPipelineÚPubSub)ÚAsyncDatabaseÚDatabaseÚ	Databases)ÚAsyncActiveDatabaseChangedÚ&CloseConnectionOnActiveDatabaseChangedÚRegisterCommandFailureÚ"ResubscribeOnActiveDatabaseChanged)ÚDEFAULT_FAILOVER_ATTEMPTSÚDEFAULT_FAILOVER_DELAYÚAsyncFailoverStrategyÚDefaultFailoverStrategyExecutorÚFailoverStrategyExecutor)ÚAsyncFailureDetector)Úrecord_geo_failover)ÚRetry)ÚAsyncOnCommandsFailEventÚEventDispatcherInterface)ÚState)ÚBaseCommandExecutorÚCommandExecutor)ÚDEFAULT_AUTO_FALLBACK_INTERVAL)ÚGeoFailoverReason)ÚKeyTc                   @   sV  e Zd Zeedefdd„ƒƒZeedee fdd„ƒƒZ	ededdfdd	„ƒZ
eedee fd
d„ƒƒZedededdfdd„ƒZeedee fdd„ƒƒZejededdfdd„ƒƒZeedefdd„ƒƒZeedefdd„ƒƒZedd„ ƒZedd„ ƒZedefdd„ƒZedeegdf fd d!„ƒZed"efd#d$„ƒZed%e de!fd&d'„ƒZ"dS )(ÚAsyncCommandExecutorÚreturnc                 C   ó   dS )zReturns a list of databases.N© ©Úselfr(   r(   úe/root/parts/websockify/install/lib/python3.10/site-packages/redis/asyncio/multidb/command_executor.pyÚ	databases"   ó   zAsyncCommandExecutor.databasesc                 C   r'   )z$Returns a list of failure detectors.Nr(   r)   r(   r(   r+   Úfailure_detectors(   r-   z&AsyncCommandExecutor.failure_detectorsÚfailure_detectorNc                 C   r'   )z=Adds a new failure detector to the list of failure detectors.Nr(   ©r*   r/   r(   r(   r+   Úadd_failure_detector.   s   z)AsyncCommandExecutor.add_failure_detectorc                 C   r'   )z"Returns currently active database.Nr(   r)   r(   r(   r+   Úactive_database3   r-   z$AsyncCommandExecutor.active_databaseÚdatabaseÚreasonc                 Ã   ó   �dS )z›Sets the currently active database.

        Args:
            database: The new active database.
            reason: The reason for the failover.
        Nr(   )r*   r3   r4   r(   r(   r+   Úset_active_database9   s   €
z(AsyncCommandExecutor.set_active_databasec                 C   r'   )z Returns currently active pubsub.Nr(   r)   r(   r(   r+   Úactive_pubsubE   r-   z"AsyncCommandExecutor.active_pubsubÚpubsubc                 C   r'   )zSets currently active pubsub.Nr(   ©r*   r8   r(   r(   r+   r7   K   r-   c                 C   r'   )z#Returns failover strategy executor.Nr(   r)   r(   r(   r+   Úfailover_strategy_executorQ   r-   z/AsyncCommandExecutor.failover_strategy_executorc                 C   r'   )zReturns command retry object.Nr(   r)   r(   r(   r+   Úcommand_retryW   r-   z"AsyncCommandExecutor.command_retryc                 Ë   r5   )z:Initializes a PubSub object on a currently active databaseNr(   ©r*   Úkwargsr(   r(   r+   r8   ]   ó   €zAsyncCommandExecutor.pubsubc                 Ï   r5   )z*Executes a command and returns the result.Nr(   )r*   ÚargsÚoptionsr(   r(   r+   Úexecute_commandb   r>   z$AsyncCommandExecutor.execute_commandÚcommand_stackc                 Ã   r5   )z)Executes a stack of commands in pipeline.Nr(   )r*   rB   r(   r(   r+   Úexecute_pipelineg   r>   z%AsyncCommandExecutor.execute_pipelineÚtransactionc                 Ï   r5   )z1Executes a transaction block wrapped in callback.Nr(   )r*   rD   Úwatchesr@   r(   r(   r+   Úexecute_transactionl   s   €z(AsyncCommandExecutor.execute_transactionÚmethod_namec                 Ï   r5   )z*Executes a given method on active pub/sub.Nr(   )r*   rG   r?   r=   r(   r(   r+   Úexecute_pubsub_methods   r>   z*AsyncCommandExecutor.execute_pubsub_methodÚ
sleep_timec                 Ë   r5   )z!Executes pub/sub run in a thread.Nr(   )r*   rI   r=   r(   r(   r+   Úexecute_pubsub_runx   r>   z'AsyncCommandExecutor.execute_pubsub_run)#Ú__name__Ú
__module__Ú__qualname__Úpropertyr   r   r,   r   r   r.   r1   r	   r   r2   r#   r6   r   r7   Úsetterr   r:   r   r;   r8   rA   ÚtuplerC   r   r   rF   ÚstrrH   Úfloatr   rJ   r(   r(   r(   r+   r%   !   s\    ÿÿþ

ÿr%   c                       sÆ  e Zd Zeeefdee dede	de
dedededef‡ fd	d
„Zedefdd„ƒZedee fdd„ƒZdeddfdd„Zedee fdd„ƒZdededdfdd„Zedee fdd„ƒZejdeddfdd„ƒZedefdd„ƒZede	fd d!„ƒZd"d#„ Zd$d%„ Zd&e fd'd(„Z!dd)dd*œd+e"d,ge#e$e%e$ f f d-e&d.ee' d/e(d0ee f
d1d2„Z)d3e'fd4d5„Z*	dGd6ede$fd7d8„Z+	9dHd:e"d;e fd<d=„Z,d>d?„ Z-d@dA„ Z.dBe fdCdD„Z/dEdF„ Z0‡  Z1S )IÚDefaultCommandExecutorr.   r,   r;   Úfailover_strategyÚevent_dispatcherÚfailover_attemptsÚfailover_delayÚauto_fallback_intervalc	           
         sn   t ƒ  |¡ |D ]}	|	j| d� q|| _|| _|| _t|||ƒ| _|| _d| _	d| _
i | _|  ¡  |  ¡  dS )a°  
        Initialize the DefaultCommandExecutor instance.

        Args:
            failure_detectors: List of failure detector instances to monitor database health
            databases: Collection of available databases to execute commands on
            command_retry: Retry policy for failed command execution
            failover_strategy: Strategy for handling database failover
            event_dispatcher: Interface for dispatching events
            failover_attempts: Number of failover attempts
            failover_delay: Delay between failover attempts
            auto_fallback_interval: Time interval in seconds between attempts to fall back to a primary database
        )Úcommand_executorN)ÚsuperÚ__init__Úset_command_executorÚ
_databasesÚ_failure_detectorsÚ_command_retryr   Ú_failover_strategy_executorÚ_event_dispatcherÚ_active_databaseÚ_active_pubsubÚ_active_pubsub_kwargsÚ_setup_event_dispatcherÚ_schedule_next_fallback)
r*   r.   r,   r;   rT   rU   rV   rW   rX   Úfd©Ú	__class__r(   r+   r[      s   ÿzDefaultCommandExecutor.__init__r&   c                 C   ó   | j S ©N)r]   r)   r(   r(   r+   r,   ©   ó   z DefaultCommandExecutor.databasesc                 C   rj   rk   )r^   r)   r(   r(   r+   r.   ­   rl   z(DefaultCommandExecutor.failure_detectorsr/   Nc                 C   s   | j  |¡ d S rk   )r^   Úappendr0   r(   r(   r+   r1   ±   s   z+DefaultCommandExecutor.add_failure_detectorc                 C   rj   rk   )rb   r)   r(   r(   r+   r2   ´   rl   z&DefaultCommandExecutor.active_databaser3   r4   c                 Ã   sd   �| j }|| _ |d ur.||ur0t|||d�I d H  | j t|| j | fi | j¤Ž¡I d H  d S d S d S )N)Ú	fail_fromÚfail_tor4   )rb   r   ra   Údispatch_asyncr   rd   )r*   r3   r4   Ú
old_activer(   r(   r+   r6   ¸   s&   €ýýüÿúz*DefaultCommandExecutor.set_active_databasec                 C   rj   rk   ©rc   r)   r(   r(   r+   r7   Í   rl   z$DefaultCommandExecutor.active_pubsubr8   c                 C   s
   || _ d S rk   rr   r9   r(   r(   r+   r7   Ñ   s   
c                 C   rj   rk   )r`   r)   r(   r(   r+   r:   Õ   rl   z1DefaultCommandExecutor.failover_strategy_executorc                 C   rj   rk   )r_   r)   r(   r(   r+   r;   Ù   rl   z$DefaultCommandExecutor.command_retryc                 K   sD   | j d u r t| jjtƒrtdƒ‚| jjjdi |¤Ž| _ || _d S d S )Nz(PubSub is not supported for RedisClusterr(   )rc   Ú
isinstancerb   Úclientr   Ú
ValueErrorr8   rd   r<   r(   r(   r+   r8   Ý   s   

ûzDefaultCommandExecutor.pubsubc                 �   s$   �‡ ‡‡fdd„}ˆ  |ˆ ¡I d H S )Nc                  “   s0   �ˆj jjˆ i ˆ¤ŽI d H } ˆ ˆ ¡I d H  | S rk   )rb   rt   rA   Ú_register_command_execution©Úresponse©r?   r@   r*   r(   r+   Úcallbackæ   s   €ÿÿz8DefaultCommandExecutor.execute_command.<locals>.callback©Ú_execute_with_failure_detection)r*   r?   r@   rz   r(   ry   r+   rA   å   s   €z&DefaultCommandExecutor.execute_commandrB   c                 ƒ   s"   �‡ ‡fdd„}ˆ  |ˆ ¡I d H S )Nc               	   “   s†   �ˆj j ¡ 4 I d H š+} ˆ D ]\}}| j|i |¤Ž q|  ¡ I d H }ˆ ˆ ¡I d H  |W  d   ƒI d H  S 1 I d H s<w   Y  d S rk   )rb   rt   ÚpipelinerA   Úexecuterv   )ÚpipeÚcommandr@   rx   ©rB   r*   r(   r+   rz   ð   s   €0úz9DefaultCommandExecutor.execute_pipeline.<locals>.callbackr{   )r*   rB   rz   r(   r�   r+   rC   ï   s   €	z'DefaultCommandExecutor.execute_pipelineF©Ú
shard_hintÚvalue_from_callableÚwatch_delayÚfuncr   rE   rƒ   r„   r…   c                ‡   s(   �‡ ‡‡‡‡‡fdd„}ˆ  |¡I d H S )Nc                  “   s<   �ˆj jjˆ gˆ¢R ˆˆˆdœŽI d H } ˆ d¡I d H  | S )Nr‚   r(   )rb   rt   rD   rv   rw   ©r†   r*   rƒ   r„   r…   rE   r(   r+   rz     s   €ÿþûz<DefaultCommandExecutor.execute_transaction.<locals>.callbackr{   )r*   r†   rƒ   r„   r…   rE   rz   r(   r‡   r+   rF   û   s   €z*DefaultCommandExecutor.execute_transactionrG   c                 �   s,   �‡ ‡‡‡fdd„}ˆj |gˆ ¢R Ž I d H S )Nc                  “   sN   �t ˆjˆƒ} t| ƒr| ˆ i ˆ¤ŽI d H }n| ˆ i ˆ¤Ž}ˆ ˆ ¡I d H  |S rk   )Úgetattrr7   r   rv   )Úmethodrx   ©r?   r=   rG   r*   r(   r+   rz     s   €z>DefaultCommandExecutor.execute_pubsub_method.<locals>.callbackr{   )r*   rG   r?   r=   rz   r(   rŠ   r+   rH     s   €
z,DefaultCommandExecutor.execute_pubsub_methodrI   c                 ƒ   s$   �‡ ‡‡‡fdd„}ˆ  |¡I d H S )Nc                   “   s   �ˆj jˆˆ ˆd�I d H S )N)Úpoll_timeoutÚexception_handlerr8   )rc   Úrunr(   ©rŒ   r8   r*   rI   r(   r+   rz      s   €ýz;DefaultCommandExecutor.execute_pubsub_run.<locals>.callbackr{   )r*   rI   rŒ   r8   rz   r(   rŽ   r+   rJ     s   €z)DefaultCommandExecutor.execute_pubsub_runr(   rz   Úcmdsc                 ƒ   s6   �‡ ‡fdd„‰ˆj  ‡fdd„‡‡fdd„¡I dH S )zO
        Execute a commands execution callback with failure detection.
        c                   “   s   �ˆ  ¡ I d H  ˆ ƒ I d H S rk   )Ú_check_active_databaser(   )rz   r*   r(   r+   Úwrapper0  s   €zGDefaultCommandExecutor._execute_with_failure_detection.<locals>.wrapperc                      s   ˆ ƒ S rk   r(   r(   )r‘   r(   r+   Ú<lambda>6  s    zHDefaultCommandExecutor._execute_with_failure_detection.<locals>.<lambda>c                    s   ˆj | gˆ ¢R Ž S rk   )Ú_on_command_fail)Úerror)r�   r*   r(   r+   r’   7  s    N)r_   Úcall_with_retry)r*   rz   r�   r(   )rz   r�   r*   r‘   r+   r|   )  s   €

þz6DefaultCommandExecutor._execute_with_failure_detectionc                 Ã   sh   �| j du s| j jjtjks| jdkr0| jt ¡ kr2|  	| j
 ¡ I dH tj¡I dH  |  ¡  dS dS dS )zB
        Checks if active a database needs to be updated.
        Nr   )rb   ÚcircuitÚstateÚCBStateÚCLOSEDÚ_auto_fallback_intervalÚ_next_fallback_attemptr   Únowr6   r`   r~   r#   Ú	AUTOMATICrf   r)   r(   r(   r+   r�   :  s   €


þøz-DefaultCommandExecutor._check_active_databasec                 Ç   s   �| j  t||ƒ¡I d H  d S rk   )ra   rp   r   )r*   r”   r?   r(   r(   r+   r“   L  s   €ÿz'DefaultCommandExecutor._on_command_failÚcmdc                 Ã   s"   �| j D ]
}| |¡I d H  qd S rk   )r^   Úregister_command_execution)r*   rž   Údetectorr(   r(   r+   rv   Q  s   €
ÿz2DefaultCommandExecutor._register_command_executionc                 C   s4   t | jƒ}tƒ }tƒ }| j t|gt||gi¡ dS )z0
        Registers necessary listeners.
        N)r   r^   r   r   ra   Úregister_listenersr   r   )r*   Úfailure_listenerÚresubscribe_listenerÚclose_connection_listenerr(   r(   r+   re   U  s   
þþÿz.DefaultCommandExecutor._setup_event_dispatcher)NN)r(   )2rK   rL   rM   r   r   r"   r   r   r   r   r   r   ÚintrR   r[   rN   r,   r.   r1   r	   r   r2   r#   r6   r   r7   rO   r   r:   r;   r8   rA   rP   rC   r   r
   r   r   r$   rQ   ÚboolrF   rH   rJ   r|   r�   r“   rv   re   Ú__classcell__r(   r(   rh   r+   rS   ~   sš    ÷þýüûúùø	÷*ÿÿ
þ
úþýüû
úÿÿ
þÿÿ
ÿrS   N)7Úabcr   Úasyncior   r   Útypingr   r   r   r   r	   r
   Úredis.asyncior   Úredis.asyncio.clientr   r   Úredis.asyncio.multidb.databaser   r   r   Úredis.asyncio.multidb.eventr   r   r   r   Úredis.asyncio.multidb.failoverr   r   r   r   r   Ú&redis.asyncio.multidb.failure_detectorr   Ú$redis.asyncio.observability.recorderr   Úredis.asyncio.retryr   Úredis.eventr   r   Úredis.multidb.circuitr   r˜   Úredis.multidb.command_executorr    r!   Úredis.multidb.configr"   Úredis.observability.attributesr#   Úredis.typingr$   r%   rS   r(   r(   r(   r+   Ú<module>   s(     ]