
    Wwg2                     H   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 jF                  e$      Z% G d d      Z& G d de&e      Z' G d de&e      Z(ddZ)dede*fdZ+y)    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                        e Zd ZdZdZ fdZedefd       Zede	de
edf   fd       Zede	de
edf   fd       Zd	 Z xZS )
DjangoResultStoreMixinzfMixin class that adds the ability for a JobStore to store job execution results in the Django databaseNc                     t         |   ||       | j                  j                         t        _        | j                          y N)superstart
_scheduler_create_lockr   lockregister_event_listeners)self	scheduleralias	__class__s      S/var/www/horilla/myenv/lib/python3.12/site-packages/django_apscheduler/jobstores.pyr   zDjangoResultStoreMixin.start   s5    i' '+oo&B&B&D#%%'    eventc                    	 |j                   t        j                  k(  rSt        j                  | j
                  |j                  |j                  d   t        j                        }|j                  S |j                   t        j                  k(  rgt        j                  }d|j                   d}t        j                  | j
                  |j                  |j                  d   ||      }|j                  S t        d|j                    dt        j                  t        j                  g d      # t        $ r& t        j                  d|j                   d	       Y y
w xY w)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_idscheduled_run_timesSENTEVENT_JOB_MAX_INSTANCESMAX_INSTANCESNotImplementedErrorr   loggerwarningid)clsr&   job_executionstatusr)   s        r$   handle_submission_eventz.DjangoResultStoreMixin.handle_submission_event'   sM   "	zzV777 2 J JHHLL--a0&++	!B 5 v===+99 ) 7) * 
 !3 J JHHLL--a0'!$  *CEJJ< P & : :F<Z<Z[\\^`   	NN~%]^ 		s   A$D0 2A8D0 6:D0 0,EEreturnc                    |j                   t        j                  k7  r*t        d|j                    dt        j                   d      	 t	        j
                  | j                  |j                  |j                  t        j                        }|j                  S # t        $ r& t        j                  d|j                   d       Y yw xY w)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_EXECUTEDr6   r   r0   r   r1   scheduled_run_timeSUCCESSr   r7   r8   r9   )r:   r&   r;   s      r$   handle_execution_eventz-DjangoResultStoreMixin.handle_execution_eventU   s     ::222%>uzzl K--.b2 
	.FF(("**	M   	NN~%]^ 		s   	AB ,CCc                 n   	 |j                   t        j                  k(  r|j                  r+t	        |j                        }t	        |j
                        }nd|j                   d}d}t        j                  | j                  |j                  |j                  t        j                  ||      }|j&                  S |j                   t        j                  k(  rdt        j                  }d|j                   d}t        j                  | j                  |j                  |j                  ||      }|j&                  S t        d|j                    d	t        j                  t        j                  t        j                  g d
      # t         $ r& t"        j%                  d|j                   d       Y yw xY w)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(   r@   r*   r+   r-   )r.   r   EVENT_JOB_ERRORr)   strrF   r1   r   r0   r   rB   ERROREVENT_JOB_MISSEDMISSEDr6   r4   r   r7   r8   r9   )r:   r&   r)   rF   r;   r<   s         r$   handle_error_eventz)DjangoResultStoreMixin.handle_error_eventr   s   )	zzV333?? #EOO 4I #EOO 4I"'~5G HI $I 2 J JHHLL,,&,,''!B 1 v666+22/~]K	 2 J JHHLL,,'!&  *B5::, O & 6 68V8VX^XoXopqqsu   	NN~%]^ 		s    B-F ;A5F <A	F ,F43F4c                    | j                   j                  | j                  t        j                  t        j
                  z         | j                   j                  | j                  t        j                         | j                   j                  | j                  t        j                  t        j                  z         y)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   add_listenerr=   r   r/   r4   rD   rA   rL   rG   rJ   r    s    r$   r   z/DjangoResultStoreMixin.register_event_listeners   s     	$$((&&)G)GG	

 	$$'')B)B	
 	$$##""V%<%<<	
r%   )__name__
__module____qualname____doc__r   r   classmethodr   r=   r   r   intrD   rL   r   __classcell__r#   s   @r$   r   r      s    pD( + ,> +  + Z  +<  sDyAQ    8 2 '8 2 U39=M 2  2 h
r%   r   c                       e Zd ZdZej
                  fdef fdZej                  de
dedef   fd       Zdee   fdZej                  d	        Zd
 Zej                  defd       Zej                  defd       Zej                  de
fd       Zej                  d        Zd Zd Zej                  d        Zd Z x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                 0    t         |           || _        y r   )r   __init__rZ   )r    rZ   r#   s     r$   r\   zDjangoJobStore.__init__   s    .r%   r1   r>   Nc                     	 t         j                  j                  |      j                  }|r| j	                  |      S d S # t         j
                  $ r Y y w xY wN)r9   )r   objectsget	job_state_reconstitute_jobDoesNotExist)r    r1   ra   s      r$   
