o
    ͜iK                     @   s  d Z ddlZddlZddlZddlmZ zddlmZ W n ey+   ddl	mZ Y nw ddl
mZmZ ddl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mZ ddlmZmZmZmZm Z  ddl!m"Z" ddl#m$Z$m%Z% ddl&m'Z'm(Z( ddl)m*Z*m+Z+ ddl,m-Z- ddl.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4 ddl5m6Z6m7Z7m8Z8 dZ9dZ:dZ;ee<Z=e=j>e=j?e=j@Z>Z?Z@G dd deZAG dd deZBdS )zBeat Scheduler Implementation.    N)Finalize)ZoneInfo)current_app	schedules)ScheduleEntry	Scheduler)
get_logger)maybe_make_aware)settings)ObjectDoesNotExist)close_old_connectionstransaction)CaseFIntegerFieldQWhen)Cast)DatabaseErrorInterfaceError)	safe_reprsafe_str)dumpsloads   )clocked)ClockedScheduleCrontabScheduleIntervalSchedulePeriodicTaskPeriodicTasksSolarSchedule)NEVER_CHECK_TIMEOUT	aware_nownow   i,  z;Cannot add entry %r to database schedule: %r. Contents: %r
c                   @   s   e Zd ZdZejedfejedfej	e
dfeedffZg dZddd	Zd
d Zdd Zdd Zdd ZeZdd Zedd ZedddZe	dddZe		d ddZdd ZdS )!
ModelEntryz(Scheduler entry taken from database row.crontabintervalsolarr   )last_run_attotal_run_count
no_changesNc              
   C   st  |pt  | _|j| _|j| _z|j| _W n |jy+   td| j | 	| Y nw zt
|jp2d| _t
|jp:d| _W n ty] } ztd| j| | 	| W Y d}~nd}~ww i | _dD ]}t||}|du roqc|| j|< qct|ddrt|d| jd< t
|jpd}|j|d	< || jd
< |j| _|| _|js|jp|  |_| jjr|jtjdd |_|j| _dS )zInitialize the model entry.z4Disabling schedule %s that was removed from databasez[]z{}z:Removing schedule %s for argument deseralization error: %rN)queueexchangerouting_keypriorityexpires_expiresperiodic_task_nameheadersi*  )days)r   _get_current_objectappnametaskscheduleDoesNotExistloggererror_disabler   argskwargs
ValueError	exceptionoptionsgetattrr4   r+   modelr*   date_changed_default_now
start_timedatetime	timedelta)selfrE   r7   excoptionvaluer4    rO   X/var/www/html/philips/venv/lib/python3.10/site-packages/django_celery_beat/schedulers.py__init__7   sV   



zModelEntry.__init__c                 C   s   d|_ d|_|  d S )NTF)r,   enabledsave)rK   rE   rO   rO   rP   r>   k   s   zModelEntry._disablec                 C   s&  | j js
tddS | j jd ur@|  }ttddr t|  }|| j jk r@|j	}| j 
|}|| }t| }td|S | j jd ur\|  }|| j jkr\| | j  tdtS | j jr| j jr| j jdkrd| j _d| j _d| j _| j   tdtS | jj}t| j|}| j|S )NFg      @DJANGO_CELERY_BEAT_TZ_AWARETr   )rE   rR   r   
schedstaterH   rG   rD   r
   r	   tzinfodue_start_timemathceiltotal_secondsr2   r>   r"   one_offr+   r,   rS   r7   timezoner*   
astimezoner:   is_due)rK   r$   
current_tzrH   time_remainingdelaytzlast_run_at_in_tzrO   rO   rP   r^   p   s6   
zModelEntry.is_duec                 C   s.   t tddrtj| jj}|S tj }|S )NrT   T)rD   r
   rI   r$   r7   r\   utcnow)rK   r$   rO   rO   rP   rG      s
   
zModelEntry._default_nowc                 C   s0   |   | j_| j jd7  _d| j_| | jS )Nr   T)rG   rE   r*   r+   r,   	__class__rK   rO   rO   rP   __next__   s   zModelEntry.__next__c                 C   sD   t | jjj| jjd}| jD ]}t||t| j| q|  d S )N)pk)	typerE   _default_managergetrh   save_fieldssetattrrD   rS   )rK   objfieldrO   rO   rP   rS      s   
zModelEntry.savec                 C   sT   | j D ]\}}}t|}t||r!||}|  ||f  S qtd|d)NzCannot convert schedule type z	 to model)model_schedulesr   maybe_schedule
isinstancefrom_schedulerS   rA   )clsr:   schedule_type
model_typemodel_fieldmodel_schedulerO   rO   rP   to_model_schedule   s   



