a
    dG2                     @   s  d dl Z d dlZd dlZd dlmZ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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 m!Z!m"Z" e #e$Z%G dd dZ&G dd de&eZ'G dd de&eZ(dddZ)ee*dddZ+dS )    N)UnionList)events)JobSubmissionEventJobExecutionEvent)Job)BaseJobStoreJobLookupErrorConflictingIdError)MemoryJobStore)BaseScheduler)db)transactionIntegrityError)util)	DjangoJobDjangoJobExecution)get_apscheduler_datetimeget_django_internal_datetimec                       sv   e Zd ZdZdZ fddZeedddZee	e
edf dd	d
Zee	e
edf dddZdd Z  ZS )DjangoResultStoreMixinzfMixin class that adds the ability for a JobStore to store job execution results in the Django databaseNc                    s&   t  || | j t_|   d S N)superstart
_schedulerZ_create_lockr   lockregister_event_listeners)self	scheduleralias	__class__ X/var/www/html/django/DPS/env/lib/python3.9/site-packages/django_apscheduler/jobstores.pyr      s    zDjangoResultStoreMixin.start)eventc                 C   s   z|j tjkr,t| j|j|jd tj}n`|j tj	krltj
}d|j d}tj| j|j|jd ||d}n td|j  dtjtj	g dW n( ty   td|j d	 Y d
S 0 |jS )a  
        Create and return new job execution instance in the database when the job is submitted to the scheduler.

        :param event: JobExecutionEvent instance
        :return: DjangoJobExecution ID or None if the job execution could not be logged.
        r   zExecution of job 'z7' skipped: maximum number of running instances reached!	exceptionz-Don't know how to handle JobSubmissionEvent ''. Expected one of ''.Job '8' no longer exists! Skipping logging of job execution...N)coder   EVENT_JOB_SUBMITTEDr   atomic_update_or_creater   job_idZscheduled_run_timesZSENTEVENT_JOB_MAX_INSTANCESZMAX_INSTANCESNotImplementedErrorr   loggerwarningid)clsr#   job_executionstatusr%   r!   r!   r"   handle_submission_event'   s<    

z.DjangoResultStoreMixin.handle_submission_event)r#   returnc                 C   sr   |j tjkr&td|j  dtj dzt| j|j|jtj	}W n( t
yj   td|j d Y dS 0 |jS )z
        Store "successful" job execution status in the database.

        :param event: JobExecutionEvent instance
        :return: DjangoJobExecution ID or None if the job execution could not be logged.
        ,Don't know how to handle JobExecutionEvent 'z'. Expected 'r'   r(   r)   N)r*   r   EVENT_JOB_EXECUTEDr/   r   r,   r   r-   scheduled_run_timeSUCCESSr   r0   r1   r2   )r3   r#   r4   r!   r!   r"   handle_execution_eventU   s&    
z-DjangoResultStoreMixin.handle_execution_eventc                 C   s   z|j tjkr\|jr*t|j}t|j}nd|j d}d}tj| j	|j|j
tj||d}n`|j tjkrtj}d|j d}tj| j	|j|j
||d}n$td|j  d	tjtjtjg d
W n( ty   td|j d Y dS 0 |jS )z
        Store "failed" job execution status in the database.

        :param event: JobExecutionEvent instance
        :return: DjangoJobExecution ID or None if the job execution could not be logged.
        r(   z' raised an error!N)r%   	tracebackzRun time of job 'z' was missed!r$   r8   r&   r'   r)   )r*   r   EVENT_JOB_ERRORr%   strr=   r-   r   r,   r   r:   ERROREVENT_JOB_MISSEDZMISSEDr/   r.   r   r0   r1   r2   )r3   r#   r%   r=   r4   r5   r!   r!   r"   handle_error_eventr   sH    
		
z)DjangoResultStoreMixin.handle_error_eventc                 C   sF   | j | jtjtjB  | j | jtj | j | jtj	tj
B  dS )z
        Register various event listeners.

        See: https://github.com/agronholm/apscheduler/blob/master/docs/modules/events.rst for details on which event
        class is used for each event code.

        N)r   Zadd_listenerr6   r   r+   r.   r<   r9   rB   r>   rA   r   r!   r!   r"   r      s    

z/DjangoResultStoreMixin.register_event_listeners)__name__
__module____qualname____doc__r   r   classmethodr   r6   r   r   intr<   rB   r   __classcell__r!   r!   r   r"   r      s   -4r   c                       s   e Zd ZdZejfed fddZej	e
edef dddZee d	d
dZej	dd Zdd Zej	edddZej	edddZej	e
dddZej	dd Zdd Zdd Zej	dd Zd d! Z  ZS )"DjangoJobStorea5  
    Stores jobs in a Django database. Based on APScheduler's `MongoDBJobStore`.

    See: https://github.com/agronholm/apscheduler/blob/master/apscheduler/jobstores/mongodb.py

    :param int pickle_protocol: pickle protocol level to use (for serialization), defaults to the
           highest available
    )pickle_protocolc                    s   t    || _d S r   )r   __init__rL   )r   rL   r   r!   r"   rM      s    
