o
    ×èFh�7  ã                	   @   s8  d Z ddlZddl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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 dd
lmZ ddlmZ ddlmZ ddlm Z m!Z!m"Z" G dd„ dej#e	ƒZ$G dd„ deƒZ%de!de%fdd„Z&de'de(defdd„Z)eefde*de*de*de*fdd„Z+dS )zEHelpers for applying Google Cloud Firestore changes in a transaction.é    N)Úgapic_v1)Úretry)Ú_BaseTransactionalÚBaseTransactionÚMAX_ATTEMPTSÚ_CANT_BEGINÚ_CANT_ROLLBACKÚ_CANT_COMMITÚ_WRITE_READ_ONLYÚ_INITIAL_SLEEPÚ
_MAX_SLEEPÚ_MULTIPLIERÚ_EXCEED_ATTEMPTS_TEMPLATE)Ú
exceptions)Úbatch)ÚDocumentReference)Ú_helpers)ÚQuery)ÚDocumentSnapshot)ÚCommitResponse)ÚAnyÚCallableÚ	Generatorc                       sÆ   e Zd ZdZedfd‡ fdd„Zdeddf‡ fdd	„Zdd
eddfdd„Z	ddd„Z
defdd„Zejjdfdedejdedeeedf fdd„Zejjdfdejdedeeedf fdd„Z‡  ZS )ÚTransactionaD  Accumulate read-and-write operations to be sent in a transaction.

    Args:
        client (:class:`~google.cloud.firestore_v1.client.Client`):
            The client that created this transaction.
        max_attempts (Optional[int]): The maximum number of attempts for
            the transaction (i.e. allowing retries). Defaults to
            :attr:`~google.cloud.firestore_v1.transaction.MAX_ATTEMPTS`.
        read_only (Optional[bool]): Flag indicating if the transaction
            should be read-only or should allow writes. Defaults to
            :data:`False`.
    FÚreturnNc                    s"   t t| ƒ |¡ t | ||¡ d S ©N)Úsuperr   Ú__init__r   )ÚselfÚclientÚmax_attemptsÚ	read_only©Ú	__class__© ú^/var/www/html/loop/nvenv/lib/python3.10/site-packages/google/cloud/firestore_v1/transaction.pyr   @   s   zTransaction.__init__Ú	write_pbsc                    s"   | j rttƒ‚tt| ƒ |¡ dS )a  Add `Write`` protobufs to this transaction.

        Args:
            write_pbs (List[google.cloud.proto.firestore.v1.                write.Write]): A list of write protobufs to be added.

        Raises:
            ValueError: If this transaction is read-only.
        N)Ú
_read_onlyÚ
ValueErrorr
   r   r   Ú_add_write_pbs)r   r&   r"   r$   r%   r)   D   s   
zTransaction._add_write_pbsÚretry_idc                 C   sL   | j rt | j¡}t|ƒ‚| jjj| jj|  	|¡dœ| jj
d�}|j| _dS )zìBegin the transaction.

        Args:
            retry_id (Optional[bytes]): Transaction ID of a transaction to be
                retried.

        Raises:
            ValueError: If the current transaction has already begun.
        )ÚdatabaseÚoptions©ÚrequestÚmetadataN)Úin_progressr   ÚformatÚ_idr(   Ú_clientÚ_firestore_apiÚbegin_transactionÚ_database_stringÚ_options_protobufÚ_rpc_metadataÚtransaction)r   r*   ÚmsgÚtransaction_responser$   r$   r%   Ú_beginS   s   
þûzTransaction._beginc                 C   sJ   | j sttƒ‚z| jjj| jj| jdœ| jjd� W |  	¡  dS |  	¡  w )zÀRoll back the transaction.

        Raises:
            ValueError: If no transaction is in progress.
            google.api_core.exceptions.GoogleAPICallError: If the rollback fails.
        )r+   r9   r-   N)
r0   r(   r   r3   r4   Úrollbackr6   r2   r8   Ú	_clean_up)r   r$   r$   r%   Ú	_rollbackj   s   þû	zTransaction._rollbackc                 C   s2   | j sttƒ‚t| j| j| jƒ}|  ¡  t|j	ƒS )aÄ  Transactionally commit the changes accumulated.

        Returns:
            List[:class:`google.cloud.proto.firestore.v1.write.WriteResult`, ...]:
            The write results corresponding to the changes committed, returned
            in the same order as the changes were applied to this transaction.
            A write result contains an ``update_time`` field.

        Raises:
            ValueError: If no transaction is in progress.
        )
r0   r(   r	   Ú_commit_with_retryr3   Ú
_write_pbsr2   r>   ÚlistÚwrite_results)r   Úcommit_responser$   r$   r%   Ú_commit�   s
   
zTransaction._commitÚ
referencesr   Útimeoutc                 C   s$   t  ||¡}| jj|fd| i|¤ŽS )ao  Retrieves multiple documents from Firestore.

        Args:
            references (List[.DocumentReference, ...]): Iterable of document
                references to be retrieved.
            retry (google.api_core.retry.Retry): Designation of what errors, if any,
                should be retried.  Defaults to a system-specified policy.
            timeout (float): The timeout for this request.  Defaults to a
                system-specified value.

        Yields:
            .DocumentSnapshot: The next document snapshot that fulfills the
            query, or :data:`None` if the document does not exist.
        r9   )r   Úmake_retry_timeout_kwargsr3   Úget_all)r   rF   r   rG   Úkwargsr$   r$   r%   rI   •   s   zTransaction.get_allc                 C   sV   t  ||¡}t|tƒr| jj|gfd| i|¤ŽS t|tƒr'|jdd| i|¤ŽS tdƒ‚)aO  Retrieve a document or a query result from the database.

        Args:
            ref_or_query: The document references or query object to return.
            retry (google.api_core.retry.Retry): Designation of what errors, if any,
                should be retried.  Defaults to a system-specified policy.
            timeout (float): The timeout for this request.  Defaults to a
                system-specified value.

        Yields:
            .DocumentSnapshot: The next document snapshot that fulfills the
            query, or :data:`None` if the document does not exist.
        r9   zIValue for argument "ref_or_query" must be a DocumentReference or a Query.Nr$   )	r   rH   Ú
isinstancer   r3   rI   r   Ústreamr(   )r   Úref_or_queryr   rG   rJ   r$   r$   r%   Úget¬   s   

ÿzTransaction.get©r   Nr   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   rB   r)   Úbytesr<   r?   rE   r   ÚmethodÚDEFAULTÚretriesÚRetryÚfloatr   r   r   rI   rN   Ú__classcell__r$   r$   r"   r%   r   2   s6    
üþýü
ûüýüûr   c                       sB   e Zd ZdZd‡ fdd„Zdedefdd„Zdefd	d
„Z‡  Z	S )Ú_TransactionalaY  Provide a callable object to use as a transactional decorater.

    This is surfaced via
    :func:`~google.cloud.firestore_v1.transaction.transactional`.

    Args:
        to_wrap (Callable[[:class:`~google.cloud.firestore_v1.transaction.Transaction`, ...], Any]):
            A callable that should be run (and retried) in a transaction.
    r   Nc                    s   t t| ƒ |¡ d S r   )r   r[   r   )r   Úto_wrapr"   r$   r%   r   Õ   s   z_Transactional.__init__r9   c                 O   sH   |  ¡  |j| jd� |j| _| jdu r| j| _| j|g|¢R i |¤ŽS )am  Begin transaction and call the wrapped callable.

        Args:
            transaction
                (:class:`~google.cloud.firestore_v1.transaction.Transaction`):
                A transaction to execute the callable within.
            args (Tuple[Any, ...]): The extra positional arguments to pass
                along to the wrapped callable.
            kwargs (Dict[str, Any]): The extra keyword arguments to pass
                along to the wrapped callable.

        Returns:
            Any: result of the wrapped callable.

        Raises:
            Exception: Any failure caused by ``to_wrap``.
        )r*   N)r>   r<   r*   r2   Ú
current_idr\   )r   r9   ÚargsrJ   r$   r$   r%   Ú_pre_commitØ   s   
z_Transactional._pre_commitc           
      O   s°   |   ¡  |js
tjnd}d}z=t|jƒD ],}| j|g|¢R i |¤Ž}z
| ¡  |W   W S  |y@ } z|}W Y d}~qd}~ww t 	|j¡}	t
|	ƒ|‚ tyW   | ¡  ‚ w )aš  Execute the wrapped callable within a transaction.

        Args:
            transaction
                (:class:`~google.cloud.firestore_v1.transaction.Transaction`):
                A transaction to execute the callable within.
            args (Tuple[Any, ...]): The extra positional arguments to pass
                along to the wrapped callable.
            kwargs (Dict[str, Any]): The extra keyword arguments to pass
                along to the wrapped callable.

        Returns:
            Any: The result of the wrapped callable.

        Raises:
            ValueError: If the transaction does not succeed in
                ``max_attempts``.
        r$   N)Ú_resetr'   r   ÚAbortedÚrangeÚ_max_attemptsr_   rE   r   r1   r(   ÚBaseExceptionr?   )
r   r9   r^   rJ   Úretryable_exceptionsÚlast_excÚattemptÚresultÚexcr:   r$   r$   r%   Ú__call__ô   s(   ÿ€ÿ

üz_Transactional.__call__rO   )
rP   rQ   rR   rS   r   r   r   r_   rj   rZ   r$   r$   r"   r%   r[   Ê   s
    
r[   r\   r   c                 C   s   t | ƒS )a‡  Decorate a callable so that it runs in a transaction.

    Args:
        to_wrap
            (Callable[[:class:`~google.cloud.firestore_v1.transaction.Transaction`, ...], Any]):
            A callable that should be run (and retried) in a transaction.

    Returns:
        Callable[[:class:`~google.cloud.firestore_v1.transaction.Transaction`, ...], Any]:
        the wrapped callable.
    )r[   )r\   r$   r$   r%   Útransactional&  s   rk   r&   Útransaction_idc                 C   sD   t }	 z| jj| j||dœ| jd�W S  tjy   Y nw t|ƒ}q)a.  Call ``Commit`` on the GAPIC client with retry / sleep.

    Retries the ``Commit`` RPC on Unavailable. Usually this RPC-level
    retry is handled by the underlying GAPICd client, but in this case it
    doesn't because ``Commit`` is not always idempotent. But here we know it
    is "idempotent"-like because it has a transaction ID. We also need to do
    our own retry to special-case the ``INVALID_ARGUMENT`` error.

    Args:
        client (:class:`~google.cloud.firestore_v1.client.Client`):
            A client with GAPIC client and configuration details.
        write_pbs (List[:class:`google.cloud.proto.firestore.v1.write.Write`, ...]):
            A ``Write`` protobuf instance to be committed.
        transaction_id (bytes):
            ID of an existing transaction that this commit will run in.

    Returns:
        :class:`google.cloud.firestore_v1.types.CommitResponse`:
        The protobuf response from ``Commit``.

    Raises:
        ~google.api_core.exceptions.GoogleAPICallError: If a non-retryable
            exception is encountered.
    T)r+   Úwritesr9   r-   )r   r4   Úcommitr6   r8   r   ÚServiceUnavailableÚ_sleep)r   r&   rl   Úcurrent_sleepr$   r$   r%   r@   5  s   ýúþòr@   rq   Ú	max_sleepÚ
multiplierc                 C   s$   t  d| ¡}t |¡ t||  |ƒS )aÌ  Sleep and produce a new sleep time.

    .. _Exponential Backoff And Jitter: https://www.awsarchitectureblog.com/                                        2015/03/backoff.html

    Select a duration between zero and ``current_sleep``. It might seem
    counterintuitive to have so much jitter, but
    `Exponential Backoff And Jitter`_ argues that "full jitter" is
    the best strategy.

    Args:
        current_sleep (float): The current "max" for sleep interval.
        max_sleep (Optional[float]): Eventual "max" sleep time
        multiplier (Optional[float]): Multiplier for exponential backoff.

    Returns:
        float: Newly doubled ``current_sleep`` or ``max_sleep`` (whichever
        is smaller)
    g        )ÚrandomÚuniformÚtimeÚsleepÚmin)rq   rr   rs   Úactual_sleepr$   r$   r%   rp   b  s   
rp   ),rS   rt   rv   Úgoogle.api_corer   r   rW   Ú*google.cloud.firestore_v1.base_transactionr   r   r   r   r   r	   r
   r   r   r   r   r   Úgoogle.cloud.firestore_v1r   Ú"google.cloud.firestore_v1.documentr   r   Úgoogle.cloud.firestore_v1.queryr   Ú'google.cloud.firestore_v1.base_documentr   Úgoogle.cloud.firestore_v1.typesr   Útypingr   r   r   Ú
WriteBatchr   r[   rk   rB   rT   r@   rY   rp   r$   r$   r$   r%   Ú<module>   sF   4 \ÿÿ
þ.ÿÿÿÿþ