def _start_a_job(self): """Either starts a waiting job and returns a 3-tuple of (job, sz_key, future), or finds no waiting job and returns a 3-tuple of (None, None, None). """ with transaction(self._model_access): (job, sz_key) = self._get_next_job() if job is None: return (None, None, None) job.started_at = utc_now() if sz_key: sz_key.active_job_id = job.id self._update_job(job, sz_key) def fxn(): """Future closure.""" if job.name not in self._job_handlers: raise KeyError("Bad job name") self._job_handlers[job.name](job.payload) future = self._executor.submit(fxn) return (job, sz_key, future)
def _schedule_jobs(self): # Don't schedule jobs if the frequency is None if self._schedule_frequency is None: return None # Only perform a diff check if jobs have been scheduled if self._last_job_scheduling is not None: ts = utc_now().timestamp() # If the last scheduling timestamp plus the frequency is greater than the # current timestamp, it is not yet time to schedule. if self._last_job_scheduling + self._schedule_frequency > ts: return None with transaction(self._model_access): cr, _ = self._model_access.callproc("schedule_jobs", []) job_count = self._model_access.get_scalar(cr) self._last_job_scheduling = utc_now().timestamp() return job_count
def _finished_job(self, job, sz_key, future): """Marks the job as complete. :param job: the Job instance :param sz_key: the SerializationKey instance :param future: the Future instance that handled the job """ error_message = exception_to_message(future.exception()) job.update(completed_at=utc_now(), error_message=error_message) if sz_key: sz_key.active_job_id = None with transaction(self._model_access): self._update_job(job, sz_key)
def to_now(_): """Returns the current timestamp, with a utc timezone.""" return date.utc_now()
def _get_ts(self, seconds_in_future=0): return utc_now() + timedelta(seconds=seconds_in_future)