async def __retry_tasks(self, tasks: List[WorkerTaskInProgress]) -> None: for task in tasks: if task.retry_counter > 0: # todo: maybe it still in the queue of the worker? # reschedule await self.__add_task(task.task, task.retry_counter - 1) else: log.warning(f"Too many retried executing task {task.task.id}. Give up.") self.outstanding_tasks.pop(task.task.id, None) self.work_count[task.worker.worker_id] = self.work_count[task.worker.worker_id] - 1 set_future_result(task.task.callback, TimeoutError("Could not finish the task."))
async def __acknowledge_task(self, worker_id: WorkerId, task_id: TaskId, result: Optional[Json]) -> None: # remove task from internal list in_progress = self.outstanding_tasks.get(task_id, None) if in_progress: if in_progress.worker.worker_id == worker_id: self.outstanding_tasks.pop(task_id, None) self.work_count[worker_id] = self.work_count[worker_id] - 1 set_future_result(in_progress.task.callback, result) # todo: remove task from database else: log.info(f"Got result for task {task_id} from wrong worker {worker_id}. outdated?")
async def __error_task(self, worker_id: WorkerId, task_id: TaskId, message: str) -> None: log.warning(f"Task {task_id} yielded an error: {message}") in_progress = self.outstanding_tasks.get(task_id, None) if in_progress: if in_progress.worker.worker_id == worker_id: self.outstanding_tasks.pop(task_id, None) self.work_count[worker_id] = self.work_count[worker_id] - 1 set_future_result(in_progress.task.callback, AttributeError(f"Error executing task: {message}")) # todo: remove task from database else: log.info(f"Got error for task {task_id} from wrong worker {worker_id}. outdated?")
async def check_outdated_unassigned_tasks(self) -> None: now = utc() outstanding = [ip for ip in self.outstanding_tasks.values() if ip.deadline < now] not_started_outdated = [ns for ns in self.unassigned_tasks.values() if ns.deadline < now] async with self.lock: await self.__retry_tasks(outstanding) for ns in not_started_outdated: log.info(f"No worker for task: {ns.task.id}. Give up.") set_future_result(ns.task.callback, Exception(f"No worker for task: {ns.task.name}")) self.unassigned_tasks.pop(ns.task.id, None) # unassigned_task now only holds valid tasks for ns in list(self.unassigned_tasks.values()): if await self.__add_task(ns.task, ns.retry_counter): self.unassigned_tasks.pop(ns.task.id, None)