def start(self, method=None, method_args=None): """ Start this job. """ with TransactionLock(self.table, '%s.start' % self): logger.info("%s: Job starting" % self) self.refresh() if self.is_follower: logger.debug("%s: Shadowing master job %s" % (self, self.master)) if self.master.status == Job.COMPLETE: self.mark_complete() elif self.master.status == Job.ERROR: self.mark_error(self.master.message, self.master.exception) return if method is None: method = self.table.queryclass.run # Create an task to do the work task = Task(self, Callable(method, method_args)) logger.debug("%s: Created task %s" % (self, task)) task.start()
def check_children(self, objlock=None): # get a lock on the child that's called us to ensure any status # from its transaction will be seen. if objlock is None: objlock = self with TransactionLock(objlock, '%s.checking_children' % self): running_children = Job.objects.filter( parent=self, status__in=[Job.NEW, Job.RUNNING]) logger.info("%s: %d running children" % (self, len(running_children))) logger.debug("%s: all children: %s" % (self, ';'.join('%s - %s' % (j.status, j) for j in Job.objects.filter(parent=self)))) if len(running_children) > 0: # Not done yet, do nothing return # Grab a lock on this job to make sure only one caller # gets the callback with TransactionLock(self, '%s.check_children' % self): # Now that we have the lock, make sure we have latest Job # details self.refresh() logger.info("%s: checking callback %s" % (self, self.callback)) if self.callback is None: # Some other child got to it first return # Save off the callback, we'll call it outside the transaction callback = self.callback # Clear the callback while still in lockdown self.callback = None self.save() t = Task(self, callback=callback) logger.info("%s: Created callback task %s" % (self, t)) t.start()
def check_children(self, objlock=None): # get a lock on the child that's called us to ensure any status # from its transaction will be seen. if objlock is None: objlock = self with TransactionLock(objlock, '%s.checking_children' % self): running_children = Job.objects.filter( parent=self, status__in=[Job.NEW, Job.RUNNING]) logger.info("%s: %d running children" % (self, len(running_children))) logger.debug( "%s: all children: %s" % (self, ';'.join('%s - %s' % (j.status, j) for j in Job.objects.filter(parent=self)))) if len(running_children) > 0: # Not done yet, do nothing return # Grab a lock on this job to make sure only one caller # gets the callback with TransactionLock(self, '%s.check_children' % self): # Now that we have the lock, make sure we have latest Job # details self.refresh() logger.info("%s: checking callback %s" % (self, self.callback)) if self.callback is None: # Some other child got to it first return # Save off the callback, we'll call it outside the transaction callback = self.callback # Clear the callback while still in lockdown self.callback = None self.save() t = Task(self, callback=callback) logger.info("%s: Created callback task %s" % (self, t)) t.start()
def mark_done(self, status, **kwargs): with TransactionLock(self, '%s.mark_done' % self): self.refresh() old_status = self.status if old_status in (Job.COMPLETE, Job.ERROR): # Status was already set to a done state, avoid # double action and return now return self.status = status for k, v in kwargs.iteritems(): setattr(self, k, v) self.save() # On status change, do more... self.mark_progress(status=status, progress=100) if not self.is_follower: # Notify followers of this job followers = Job.objects.filter(master=self) for follower in followers: if self.status == Job.COMPLETE: kwargs['actual_criteria'] = self.actual_criteria follower.mark_complete(status=status, **kwargs) elif self.status == Job.ERROR: follower.mark_done(status=status, **kwargs) if self.parent: logger.info("%s: Asking parent %s to check children" % (self, self.parent)) t = Task(self.parent, callback=Callable(self.parent.check_children, called_kwargs={'objlock': self}), generic=True) logger.info("%s: Created check_children task %s" % (self, t)) t.start() return True