zDjangoJobStore.__init__N)r-   r7   c                 C   s@   z$t jj|dj}|r | |nd W S  t jy:   Y d S 0 d S N)r2   )r   objectsget	job_state_reconstitute_jobDoesNotExist)r   r-   rQ   r!   r!   r"   
lookup_job   s
    zDjangoJobStore.lookup_job)r7   c                 C   s   t |}| j|dS )N)Znext_run_time__lte)r   	_get_jobs)r   nowdtr!   r!   r"   get_due_jobs   s    zDjangoJobStore.get_due_jobsc                 C   s@   z$t jjddd}t|j| jW S  t jy:   Y d S 0 d S )NF)Znext_run_time__isnullnext_run_time)r   rO   filterZearliestr   rY   r   rS   r   jobr!   r!   r"   get_next_run_time   s    z DjangoJobStore.get_next_run_timec                 C   s   |   }| | |S r   )rU   Z_fix_paused_jobs_sorting)r   jobsr!   r!   r"   get_all_jobs   s    
zDjangoJobStore.get_all_jobs)r\   c              	   C   s   t  f z8tjj|jt|jt	|
 | jdW W  d    S  ty^   t|jY n0 W d    n1 st0    Y  d S )N)r2   rY   rQ   )r   atomicr   rO   creater2   r   rY   pickledumps__getstate__rL   r   r
   r[   r!   r!   r"   add_job   s    
zDjangoJobStore.add_jobc              	   C   s   t  l z<tjj|jd}t|j|_t	|
 | j|_|  W n tjyd   t|jY n0 W d    n1 sz0    Y  d S rN   )r   r`   r   rO   rP   r2   r   rY   rb   rc   rd   rL   rQ   saverS   r	   )r   r\   Zdb_jobr!   r!   r"   
update_job   s    

zDjangoJobStore.update_job)r-   c                 C   s8   zt jj|d  W n t jy2   t|Y n0 d S rN   )r   rO   rP   deleterS   r	   )r   r-   r!   r!   r"   
remove_job  s    zDjangoJobStore.remove_jobc                 C   s   t j   d S r   )r   rO   allrh   rC   r!   r!   r"   remove_all_jobs  s    zDjangoJobStore.remove_all_jobsc                 C   s   t j  d S r   )r   
connectioncloserC   r!   r!   r"   shutdown  s    zDjangoJobStore.shutdownc                 C   s2   t |}tt}|| | j|_| j|_|S r   )rb   loadsAppSchedulerJob__new____setstate__r   _aliasZ_jobstore_alias)r   rQ   r\   r!   r!   r"   rR     s    


z DjangoJobStore._reconstitute_jobc              	   K   s   g }t  }tjjf i |dd}|D ]N\}}z|| | W q( tyt   | j	d| d |
| Y q(0 q(|rtd|  tjj|d  |S )Nr2   rQ   zUnable to restore job 'z'. Removing it...zRemoving failed jobs: )Zid__in)setr   rO   rZ   Zvalues_listappendrR   	ExceptionZ_loggerr%   addr0   r1   rh   )r   filtersr^   Zfailed_job_idsZ
job_statesr-   rQ   r!   r!   r"   rU     s    
zDjangoJobStore._get_jobsc                 C   s   d| j j d| j dS )N<z(pickle_protocol=z)>)r    rD   rL   rC   r!   r!   r"   __repr__6  s    zDjangoJobStore.__repr__)rD   rE   rF   rG   rb   HIGHEST_PROTOCOLrI   rM   r   Zretry_on_db_operational_errorr?   r   rp   rT   r   rX   r]   r_   re   rg   ri   rk   rn   rR   rU   rz   rJ   r!   r!   r   r"   rK      s*   	


	
rK   c                   @   s   e Zd ZdZdS )DjangoMemoryJobStorez
    Adds the DjangoResultStoreMixin to the standard MemoryJobStore so that job executions can be
    logged to the Django database.
    N)rD   rE   rF   rG   r!   r!   r!   r"   r|   :  s   r|   c                 C   s   t dt d S )Nza'register_events' is deprecated since version 0.4.0. Please remove all references from your code.)warningswarnDeprecationWarning)r   Zresult_storager!   r!   r"   register_eventsC  s
    r   )r   r7   c                    s    fdd}|S )a  
    Helper decorator for job registration.

    Automatically fills id parameter to prevent jobs duplication.
    See this comment for explanation: https://github.com/jcass77/django-apscheduler/pull/9#issuecomment-342074372

    Usage example::

        @register_job(scheduler, "interval", seconds=1)
        def dummy_job():
            print("I'm a job!")

    :param scheduler: Scheduler instance
    :param args, kwargs: Params, will be passed to scheduler.add_job method. See :func:`BaseScheduler.add_job`
    c                    sB   t dt d| j d| j  j| g R i  | S )NzThe 'register_job' decorator is deprecated since version 0.5.0. Please use APScheduler's add_job() method or @scheduled_job decorator instead.r2   .)r}   r~   r   
setdefaultrE   rD   re   )funcargskwargsr   r!   r"   wrapper_register_job^  s    z*register_job.<locals>.wrapper_register_jobr!   )r   r   r   r   r!   r   r"   register_jobM  s    r   )N),loggingrb   r}   typingr   r   Zapschedulerr   Zapscheduler.eventsr   r   Zapscheduler.jobr   rp   Zapscheduler.jobstores.baser   r	   r
   Zapscheduler.jobstores.memoryr   Zapscheduler.schedulers.baser   djangor   Z	django.dbr   r   Zdjango_apschedulerr   Zdjango_apscheduler.modelsr   r   Zdjango_apscheduler.utilr   r   	getLoggerrD   r0   r   rK   r|   r   callabler   r!   r!   r!   r"   <module>   s*   
 %|	

