Пример #1
0
    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()
Пример #2
0
    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()
Пример #3
0
    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()
Пример #4
0
    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
Пример #5
0
    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
Пример #6
0
    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()
Пример #7
0
    def get_master(self, handle):
        """Return Job object for master or None if no valid jobs found."""
        master = None

        # Find jobs with the same handle but with no master,
        # these are candidate master jobs.  Lock these rows
        # so we can ensure they don't get deleted until
        # we have a chance to touch it and refcount the selected
        # master below
        candidates = (Job.objects.select_for_update().filter(
            status__in=[Job.NEW, Job.QUEUED, Job.RUNNING, Job.COMPLETE],
            handle=handle,
            master=None).order_by('created'))

        if candidates:
            master_jobs = Task.validate_jobs(jobs=candidates, delete=True)
            master = master_jobs[0] if master_jobs else None

        return master
Пример #8
0
    def get_master(self, handle):
        """Return Job object for master or None if no valid jobs found."""
        master = None

        # Find jobs with the same handle but with no master,
        # these are candidate master jobs.  Lock these rows
        # so we can ensure they don't get deleted until
        # we have a chance to touch it and refcount the selected
        # master below
        candidates = (Job.objects
                      .select_for_update()
                      .filter(status__in=[Job.NEW,
                                          Job.QUEUED,
                                          Job.RUNNING,
                                          Job.COMPLETE],
                              handle=handle,
                              master=None)
                      .order_by('created'))

        if candidates:
            master_jobs = Task.validate_jobs(jobs=candidates, delete=True)
            master = master_jobs[0] if master_jobs else None

        return master