1616from celery .execute import send_task
1717from celery .schedules import schedule
1818from celery .messaging import establish_connection
19+ from celery .utils import instantiate
1920from celery .utils .info import humanize_seconds
2021
2122
@@ -84,6 +85,12 @@ def is_due(self):
8485 """See :meth:`celery.task.base.PeriodicTask.is_due`."""
8586 return self .schedule .is_due (self .last_run_at )
8687
88+ def __repr__ (self ):
89+ return "<Entry: %s(*%s, **%s) {%s}>" % (self .name ,
90+ self .args ,
91+ self .kwargs ,
92+ self .schedule )
93+
8794
8895class Scheduler (UserDict ):
8996 """Scheduler for periodic tasks.
@@ -105,6 +112,7 @@ class Scheduler(UserDict):
105112 Maximum time to sleep between re-checking the schedule.
106113
107114 """
115+ Entry = ScheduleEntry
108116
109117 def __init__ (self , schedule = None , logger = None ,
110118 max_interval = None ):
@@ -117,6 +125,9 @@ def __init__(self, schedule=None, logger=None,
117125 self .cleanup ()
118126 self .setup_schedule ()
119127
128+ def iterentries (self ):
129+ return self .schedule .itervalues ()
130+
120131 def tick (self ):
121132 """Run a tick, that is one iteration of the scheduler.
122133 Executes all due tasks."""
@@ -126,7 +137,7 @@ def tick(self):
126137 remaining_times = []
127138 connection = establish_connection ()
128139 try :
129- for entry in self .schedule . values ():
140+ for entry in self .iterentries ():
130141 is_due , next_time_to_run = entry .is_due ()
131142 if is_due :
132143 debug ("Scheduler: Sending due task %s" % entry .name )
@@ -145,12 +156,17 @@ def tick(self):
145156
146157 return min (remaining_times + [self .max_interval ])
147158
148- def apply_async (self , entry , ** kwargs ):
159+ def reserve (self , entry ):
160+ new_entry = self .schedule [entry .name ] = entry .next ()
161+ return new_entry
149162
163+ def apply_async (self , entry , ** kwargs ):
150164 # Update timestamps and run counts before we actually execute,
151165 # so we have that done if an exception is raised (doesn't schedule
152166 # forever.)
153- entry = self .schedule [entry .name ] = entry .next ()
167+ entry = self .reserve (entry )
168+
169+ print ("APPLYING: %s" % (entry , ))
154170
155171 try :
156172 result = send_task (entry .name , entry .args , entry .kwargs ,
@@ -168,15 +184,15 @@ def maybe_schedule(self, s, relative=False):
168184 return s
169185
170186 def setup_schedule (self ):
171- self .schedule = self .dict_to_entries (conf .CELERYBEAT_SCHEDULE )
187+ self .data = self .dict_to_entries (conf .CELERYBEAT_SCHEDULE )
172188
173189 def dict_to_entries (self , dict_ ):
174190 entries = {}
175191 for name , entry in dict_ .items ():
176192 relative = entry .pop ("relative" , None )
177193 entry ["schedule" ] = self .maybe_schedule (entry ["schedule" ],
178194 relative )
179- entries [name ] = ScheduleEntry (** entry )
195+ entries [name ] = self . Entry (** entry )
180196 return entries
181197
182198 def cleanup (self ):
@@ -194,9 +210,11 @@ class ClockService(object):
194210 def __init__ (self , logger = None ,
195211 max_interval = conf .CELERYBEAT_MAX_LOOP_INTERVAL ,
196212 schedule = conf .CELERYBEAT_SCHEDULE ,
197- schedule_filename = conf .CELERYBEAT_SCHEDULE_FILENAME ):
213+ schedule_filename = conf .CELERYBEAT_SCHEDULE_FILENAME ,
214+ scheduler_cls = None ):
198215 self .logger = logger or log .get_default_logger ()
199216 self .max_interval = max_interval
217+ self .scheduler_cls = scheduler_cls or self .scheduler_cls
200218 self ._shutdown = threading .Event ()
201219 self ._stopped = threading .Event ()
202220 self .schedule = schedule
@@ -239,9 +257,10 @@ def stop(self, wait=False):
239257 @property
240258 def scheduler (self ):
241259 if self ._scheduler is None :
242- self ._scheduler = self .scheduler_cls (schedule = self .schedule ,
243- logger = self .logger ,
244- max_interval = self .max_interval )
260+ self ._scheduler = instantiate (self .scheduler_cls ,
261+ schedule = self .schedule ,
262+ logger = self .logger ,
263+ max_interval = self .max_interval )
245264 return self ._scheduler
246265
247266
0 commit comments