code: def _non_blocking_wrapper(self, method, *args, **kwargs):
      
  
      exceptions = []
  
      def task_run(task):
        try:
          getattr(task, method)(*args, **kwargs)
        except Exception as e:
          exceptions.append(e)
  
      threads = [threading.Thread(name=f'task_{method}_{i}',
                                  target=task_run, args=[t])
                 for i, t in enumerate(self.tasks)]
      for thread in threads:
        thread.start()
      for thread in threads:
        thread.join()
      if exceptions:
        raise exceptions[0]
docs: Runs given method on every task in the job. Blocks until all tasks finish. Propagates exception from first
      failed task.