<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _main_loop(self):
 """ Run jobs until must_stop returns True """

        fetch_priorities_delay = timedelta(seconds=self.fetch_priorities_delay)
        fetch_delayed_delay = timedelta(seconds=self.fetch_delayed_delay)

        while not self.must_stop():
            self.set_status('waiting')

            if self.last_update_keys + fetch_priorities_delay < datetime.utcnow():
                self.update_keys()

            if self.last_requeue_delayed + fetch_delayed_delay < datetime.utcnow():
                self.requeue_delayed_jobs()

            try:
                queue_and_job = self.wait_for_job()
                if queue_and_job is None:
                    # timeout for blpop
                    continue
                queue, job = queue_and_job
            except Exception as e:
                self.log('Unable to get job: %s\n%s'
                    % (str(e), traceback.format_exc()), level='error')
            else:
                self.num_loops += 1
                try:
                    identifier = 'pk:%s' % job.pk.get()
                except Exception as e:
                    identifier = '??'
                try:
                    self.set_status('running')
                    identifier, status = job.hmget('identifier', 'status')
                     # some cache, don't count on it on subclasses
                    job._cached_identifier = identifier
                    job._cached_status = status
                    queue._cached_name = queue.name.hget()

                    if status == STATUSES.DELAYED:
                        self.job_delayed(job, queue)
                    elif status != STATUSES.WAITING:
                        self.job_skipped(job, queue)
                    else:
                        try:
                            self.job_started(job, queue)
                            job_result = self.callback(job, queue)
                        except Exception as e:
                            trace = None
                            if self.save_tracebacks:
                                trace = traceback.format_exc()
                            self.job_error(job, queue, e, trace)
                        else:
                            job._cached_status = job.status.hget()
                            if job._cached_status == STATUSES.DELAYED:
                                self.job_delayed(job, queue)
                            elif job._cached_status == STATUSES.CANCELED:
                                self.job_skipped(job, queue)
                            else:
                                self.job_success(job, queue, job_result)
                except Exception as e:
                    self.log('[%s] unexpected error: %s\n%s'
                        % (identifier, str(e), traceback.format_exc()), level='error')
                    try:
                        queue.errors.rpush(job.ident)
                    except Exception as e:
                        self.log('[%s] unable to add the error in the queue: %s\n%s'
                            % (identifier, str(e), traceback.format_exc()), level='error')