from queue import Queue class IntervalTaskMaster (): def __init__(self, socketio): self.socketio = socketio self.tasks_by_id = {} self.tasks_id = 0 self.queue = Queue() def start (self): self.socketio.start_background_task(self.background_task) def background_task(self): st = 0 while True: # print (f"IntervalTaskMaster is running with {len(self.tasks_by_id)} pending tasks") # Add any items in the queue while not self.queue.empty(): task_id, callback, time, interval = self.queue.get() print (f"CREATING TASK {task_id} interval:{interval}") self.tasks_by_id[task_id] = Task(task_id, callback, time, interval) remove_intervals = [] for task_id, task in self.tasks_by_id.items(): print (f"servicing task {task_id}") ran_task = task.service(st) if not task.interval and ran_task: remove_intervals.append(task_id) for task_id in remove_intervals: print (f"deleting task {task_id}") del self.tasks_by_id[task_id] st = self.calc_current_sleep_time_ms() # print (f"taskmaster sleeping {st}") self.socketio.sleep(st/1000) def calc_current_sleep_time_ms(self): min_time = None for task in self.tasks_by_id.values(): if min_time == None or task.time < min_time: min_time = task.time if min_time is None: return 1000 else: return min(10000, min_time / 2) def setTimeout (self, callback, time, interval=False): task_id = self.tasks_id self.tasks_id += 1 self.queue.put((task_id, callback, time, interval)) return task_id def clearTimeout (self, task_id): try: del self.tasks_by_id[task_id] return True except KeyError: pass def setInterval(self, callback, time): return self.setTimeout(callback, time, True) def clearInterval(self, task_id): return self.clearTimeout(task_id) class Task (): def __init__(self, task_id, callback, time, interval=False): self.task_id = task_id self.callback = callback self.time = time self.interval = interval self.current_timer = time def service (self, elapsed_time): self.current_timer -= elapsed_time if self.current_timer <= 0: self.current_timer = 0 self.callback() return True