def abort(self): """ Abort Job - Only one thread will do it - All other threads will return - Simply sets status to TERMINATED - Scheduler should understand that it shouldn't reschedule it """ with self._abort_lock: if self._mark_for_abortion.is_set(): # All other threads will avoid cancellation Logger.info("Job already cancelled: {}".format(self.job_id)) return # Only one thread will cancel the job if self.status in [JobStatusEnum.TERMINATED, JobStatusEnum.FAILED]: Logger.warning("Job is already cancelled") return if self.status in [JobStatusEnum.RUNNING]: Logger.warning( "Job is already running - cannot abort it until finished") return # Only when job can be cancelled, we will raise a flag self._mark_for_abortion.set() Logger.info("Abort a Job: {}".format(self.job_id)) self.status = JobStatusEnum.TERMINATED
def run(self): """ Worker function - Runs until _keep_running event is down - Takes a job from the job queue: Blocks for _TIMEOUT seconds - Runs the function - Prints """ Logger.info("Worker {} .. Start".format(self.name)) while self._keep_running.is_set(): try: func, args, kwargs = self._task_queue.get( block=True, timeout=ThreadPool.Worker._TIMEOUT) try: func(*args, **kwargs) except Exception as e: Logger.warning(e) finally: self._task_queue.task_done() except Empty: # DO nothing when found no job to do # The wait is part of get job from queue pass Logger.info("Worker {} .. Done".format(self.name))
def run_job(self): if self._mark_for_abortion.is_set(): return self.abort() self._iterations += 1 self.status = JobStatusEnum.RUNNING self._last_run_started = datetime.now() try: Logger.info("Running job: {}, #{}".format(self, self._iterations)) rc = self._job_func() self._last_run_ended = datetime.now() self.status = JobStatusEnum.SUCCEEDED self._schedule_next_run() except Exception as e: self.status = JobStatusEnum.FAILED Logger.warning(str(e)) Logger.warning(traceback.format_exc()) rc = str(e) return rc