o
    Ti=                     @   s,  d dl mZ d dlmZ d dlZd dlZ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 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 eeZG dd dej Z!G dd dej"Z#eG dd dej$Z%G dd dej Z&eG dd dej$Z'dS )    )	timedelta)sha1N)StringIO)GenericForeignKey)ContentType)models)Q)timezone)python_2_unicode_compatible)InvalidTaskError)app_settings)task_failed)task_rescheduledc                   @   s   e Zd Zdd ZdS )TaskQuerySetc                 C      t j|}| j||jdS )z>
        :return: A Task queryset filtered by creator
        creator_content_typecreator_object_idr   objectsZget_for_modelfilteridselfcreatorcontent_type r   V/var/www/html/evchargy.com/venv/lib/python3.10/site-packages/background_task/models.py
created_by   
   zTaskQuerySet.created_byN)__name__
__module____qualname__r   r   r   r   r   r      s    r   c                   @   sd   e Zd Zdd Zdd ZdddZdd	 Zd
d Zdd Z				dddZ	dddZ
dddZdS )TaskManagerc                 C   s   t | j| jdS )N)using)r   model_dbr   r   r   r   get_queryset)   s   zTaskManager.get_querysetc                 C   s   |   |S N)r(   r   )r   r   r   r   r   r   ,   s   zTaskManager.created_byNc           	      C   s   t  }| |}|r|j|d}|j|d d}dtj}||d}tjrK| 	 
 }| |
 }tj||  }|dkrG|d | }|S |  }|S )N)queue)Zrun_at__lte	failed_atz
{}priorityrun_atr   )r	   nowunlockedr   formatr   Z!BACKGROUND_TASK_PRIORITY_ORDERINGZorder_byZBACKGROUND_TASK_RUN_ASYNCfailedcountlockedZBACKGROUND_TASK_ASYNC_THREADSnone)	r   r*   r-   qsreadyZ_priority_orderingZcurrently_failedZcurrently_lockedr1   r   r   r   find_available/   s$   
zTaskManager.find_availablec                 C   s:   t j}|  }|t|d }td dt|dB }||S )Nseconds)	locked_by)Zlocked_at__ltr   ZBACKGROUND_TASK_MAX_RUN_TIMEr(   r   r   r   )r   r-   max_run_timer4   
expires_atr.   r   r   r   r.   C   
   
zTaskManager.unlockedc                 C   s:   t j}|  }|t|d }tddt|dB }||S )Nr7   F)Zlocked_by__isnull)Zlocked_at__gtr:   )r   r-   r;   r4   r<   r2   r   r   r   r2   J   r=   zTaskManager.lockedc                 C   s   |   }|jddS )z
        `currently_locked - currently_failed` in `find_available` assues that
        tasks marked as failed are also in processing by the running PID.
        FZfailed_at__isnull)r(   r   )r   r4   r   r   r   r0   Q   s   zTaskManager.failedr   Fc                 C   s   |pd}|pi }|du rt  }tj||fdd}d||f }t|d }|r4tjj	|dd
  t|||||||||	pAtj|
d
S )	z
        If `remove_existing_tasks` is True, all unlocked tasks with the identical task hash will be removed.
        The attributes `repeat` and `repeat_until` are not supported at the moment.
        r   NT	sort_keys%s%sutf-8)	task_hashZlocked_at__isnull)
	task_nametask_paramsrC   priorityr,   r*   verbose_namer   repeatrepeat_until)r	   r-   jsondumpsr   encode	hexdigestTaskr   r   deleteNEVER)r   rD   argskwargsr,   rF   r*   rG   r   rH   rI   Zremove_existing_tasksrE   srC   r   r   r   new_taskY   s(   zTaskManager.new_taskc                 C   sT   |pd}|pi }t j||fdd}d||f }t|d }|  }|j|dS )Nr   Tr?   rA   rB   )rC   )rJ   rK   r   rL   rM   r(   r   )r   rD   rQ   rR   rE   rS   rC   r4   r   r   r   get_taskv   s   zTaskManager.get_taskc                 C   s   |  ||| S r)   )rU   rO   )r   rD   rQ   rR   r   r   r   	drop_task      zTaskManager.drop_taskr)   )