lookup_jobzDjangoJobStore.lookup_job   sV    	!))---8BBI8A4)))4KtK%% 		s   <A A AAc                 <    t        |      }| j                  |      S )N)next_run_time__lte)r   	_get_jobs)r    nowdts      r$   get_due_jobszDjangoJobStore.get_due_jobs   s    )#.~~~44r%   c                     	 t         j                  j                  d      j                  d      }t	        |j
                  | j                        S # t         j                  $ r Y y w xY w)NF)next_run_time__isnullnext_run_time)r   r_   filterearliestr   rm   r   rc   r    jobs     r$   get_next_run_timez DjangoJobStore.get_next_run_time   s_    	##***GPPC ,C,=,=tOO%% 		s   AA A'&A'c                 H    | j                         }| j                  |       |S r   )rg   _fix_paused_jobs_sorting)r    jobss     r$   get_all_jobszDjangoJobStore.get_all_jobs   s!    ~~%%d+r%   rq   c           	      r   t        j                         5  	 t        j                  j	                  |j
                  t        |j                        t        j                  |j                         | j                              cd d d        S # t        $ r t        |j
                        w xY w# 1 sw Y   y xY w)N)r9   rm   ra   )r   atomicr   r_   creater9   r   rm   pickledumps__getstate__rZ   r   r   rp   s     r$   add_jobzDjangoJobStore.add_job   s    ! 	11 ((//vv">s?P?P"Q$ll3+;+;+=t?S?ST 0 	1 	1 " 1(001	1 	1s   B-A*BB**B--B6c                    t        j                         5  	 t        j                  j	                         j                  |j                        }t        |j                        |_        t        j                  |j                         | j                        |_        |j                          	 d d d        y # t        j                  $ r t!        |j                        w xY w# 1 sw Y   y xY wr^   )r   rx   r   r_   select_for_updater`   r9   r   rm   rz   r{   r|   rZ   ra   saverc   r
   )r    rq   db_jobs      r$   
update_jobzDjangoJobStore.update_job   s     ! 	--"**<<>BBcffBM'CCDUDU'V$#)<<$$&(<(<$  	- 	- )) -$SVV,,-	- 	-s   C"BB66)CC""C+c                    t        j                         5  	 t        j                  j	                         j                  |      j                          	 d d d        y # t        j                  $ r t        |      w xY w# 1 sw Y   y xY wr^   )	r   rx   r   r_   r   r`   deleterc   r
   )r    r1   s     r$   
remove_jobzDjangoJobStore.remove_job  sx    ! 	--!!33599V9DKKM	- 	- )) -$V,,-	- 	-s   A?<AA<<A??Bc                 \    t         j                  j                         j                          y r   )r   r_   allr   rO   s    r$   remove_all_jobszDjangoJobStore.remove_all_jobs  s     	&&(r%   c                 @    t         j                  j                          y r   )r   
connectioncloserO   s    r$   shutdownzDjangoJobStore.shutdown  s    
r%   c                     t        j                  |      }t        j                  t              }|j	                  |       | j
                  |_        | j                  |_        |S r   )rz   loadsAppSchedulerJob__new____setstate__r   _alias_jobstore_alias)r    ra   rq   s      r$   rb   z DjangoJobStore._reconstitute_job  sJ    LL+	%%o6#"kk
r%   c                    g }t               }t        j                  j                  di |j	                  dd      }|D ]&  \  }}	 |j                  | j                  |             ( |rFt        j                  d|        t        j                  j                  |      j                          |S # t        $ r3 | j                  j                  d| d       |j                  |       Y w xY w)Nr9   ra   zUnable to restore job 'z'. Removing it...zRemoving failed jobs: )id__in )setr   r_   rn   values_listappendrb   	Exception_loggerr)   addr7   r8   r   )r    filtersru   failed_job_ids
job_statesr1   ra   s          r$   rg   zDjangoJobStore._get_jobs   s    &&--88DDT;W
!+ 	+FI+D229=>	+ NN3N3CDE$$N$;BBD  +&&-fX5FG ""6*	+s    B119C-,C-c                 P    d| j                   j                   d| j                   dS )N<z(pickle_protocol=z)>)r#   rP   rZ   rO   s    r$   __repr__zDjangoJobStore.__repr__7  s+    4>>**++<T=Q=Q<RRTUUr%   )rP   rQ   rR   rS   rz   HIGHEST_PROTOCOLrU   r\   r   retry_on_db_operational_errorrH   r   r   rd   r   rj   rr   rv   r}   r   r   r   r   rb   rg   r   rV   rW   s   @r$   rY   rY      s(    /5.E.E / / 
'' t_/D)E  (54#8 5 
'' ( 
''	1? 	1 (	1 
''-o - (-  
''- - (- 
'') () 
'' (,Vr%   rY   c                       e Zd ZdZy)DjangoMemoryJobStorez
    Adds the DjangoResultStoreMixin to the standard MemoryJobStore so that job executions can be
    logged to the Django database.
    N)rP   rQ   rR   rS   r   r%   r$   r   r   ;  s    
 	r%   r   c                 8    t        j                  dt               y )Nza'register_events' is deprecated since version 0.4.0. Please remove all references from your code.)warningswarnDeprecationWarning)r!   result_storages     r$   register_eventsr   D  s     MMk 	r%   r!   r>   c                       f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                     t        j                  dt               j                  d| j                   d| j
                           j                  | g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.r9   .)r   r   r   
setdefaultrQ   rP   r}   )funcargskwargsr!   s    r$   wrapper_register_jobz*register_job.<locals>.wrapper_register_job_  s\    3	
 	$4??"31T]]O DE	$000r%   r   )r!   r   r   r   s   ``` r$   register_jobr   N  s    "  r%   r   ),loggingrz   r   typingr   r   apschedulerr   apscheduler.eventsr   r   apscheduler.jobr   r   apscheduler.jobstores.baser	   r
   r   apscheduler.jobstores.memoryr   apscheduler.schedulers.baser   djangor   	django.dbr   r   django_apschedulerr   django_apscheduler.modelsr   r   django_apscheduler.utilr   r   	getLoggerrP   r7   r   rY   r   r   callabler   r   r%   r$   <module>r      s         D 2 W W 7 5  1 # C
 
		8	$a
 a
HzV+\ zVz	1> 		 M  x  r%   