zModelEntry.to_model_schedulec                 K   s,   t jj|| jdi |d\}}| ||dS )N)r8   defaultsr7   rO   )r   rj   update_or_create_unpack_fields)rt   r8   r7   entryrn   createdrO   rO   rP   
from_entry   s   
zModelEntry.from_entryc           
      K   sb   dd | j D }| |\}}	|||	< |j|ft|pg t|p i d| jdi |p*i  |S )Nc                 S   s   i | ]\}}}|d qS NrO   ).0_rw   rO   rO   rP   
<dictcomp>       z-ModelEntry._unpack_fields.<locals>.<dictcomp>)r?   r@   rO   )rp   ry   updater   _unpack_options)
rt   r:   r?   r@   relativerC   r~   entry_schedulesrx   rw   rO   rO   rP   r}      s   

zModelEntry._unpack_fieldsc                 K   s   ||||t |pi |dS )N)r-   r.   r/   r0   r4   expire_seconds)r   )rt   r-   r.   r/   r0   r4   r   r@   rO   rO   rP   r      s   
zModelEntry._unpack_optionsc                 C   s(   d t| j| jt| jt| j| jS )Nz!<ModelEntry: {} {}(*{}, **{}) {}>)formatr   r8   r9   r   r?   r@   r:   rf   rO   rO   rP   __repr__   s   zModelEntry.__repr__r   )NNNN)NNNNNN)__name__
__module____qualname____doc__r   r'   r   r:   r   r)   r!   r   r   rp   rl   rQ   r>   r^   rG   rg   nextrS   classmethodry   r   r}   r   r   rO   rO   rO   rP   r&   ,   s6    



4,		

r&   c                       s   e Zd ZdZeZeZeZ	dZ
dZdZdZdZdd Zdd Zd	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Z fdd Zed!d" Z  ZS )#DatabaseSchedulerzDatabase-backed Beat Scheduler.NTFc                 O   sP   t  | _tj| g|R i | t| | jdd| _|dp$| jj	j
p$t| _dS )z"Initialize the database scheduler.r%   )exitprioritymax_intervalN)set_dirtyr   rQ   r   sync	_finalizerk   r7   confbeat_max_loop_intervalDEFAULT_MAX_INTERVALr   rK   r?   r@   rO   rO   rP   rQ      s   
zDatabaseScheduler.__init__c                 C   s    |  | j | | jjj d S r   )install_default_entriesr:   update_from_dictr7   r   beat_schedulerf   rO   rO   rP   setup_schedule  s   z DatabaseScheduler.setup_schedulec              	   C   sJ   t d i }|  D ]}z| j|| jd||j< W q
 ty"   Y q
w |S )Nz-DatabaseScheduler: Fetching database scheduler{   )debugenabled_modelsEntryr7   r8   rA   )rK   srE   rO   rO   rP   all_as_schedule  s   z!DatabaseScheduler.all_as_schedulec                 C   s   t |  S )zReturn list of enabled periodic tasks.

        Allows overriding how the list of periodic tasks is fetched without
        duplicating the filtering/querying logic.
        )listenabled_models_qsrf   rO   rO   rP   r     s   z DatabaseScheduler.enabled_modelsc                 C   s@   t  tjtd }td|d}|  }||B }| jj 	|S )N)secondsF)clocked__isnullclocked__clocked_time__gt)
r$   rI   rJ   SCHEDULE_SYNC_MAX_INTERVALr   _get_crontab_exclude_queryModelobjectsrR   exclude)rK   next_schedule_syncexclude_clock_tasks_queryexclude_cron_tasks_queryexclude_queryrO   rO   rP   r     s   z#DatabaseScheduler.enabled_models_qsc                    s   t  }|jfddtddD }|dg7 }d}tjj|d}|jtdt t	 fd	d 
 D d
tdid}|j|djddd}tddt|d@ }|S )a$  
        Build a query to exclude crontab tasks based on their hour value,
        adjusted for timezone differences relative to the server.

        This creates an annotation for each crontab task that represents the
        server-equivalent hour, then filters on that annotation.
        c                    s   g | ]} | d  qS )   rO   )r   offset)server_hourrO   rP   
<listcomp>8  r   z@DatabaseScheduler._get_crontab_exclude_query.<locals>.<listcomp>      z^\d+$)hour__regexhourc                    s.   g | ]}t |td  | d d dqS )hour_intr   )r\   then)r   r   _get_timezone_offset)r   timezone_namerf   rO   rP   r   N  s    	defaultr   )r   r   )server_hour__inidTflatF)crontab__isnull)crontab__id__in)r#   r   ranger   r   filterannotater   r   r   _get_unique_timezone_namesr   r   values_listr   )rK   server_timehours_to_includenumeric_hour_patternnumeric_hour_tasksannotated_tasksexcluded_hour_task_idsr   rO   )rK   r   rP   r   *  s:   




	
z,DatabaseScheduler._get_crontab_exclude_queryc                 C   s   t jjddd S )z?Get a list of all unique timezone names used in CrontabScheduler\   Tr   )r   r   r   distinctrf   rO   rO   rP   r   j  s
   z,DatabaseScheduler._get_unique_timezone_namesc           
      C   s   t  }t|jtr|j}ntt|j}t|tr|j}t|}tdddddd}|j|d}|j|d}| 	 | 	  }t
