U
    d                     @   s   d 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	 ddl
mZmZmZmZ dd	lmZmZ d
ZG dd deZdddZG dd dejZG dd deZG dd deZdS )zModel managers.    Nwraps)count)maybe_timedelta)settings)connectionsmodelsroutertransaction   )now
raw_deletez
Polling results with transaction isolation level 'repeatable-read'
within the same transaction may give outdated results.

Be sure to commit the transaction for each poll iteration.
c                   @   s   e Zd ZdZdS )TxIsolationWarningzAWarning emitted if the transaction isolation level is suboptimal.N)__name__
__module____qualname____doc__ r   r   B/tmp/pip-unpacked-wheel-oj8imec1/django_celery_results/managers.pyr      s   r   c                    s    fdd}|S )a	  Decorate a function to retry database operations.

    For functions doing database operations, adding
    retrying if the operation fails.

    Keyword Arguments:
    -----------------
        max_retries (int): Maximum number of retries.  Default one retry.

    c                    s   t   fdd}|S )Nc               	      sN   | d}tdD ]4}z | |W   S  tk
rF   ||krB Y qX qd S )NZexception_retry_countr   )popr   	Exception)argskwargsZ_max_retriesretries)funmax_retriesr   r   _inner&   s    z1transaction_retry.<locals>._outer.<locals>._innerr   )r   r   r   )r   r   _outer$   s    z!transaction_retry.<locals>._outerr   )r   r   r   r   r   transaction_retry   s    r   c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )ResultManagerz#Generic manager for celery results.c                 C   sP   d|    krL|   }|drL| d }|dkrLttt	
  d S )NZmysqlzPSHOW VARIABLES WHERE variable_name IN ('tx_isolation', 'transaction_isolation');r   zREPEATABLE-READ)current_enginelowerconnection_for_readcursorexecuteZfetchonewarningswarnr   W_ISOLATION_REPstrip)selfr$   Z	isolationr   r   r   warn_if_repeatable_read<   s    
z%ResultManager.warn_if_repeatable_readc                 C   s   t t| j S N)r   r	   Zdb_for_writemodelr*   r   r   r   connection_for_writeH   s    z"ResultManager.connection_for_writec                 C   s
   t | j S r,   )r   dbr.   r   r   r   r#   K   s    z!ResultManager.connection_for_readc                 C   s2   zt j| j d W S  tk
r,   t j Y S X d S )NZENGINE)r   Z	DATABASESr0   AttributeErrorZDATABASE_ENGINEr.   r   r   r   r!   N   s    zResultManager.current_enginec                 C   s   | j t t| dS )zGet all expired results.)Zdate_done__lt)filterr   r   r*   expiresr   r   r   get_all_expiredT   s    zResultManager.get_all_expiredc              	   C   s.   t j| jd t| |d W 5 Q R X dS )zDelete all expired results.using)ZquerysetN)r
   Zatomicr0   r   r5   r3   r   r   r   delete_expiredX   s    zResultManager.delete_expiredN)
r   r   r   r   r+   r/   r#   r!   r5   r8   r   r   r   r   r    9   s   r    c                	   @   s0   e Zd ZdZdZdd Zeddd	ddZdS )
TaskResultManagerz5Manager for :class:`celery.models.TaskResult` models.Nc                 C   sP   z| j |dW S  | jjk
rJ   | j|kr4|   || _| j|d Y S X dS )au  Get result for task by ``task_id``.

        Keyword Arguments:
        -----------------
            exception_retry_count (int): How many times to retry by
                transaction rollback on exception.  This could
                happen in a race condition if another worker is trying to
                create the same task.  The default is to retry once.

        )task_idNgetr-   ZDoesNotExist_last_idr+   )r*   r:   r   r   r   get_taskc   s    
zTaskResultManager.get_task   r   c                 C   sf   ||||||||	|
||d}|  |j||d\}}|sb| D ]\}}t||| q@|j|d |S )ar  Store the result and status of a task.

        Arguments:
        ---------
            content_type (str): Mime-type of result and meta content.
            content_encoding (str): Type of encoding (e.g. binary/utf-8).
            task_id (str): Id of task.
            periodic_task_name (str): Celery Periodic task name.
            task_name (str): Celery task name.
            task_args (str): Task arguments.
            task_kwargs (str): Task kwargs.
            result (str): The serialized return value of the task,
                or an exception instance raised by the task.
            status (str): Task status.  See :mod:`celery.states` for a list of
                possible status values.
            worker (str): Worker that executes the task.
            using (str): Django database connection to use.
            traceback (str): The traceback string taken at the point of
                exception (only passed if the task failed).
            meta (str): Serialized result meta data (this contains e.g.
                children).

        Keyword Arguments:
        -----------------
            exception_retry_count (int): How many times to retry by
                transaction rollback on exception.  This could
                happen in a race condition if another worker is trying to
                create the same task.  The default is to retry twice.

        )statusresult	tracebackmetacontent_encodingcontent_typeperiodic_task_name	task_name	task_argstask_kwargsworker)r:   defaultsr6   )r7   get_or_createitemssetattrsave)r*   rE   rD   r:   rA   r@   rB   rC   rF   rG   rH   rI   rJ   r7   fieldsobjcreatedkvr   r   r   store_resultv   s(    &
zTaskResultManager.store_result)NNNNNNNN)r   r   r   r   r=   r>   r   rU   r   r   r   r   r9   ^   s               r9   c                   @   s0   e Zd ZdZdZdd Zeddd	ddZdS )
GroupResultManagerz6Manager for :class:`celery.models.GroupResult` models.Nc                 C   sP   z| j |dW S  | jjk
rJ   | j|kr4|   || _| j|d Y S X dS )aw  Get result for group by ``group_id``.

        Keyword Arguments:
        -----------------
            exception_retry_count (int): How many times to retry by
                transaction rollback on exception.  This could
                happen in a race condition if another worker is trying to
                create the same task.  The default is to retry once.

        )group_idNr;   )r*   rW   r   r   r   	get_group   s    
zGroupResultManager.get_groupr?   r   c                 C   sb   |||d}|s| j }| |j||d\}}|s^| D ]\}	}
t||	|
 q:|j| j d |S )N)rA   rD   rE   )rW   rK   r6   )r0   r7   rL   rM   rN   rO   )r*   rE   rD   rW   rA   r7   rP   rQ   rR   rS   rT   r   r   r   store_group_result   s    
z%GroupResultManager.store_group_result)N)r   r   r   r   r=   rX   r   rY   r   r   r   r   rV      s    rV   )r   )r   r&   	functoolsr   	itertoolsr   Zcelery.utils.timer   Zdjango.confr   Z	django.dbr   r   r	   r
   utilsr   r   r(   UserWarningr   r   Managerr    r9   rV   r   r   r   r   <module>   s   
 %S