def submitJob(self, job, runTimes): if self.__instances[job.state["id"]] >= job.state["maxInstances"]: schedulerLogger.warning( "Execution of job '{}' skipped: maximum number of running instances reached ({})" .format(job, job.state["maxInstances"])) else: def callback(future): self.__instances[job.state["id"]] -= 1 if self.__instances[job.state["id"]] == 0: del self.__instances[job.state["id"]] graceTime = timedelta(seconds=job.state["misfireGraceTime"]) tasks = [] for runTime in runTimes: difference = datetime.utcnow() - runTime if difference > graceTime: schedulerLogger.warning( "Run time of job '{}' was missed by '{}'".format( job, difference)) continue tasks.append(job.state["func"](*job.state["args"], **job.state["kwargs"])) if tasks: tasks = asyncio.gather(*tasks) tasks.add_done_callback(callback) self.__instances[job.state["id"]] += 1 schedulerLogger.info( "Submit job '{}' successfully.".format(job))
async def resume(self): if self.state == stateStopped: schedulerLogger.error("Scheduler not running.") raise RuntimeError("Scheduler not running.") elif self.state == statePaused: self.state = stateRunning tornadoScheduler.__ioLoop.add_callback(self.__wakeup) schedulerLogger.info("Resumed scheduler job processing.")
async def __removeJob(self, jobId, jobStoreName="temporary"): if self.state == stateStopped: for index, (job, job_store_name) in enumerate(self.__pendingJobs): if job.state["id"] == jobId and job_store_name == jobStoreName: del self.__pendingJobs[index] break else: await self.__jobStores[jobStoreName].removeJob(jobId) schedulerLogger.info("Removed job {}".format(jobId))
async def shutdown(self): if self.state == stateStopped: schedulerLogger.error("Scheduler not running.") raise RuntimeError("Scheduler not running.") if self.__timeout is not None: tornadoScheduler.__ioLoop.remove_timeout(self.__timeout) self.__timeout = None self.state = stateStopped schedulerLogger.info("Scheduler has been shutdown.")
async def pause(self): if self.state == stateStopped: schedulerLogger.error("Scheduler not running.") raise RuntimeError("Scheduler not running.") elif self.state == stateRunning: if self.__timeout is not None: tornadoScheduler.__ioLoop.remove_timeout(self.__timeout) self.__timeout = None self.state = statePaused schedulerLogger.info("Paused scheduler job processing.")
async def __wakeup(self): if self.state != stateRunning: schedulerLogger.info( "Scheduler is not running -- not processing jobs.") return if self.__timeout is not None: tornadoScheduler.__ioLoop.remove_timeout(self.__timeout) self.__timeout = None nextWakeupTime = await self.__processJobs() if nextWakeupTime is not None: self.__timeout = tornadoScheduler.__ioLoop.add_timeout( nextWakeupTime - datetime.utcnow(), self.__wakeup)
def start(self, paused=False): if self.state != stateStopped: schedulerLogger.error("Scheduler already running.") raise RuntimeError("Scheduler already running.") for jobStoreName in self.jobStoreNames: self.__jobStores[jobStoreName].start() for job, jobStoreName in self.__pendingJobs: self.__jobStores[jobStoreName].syncAddJob(job) del self.__pendingJobs[:] self.state = statePaused if paused else stateRunning schedulerLogger.info("Scheduler started.") if not paused: tornadoScheduler.__ioLoop.add_callback(self.__wakeup)
async def addJob(self, jobId, func, args=None, kwargs=None, description="undefined", jobStoreName="temporary", triggerName="date", misfireGraceTime=60, coalesce=True, maxInstances=1, nextRunTime="undefined", **triggerArgs): trigger = createTrigger(triggerName, triggerArgs) jobKwargs = { "id": jobId, "func": func, "args": tuple(args) if args is not None else (), "kwargs": kwargs if kwargs is not None else {}, "description": description, "trigger": trigger, "misfireGraceTime": misfireGraceTime, "coalesce": coalesce, "maxInstances": maxInstances, "nextRunTime": nextRunTime if nextRunTime != "undefined" else trigger.getNextFireTime(None, datetime.utcnow()) } job = job(**jobKwargs) if self.state == stateStopped: self.__pendingJobs.append((job, jobStoreName)) schedulerLogger.info( "Adding job tentatively -- it will be properly scheduled when the scheduler starts." ) else: await self.__jobStores[jobStoreName].addJob(job) schedulerLogger.info("Added job '{}' to table '{}'.".format( job, self.__jobStores[jobStoreName].tableName)) if self.state == stateRunning: tornadoScheduler.__ioLoop.add_callback(self.__wakeup)