NNNr   NNNNNF)NN)r    r!   r"   r(   r   r6   r.   r2   r0   rT   rU   rV   r   r   r   r   r#   '   s    


	r#   c                       s  e Zd ZejdddZe ZejdddZejddddZ	ej
dddZejdd	Zd
Zde Zde Zde Zde ZdZedfedfedfedfedfedffZejeedZejdddZejdddddZej
dddZejddddZejddZejdddddZejddddZejedddej dZ!ej"dddZ#e$ddZ%e& Z'dd  Z(de(_)d!d" Z*de*_)d#d$ Z+d%d& Z,d'd( Z-d)d* Z.d+d, Z/d-d. Z0d/d0 Z1d1d2 Z2d3d4 Z3 fd5d6Z4d7d8 Z5G d9d: d:Z6  Z7S );rN      T
max_lengthdb_index(      rZ   nullblankr   defaultr[   r[   i              ZhourlyZdailyZweeklyzevery 2 weekszevery 4 weeksneverchoicesrb   r_   r`   rZ   r[   r_   r`   r[   r_   r`   r`   @   background_taskr_   r`   Zrelated_nameZ	on_deleter   r   c                 C   0   | j rztt| j d W dS    Y dS dS zB
        Check if the locked_by process is still running.
        r   TFNr9   oskillintr'   r   r   r   locked_by_pid_running      zTask.locked_by_pid_runningc                 C   
   t | jS z9
        Check if the last_error field is empty.
        bool
last_errorr'   r   r   r   	has_error      
zTask.has_errorc                 C   s.   t | j\}}tdd | D }||fS )Nc                 s   s     | ]\}}t ||fV  qd S r)   )str).0kvr   r   r   	<genexpr>   s    zTask.params.<locals>.<genexpr>)rJ   loadsrE   dictitems)r   rQ   rR   r   r   r   params   s   zTask.paramsc                 C   sD   t  }tj|j| jd}|j||d}|r tjj| jdS d S )N)pk)r9   	locked_at)	r	   r-   rN   r   r.   r   r   updateget)r   r9   r-   r.   updatedr   r   r   lock   s   z	Task.lockc                 C   s    t  }t|||d | | S r)   )r   	tracebackprint_exceptiongetvalue)r   typeerrtbfiler   r   r   _extract_error   s   zTask._extract_errorc                 C   s   |  j d7  _ |   d S )N   )attemptssaver'   r   r   r   increment_attempts   s   zTask.increment_attemptsc                 C   s   t j}| j|kS r)   )r   ZBACKGROUND_TASK_MAX_ATTEMPTSr   )r   Zmax_attemptsr   r   r   has_reached_max_attempts   s   
zTask.has_reached_max_attemptsc                 C   s   | j | jkS r)   )rH   rP   r'   r   r   r   is_repeating_task   s   zTask.is_repeating_taskc                 C   s   |  |||| _|   |  st|tr4t | _t	
d|  |  }tj| j| j|d |   dS tj}tt| j| d d}t | | _t	
d| || j tj| j| d d| _d| _|   dS )z
        Set a new time to run the task in the future, or create a CompletedTask and delete the Task
        if it has reached the maximum of allowed attempts
        zMarking task %s as failed
)sendertask_idcompleted_task   r7   z(Rescheduling task %s for %s later at %s
)r   taskN)r   r~   r   r   
isinstancer   r	   r-   r+   loggerwarningcreate_completed_taskr   send	__class__r   rO   r   Z"BACKGROUND_TASK_BACKOFF_MULTIPLIERr   rw   r   r,   r   r9   r   r   )r   r   r   r   	completedZbackoff_multiplierbackoffr   r   r   
reschedule   s$   
zTask.reschedulec                 C   sR   t | j| j| j| jt | j| j| j	| j
| j| j| j| j| j| jd}|  |S )zK
        Returns a new CompletedTask instance with the same values
        )rD   rE   rC   rF   r,   r*   r   r+   r~   r9   r   rG   r   rH   rI   )CompletedTaskrD   rE   rC   rF   r	   r-   r*   r   r+   r~   r9   r   rG   r   rH   rI   r   )r   r   r   r   r   r     s&   zTask.create_completed_taskc                 C   s   |   sdS | jr| jt krdS |  \}}| jt| jd }|t k r5|t| jd7 }|t k s't j	| j
|||| j| j| j| j| j| jd
}|  |S )zp
        :return: A new Task with an offset of self.repeat, or None if the self.repeat_until is reached
        Nr7   )
rD   rQ   rR   r,   rF   r*   rG   r   rH   rI   )r   rI   r	   r-   r   r,   r   rH   r#   rT   rD   rF   r*   rG   r   r   )r   rQ   rR   Z
new_run_atrT   r   r   r   create_repetition#  s.   zTask.create_repetitionc                    s"   | j pd | _ tt| j|i |S r)   )r9   superrN   r   )r   argkwr   r   r   r   B  s   z	Task.savec                 C   s   d | jp| jS )Nz{})r/   rG   rD   r'   r   r   r   __str__G  rW   zTask.__str__c                   @   s   e Zd ZdZdS )z	Task.Metarp   N)r    r!   r"   Zdb_tabler   r   r   r   MetaJ  s    r   )8r    r!   r"   r   	CharFieldrD   	TextFieldrE   rC   rG   IntegerFieldrF   DateTimeFieldr,   ZHOURLYZDAILYZWEEKLYZEVERY_2_WEEKSZEVERY_4_WEEKSrP   REPEAT_CHOICESBigIntegerFieldrH   rI   r*   r   r+   r~   r9   r   
ForeignKeyr   CASCADEr   PositiveIntegerFieldr   r   r   r#   r   rx   booleanr   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r   r   r   r   rN      sn    
rN   c                   @   s(   e Zd Zdd ZdddZdddZdS )	CompletedTaskQuerySetc                 C   r   )zG
        :return: A CompletedTask queryset filtered by creator
        r   r   r   r   r   r   r   S  r   z CompletedTaskQuerySet.created_byNc                 C   ,   | j dd}|rt | }|j |d}|S )z
        :param within: A timedelta object
        :return: A queryset of CompletedTasks that failed within the given timeframe (e.g. less than 1h ago)
        Fr>   )Zfailed_at__gtr   r	   r-   r   Zwithinr4   Z
time_limitr   r   r   r0   ]  s   zCompletedTaskQuerySet.failedc                 C   r   )z
        :param within: A timedelta object
        :return: A queryset of CompletedTasks that completed successfully within the given timeframe
        (e.g. less than 1h ago)
        Tr>   )Z
run_at__gtr   r   r   r   r   	succeededj  s   zCompletedTaskQuerySet.succeededr)   )r    r!   r"   r   r0   r   r   r   r   r   r   Q  s    

r   c                   @   s2  e Zd ZejdddZe ZejdddZejddddZ	ej
dddZejdd	Zejejejd
ZejdddZejdddddZej
dddZejddddZejddZejdddddZejddddZejedddejdZejdddZe ddZ!e"# Z$dd Z%de%_&dd Z'de'_&dd Z(dS )r   rX   TrY   r\   r]   r^   r   ra   rc   ri   rk   rl   rm   rn   ro   Zcompleted_background_taskrq   r   r   c                 C   rr   rs   rt   r'   r   r   r   rx     ry   z#CompletedTask.locked_by_pid_runningc                 C   rz   r{   r|   r'   r   r   r   r     r   zCompletedTask.has_errorc                 C   s   d | jp| j| jS )Nz{} - {})r/   rG   rD   r,   r'   r   r   r   r     s   
zCompletedTask.__str__N))r    r!   r"   r   r   rD   r   rE   rC   rG   r   rF   r   r,   r   rN   r   rP   rH   rI   r*   r   r+   r~   r9   r   r   r   r   r   r   r   r   r   r   Z
as_managerr   rx   r   r   r   r   r   r   r   r   y  s>    
r   )(datetimer   hashlibr   rJ   loggingru   r   ior   Z"django.contrib.contenttypes.fieldsr   Z"django.contrib.contenttypes.modelsr   Z	django.dbr   Zdjango.db.modelsr   Zdjango.utilsr	   sixr
   Zbackground_task.exceptionsr   Zbackground_task.settingsr   Zbackground_task.signalsr   r   	getLoggerr    r   ZQuerySetr   Managerr#   ZModelrN   r   r   r   r   r   r   <module>   s4   
\ N(