code: def ax_client_data_attacher(
      queue: "Queue[Tuple[int, TEvaluationOutcome]]",
      stop_event: Event,
      ax_client: AxClient,
      lock: Lock,
  ) -> None:
      """Thread-safe method for attaching evaluation outcomes to the AxClient from the
      outcome queue. If the AxClient's lock is acquired all data in the outcome queue
      is attached at once, then the lock released. Stops when the event is set.
      """
  
      while not stop_event.is_set():
          if not queue.empty():
              with lock:
                  while not queue.empty():
                      trial_index, raw_data = queue.get()
  
                      ax_client.complete_trial(
                          trial_index=trial_index,
                          raw_data=raw_data,
                      )
  
                      queue.task_done()
  
          time.sleep(IDLE_SLEEP_SEC)
  
file_path: Ax/ax/service/interactive_loop.py
imports: import time
  from logging import Logger
  from queue import Queue
  from threading import Event, Lock, Thread
  from typing import Any, Callable, Dict, Optional, Tuple
  from ax.core.types import TEvaluationOutcome, TParameterization
  from ax.exceptions.core import DataRequiredError
  from ax.exceptions.generation_strategy import MaxParallelismReachedException
  from ax.service.ax_client import AxClient
  from ax.utils.common.logger import get_logger
label_desc: Use image node_id 4 for calling a global function with example usage: ax_client_data_attacher(queue, stop_event, ax_client, lock) without return types