class_docstr: A thread that batches requests to our file prepare API.
  
  Any number of threads may call prepare_async() in parallel. The PrepareBatcher thread
  will batch requests up and send them all to the backend at once.
code: def _thread_body(self) -> None:
      while True:
          finish, batch = gather_batch(
              request_queue=self._request_queue,
              batch_time=self._batch_time,
              inter_event_time=self._inter_event_time,
              max_batch_size=self._max_batch_size,
          )
          if batch:
              batch_response = self._prepare_batch(batch)
              # send responses
              for prepare_request in batch:
                  name = prepare_request.file_spec["name"]
                  response_file = batch_response[name]
                  response = prepare_response(response_file)
                  if isinstance(
                      prepare_request.response_channel, queue.Queue
                  ):
                      prepare_request.response_channel.put(response)
                  else:
                      loop, future = prepare_request.response_channel
                      loop.call_soon_threadsafe(
                          future.set_result, response
                      )
          if finish:
              break
  
imports: import asyncio
  import functools
  import queue
  import threading
  import time
  from typing import TYPE_CHECKING, Callable, Dict, List, Mapping, NamedTuple, Optional, Sequence, Tuple, Union
label_desc: Use image node_id 2 for calling the StepPrepare obj's underlying member method code with example usage: obj._thread_body() without return types