code: def run_task(
      task_func: Callable,
      task_pool: str,
      query: dict = {},
      force_release: bool = False,
      before_status: str = TaskManager.STATUS_WAITING,
      after_status: str = TaskManager.STATUS_DONE,
      **kwargs,
  ):
      r"""
      While the task pool is not empty (has WAITING tasks), use task_func to fetch and run tasks in task_pool
  
      After running this method, here are 4 situations (before_status -> after_status):
  
          STATUS_WAITING -> STATUS_DONE: use task["def"] as `task_func` param, it means that the task has not been started
  
          STATUS_WAITING -> STATUS_PART_DONE: use task["def"] as `task_func` param
  
          STATUS_PART_DONE -> STATUS_PART_DONE: use task["res"] as `task_func` param, it means that the task has been started but not completed
  
          STATUS_PART_DONE -> STATUS_DONE: use task["res"] as `task_func` param
  
      Parameters
      ----------
      task_func : Callable
          def (task_def, \**kwargs) -> <res which will be committed>
  
          the function to run the task
      task_pool : str
          the name of the task pool (Collection in MongoDB)
      query: dict
          will use this dict to query task_pool when fetching task
      force_release : bool
          will the program force to release the resource
      before_status : str:
          the tasks in before_status will be fetched and trained. Can be STATUS_WAITING, STATUS_PART_DONE.
      after_status : str:
          the tasks after trained will become after_status. Can be STATUS_WAITING, STATUS_PART_DONE.
      kwargs
          the params for `task_func`
      """
      tm = TaskManager(task_pool)
  
      ever_run = False
  
      while True:
          with tm.safe_fetch_task(
              status=before_status, query=query
          ) as task:
              if task is None:
                  break
              get_module_logger("run_task").info(task["def"])
              # when fetching `WAITING` task, use task["def"] to train
              if before_status == TaskManager.STATUS_WAITING:
                  param = task["def"]
              # when fetching `PART_DONE` task, use task["res"] to train because the middle result has been saved to task["res"]
              elif before_status == TaskManager.STATUS_PART_DONE:
                  param = task["res"]
              else:
                  raise ValueError(
                      "The fetched task must be `STATUS_WAITING` or `STATUS_PART_DONE`!"
                  )
              if force_release:
                  with concurrent.futures.ProcessPoolExecutor(
                      max_workers=1
                  ) as executor:
                      res = executor.submit(
                          task_func, param, **kwargs
                      ).result()
              else:
                  res = task_func(param, **kwargs)
              tm.commit_task_res(task, res, status=after_status)
              ever_run = True
  
      return ever_run
  
imports: import concurrent
  import pickle
  import time
  from contextlib import contextmanager
  from typing import Callable, List
  import fire
  import pymongo
  from bson.binary import Binary
  from bson.objectid import ObjectId
  from pymongo.errors import InvalidDocument
  from qlib import auto_init, get_module_logger
  from tqdm.cli import tqdm
  from .utils import get_mongodb
  from ...config import C
label_desc: Use image node_id 1 for calling a global function with example usage: run_task(task_func, task_pool, query, force_release, before_status, after_status) and returns: ever_run