|d }	|	S )z
        Args:
            timezone_name: The name of the timezone or a ZoneInfo object

        Returns:
            int: The hour offset
        i  r      r   )rV   i  )r#   rr   rV   r   strkeyrI   replace	utcoffsetrZ   int)
rK   r   r   	server_tz	target_tzfixed_dtdt1dt2offset_secondsoffset_hoursrO   rO   rP   r   p  s   	
z&DatabaseScheduler._get_timezone_offsetc              
   C   s   zt   zt  W n
 tjy   Y nw | j| j }}W n& ty8 } zt	d| W Y d }~dS d }~w t
yE   td Y dS w z|rW||rN|n|kr]W || _dS W || _dS W || _dS || _w )NzDatabase gave error: %rFzYDatabaseScheduler: InterfaceError in schedule_changed(), waiting to retry in next call...T)r   r   commitTransactionManagementError_last_timestampChangeslast_changer   r<   rB   r   warning)rK   lasttsrL   rO   rO   rP   schedule_changed  s:   
z"DatabaseScheduler.schedule_changedc                 C   s   t |}| j|j |S r   )r   r   addr8   )rK   r~   	new_entryrO   rO   rP   reserve  s   zDatabaseScheduler.reservec              
   C   s  t tjr
td t }t }zsz0t  | jr@| j }z| j	| 
  || W n tttfy<   || Y nw | jsW n$ tyY } zt d| W Y d }~nd }~w tye   td Y nw W |  j|O  _d S W |  j|O  _d S W |  j|O  _d S |  j|O  _w )NzWriting entries...zDatabase error while sync: %rzMDatabaseScheduler: InterfaceError in sync(), waiting to retry in next call...)r<   isEnabledForloggingDEBUGr   r   r   r   pop	_schedulerS   r   KeyError	TypeErrorr   r   rB   r   r   )rK   _tried_failedr8   rL   rO   rO   rP   r     s<   
"zDatabaseScheduler.syncc                 C   s   i }|  D ]5\}}z| jj|fd| ji|}|jjr |||< W q ty; } ztt	||| W Y d }~qd }~ww | j
| d S )Nr7   )itemsr   r   r7   rE   rR   	Exceptionr<   rB   ADD_ENTRY_ERRORr:   r   )rK   mappingr   r8   entry_fieldsr~   rL   rO   rO   rP   r     s    z"DatabaseScheduler.update_from_dictc              	   C   s>   i }| j jjr|ddtdddddid | | d S )Nzcelery.backend_cleanup04*r   i  )r9   r:   rC   )r7   r   result_expires
setdefaultr   r'   r   )rK   dataentriesrO   rO   rP   r     s   
z)DatabaseScheduler.install_default_entriesc                    s"   | j rd| _ dS t j|i |S )NF)_heap_invalidatedsuperschedules_equalr   re   rO   rP   r    s   z!DatabaseScheduler.schedules_equalc                 C   s   d }}t j  }| jrtd d }}d| _|| _n|  r(td d}|| _|s>|| j  }|tkr>td d}|| _|rg| 	  | 
 | _|sQg | _d| _ttjrgtdddd	 | j D  | jS )
NFzDatabaseScheduler: initial readTz$DatabaseScheduler: Schedule changed.z4DatabaseScheduler: Forcing full sync after 5 minuteszCurrent schedule:
%s
c                 s   s    | ]}t |V  qd S r   )repr)r   r~   rO   rO   rP   	<genexpr>  s    
z-DatabaseScheduler.schedule.<locals>.<genexpr>)rI   r$   _initial_readr   _last_full_syncr   inforZ   r   r   r   r   _heapr  r<   r   r   r   joinvalues)rK   initialr   current_timetime_since_last_syncrO   rO   rP   r:     s@   


zDatabaseScheduler.schedule) r   r   r   r   r&   r   r   r   r    r   r   r   r
  r  r  rQ   r   r   r   r   r   r   r   r   r   r   r   r   r  propertyr:   __classcell__rO   rO   r  rP   r      s4    

@$r   )Cr   rI   r   rX   multiprocessing.utilr   zoneinfor   ImportErrorbackports.zoneinfoceleryr   r   celery.beatr   r   celery.utils.logr   celery.utils.timer	   django.confr
   django.core.exceptionsr   	django.dbr   r   django.db.modelsr   r   r   r   r   django.db.models.functionsr   django.db.utilsr   r   kombu.utils.encodingr   r   kombu.utils.jsonr   r   clockedscheduler   modelsr   r   r   r   r    r!   utilsr"   r#   r$   r   r   r   r   r<   r   r  r   r&   r   rO   rO   rO   rP   <module>   sB      A